继续上次关于罗云彬WIN32汇编程序设计的笔记
第13章, 过程控制, 改进后的内存补丁程序...
程序从start开始执行, 调用GetStartupInfo函数初始化stStartUp变量.
调用CreateProcess函数创建一个进程
invoke CreateProcess, offset szExecFilename, NULL, NULL, NULL,\
NULL, DEBUG_PROCESS or DEBUG_ONLY_THIS_PROCESS, NULL, \
NULL, offset stStartUp, offset stProcInfo
新创建的进程从szExecFilaname开始执行…
DEBUG_PROCESS or DEBUG_ONLY_THIS_PROCESS : 表示只调试这个进程
(offset stProcInfo : [out] Pointer to a PROCESS_INFORMATION structure that receives identification information about the new process.)
如果创建失败, 则调用Messagebox函数输出 “无法装载执行文件”, 结束当前进程…
设置一个while循环, 进入调试..
调用WaitForDebugEvent函数
invoke WaitForDebugEvent, addr stDE, INFINITE
"{}"内是MSND上的解释说明, 自己看吧, 呵呵
{ This function waits for a debugging event to occur in a process being debugged.
BOOL WaitForDebugEvent(
LPDEBUG_EVENT lpDebugEvent,
DWORD dwMilliseconds
);
lpDebugEvent : [in] Pointer to a DEBUG_EVENT structure that is filled with information about the debugging event.
dwMilliseconds : [in] Number of milliseconds to wait for a debugging event.
If this parameter is 0, the function tests for a debugging event and returns immediately.
If the parameter is set to INFINITE, the function does not return until a debugging event has occurred.
Return Values : Nonzero indicates success.
Remarks
Only the thread that created the process being debugged can call WaitForDebugEvent.
There is a 64 (MAXIMUM_WAIT_OBJECTS) thread limit for WaitForDebugEvent, which means that the maximum threads that can be debugged per-process is 64.
}
{ This structure describes a debugging event.
typedef struct _DEBUG_EVENT {
DWORD dwDebugEventCode;
DWORD dwProcessId;
DWORD dwThreadId;
union {
EXCEPTION_DEBUG_INFO Exception;
CREATE_THREAD_DEBUG_INFO CreateThread;
CREATE_PROCESS_DEBUG_INFO CreateProcessInfo;
EXIT_THREAD_DEBUG_INFO ExitThread;
EXIT_PROCESS_DEBUG_INFO ExitProcess;
LOAD_DLL_DEBUG_INFO LoadDll;
UNLOAD_DLL_DEBUG_INFO UnloadDll;
OUTPUT_DEBUG_STRING_INFO DebugString;
RIP_INFO RipInfo;
} u;
} DEBUG_EVENT;
dwDebugEventCode : Debugging event code that identifies the type of debugging event.
EXCEPTION_DEBUG_EVENT : Reports an exception debugging event.; The value of u.Exception specifies an EXCEPTION_DEBUG_INFO structure.
CREATE_THREAD_DEBUG_EVENT : Reports a create-thread debugging event.; The value of u.CreateThread specifies a CREATE_THREAD_DEBUG_INFO structure.
CREATE_PROCESS_DEBUG_EVENT : Reports a create-process debugging event. The value of u.CreateProcessInfo specifies a CREATE_PROCESS_DEBUG_INFO structure.
dwProcessId : Identifier of the process where the debugging event occurred. A debugger uses this value to locate the debugger's per-process structure. These values are not necessarily small integers that can be used as table indexes.
dwThreadId : Identifier of the thread where the debugging event occurred. A debugger uses this value to locate the debugger's per-thread structure. These values are not necessarily small integers that can be used as table indexes.
U : Additional information relating to the debugging event. This union assumes the type and value appropriate to the type of debugging event, as described in the dwDebugEventCode member.
}
调用WaitForDebugEvent等待调试事件的发生, 当stDE.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT的时候退出while循环..
.if stDE.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT, 即创建进程
事件, 调用WriteProcessMemory函数
invoke WriteProcessMemory, stProcInfo.hProcess, BREAK_POINT1, addr dbInt3, 1, NULL
在进程的BREAK_POINT1地址处写入dbInt3(0cch), 一个字节…设置一个断点
if stDE.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
调试进程的时候遇到异常,
{ EXCEPTION_DEBUG_INFO: This structure contains exception information that can be used by a debugger.
typedef struct _EXCEPTION_DEBUG_INFO {
EXCEPTION_RECORD ExceptionRecord;
DWORD dwFirstChance;
} EXCEPTION_DEBUG_INFO;
ExceptionRecord : Contains an EXCEPTION_RECORD structure with information specific to the exception. This includes the following:
EXCEPTION_RECORD : This structure describes an exception.
typedef struct _EXCEPTION_RECORD {
DWORD ExceptionCode;
DWORD ExceptionFlags;
struct _EXCEPTION_RECORD* ExceptionRecord;
PVOID ExceptionAddress;
DWORD NumberParameters;
DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD;
ExceptionCode : The reason the exception occurred. This is the code generated by a hardware exception or the code specified in the RaiseException function for a software-generated exception.
The following table shows the values likely to occur due to common programming errors.
EXCEPTION_BREAKPOINT : A breakpoint was encountered.
EXCEPTION_SINGLE_STEP : A trace trap or other single-instruction mechanism signaled that one instruction has been executed.
}
调用mov stCT.ContextFlags, CONTEXT_FULL 将环境变量存入stCT.ContextFlags中,
接着调用GetThreadContext函数 即
invoke GetThreadContext, stProcInfo.hThread, addr stCT
{ This function retrieves the context of the specified thread.
BOOL GetThreadContext(
HANDLE hThread,
LPCONTEXT lpContext
);
hThread : [in] Handle to the thread whose context is to be retrieved.
lpContext : [in] Pointer to the CONTEXT structure that receives the appropriate context of the specified thread.
Return Values: Nonzero indicates success.
}
返回被调试线程的环境变量, 存入stCT…
当指令寄存器的值为BREAK_POINT1 + 1即断点的下一条指令, 将指令寄存器减一回到断
点处, 调用WriteProcessMemory函数恢复断点处的代码, 进行内存补丁. 接着调用
SetThreadContext函数设置线程环境变量, 具体代码如下:
.if stCT.regEip == BREAK_POINT1 + 1
dec stCT.regEip
invoke WriteProcessMemory, stProcInfo.hProcess, BREAK_POINT1, addr dbOldByte, 1, NULL
or stCT.regFlag, 100h
invoke SetThreadContext, stProcInfo.hThread, addr stCT
.endif
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.elseif stDE.u.Exception.pExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP
单步执行, 当指令寄存器的值到达BREAK_POINT2的时候, 调用WriteProcessMemory函数
dbPatched写入进程的PATCH_POSITION位置, 即两个NOP指令…
具体执行如下:
.elseif stDE.u.Exception.pExceptionRecord.ExceptionCode== EXCEPTION_SINGLE_STEP
mov stCT.ContextFlags, CONTEXT_FULL
invoke GetThreadContext, stProcInfo.hThread, addr stCT
.if stCT.regEip == BREAK_POINT2
invoke WriteProcessMemory, stProcInfo.hProcess, PATCH_POSITION, addr dbPatched, sizeof dbPatched, NULL
.else or stCT.regFlag, 100h
invoke SetThreadContext, stProcInfo.hThread, addr stCT
.endif
.endif
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
接着调用ContinueDebugEvent函数继续调试..直到 调试到
EXIT_PROCESS_DEBUG_EVENT事件
{ContinueDebugEvent : This function enables a debugger to continue a thread that previously reported a debugging event.
BOOL ContinueDebugEvent(
DWORD dwProcessId,
DWORD dwThreadId,
DWORD dwContinueStatus
);
dwProcessId : [in] Specifies the handle to the process to continue.
dwThreadId : [in] Specifies the handle to the thread to continue. The combination of process identifier and thread identifier must identify a thread that has previously reported a debugging event.
dwContinueStatus: [in] Specifies how to continue the thread that reported the debugging event. If the DBG_CONTINUE flag is specified for this parameter and the thread specified by the dwThreadId parameter previously reported an EXCEPTION_DEBUG_EVENT debugging event, the function stops all exception processing and continues the thread. For any other debugging event, this flag continues the thread.
}
invoke ContinueDebugEvent, stDE.dwProcessId, stDE.dwThreadId, DBG_CONTINUE