一 : R3调试器流程
基础知识:
异常处理发生的处理大概过程如下:
1)系统查看产生异常的进程是否正在被调试,是则向调试器发送Exception_Debug_Event事件;
2)如果进程没有被调试或调试不处理此异常,那么系统检查异常所处的线程,并在这个线程的环境中查看FS:[0]来确定是否安装了SEH异常处理回调函数,有则调用;
3)回调函数尝试处理此异常,可以正确处理则修正错误并将返回值设置为”ExceptionContinueExceution”,系统结束整个查找过程;
4)如果回调函数返回ExceptionContinueSearch,(说明无法处理, 继续搜索),则根据SHE链中的下一个回调函数去尝试执行,直到0xFFFFFFFF(SEH结束)还未有处理,退出异常处理链;
5)系统再次检测进程是否正在被调试,如果被调试则再发一次给调试器处理;
6)调试器不处理或没有调试器,系统检查是否有安装筛选器回调函数,有安装则调用处理,返回值时,系统默认的异常处理根据返回值做相应的动作;
7)没有处理则直接调用系统默认的异常处理函数处理。(终止进程,调错误提示)
R3调试器的一般流程
在写R3调试时,CreateProcess创建进程时,dwCreationFlags参数使用 DEBUG_ONLY_THIS_PROCESS| DEBUG_PROCESS调试方式创建调试进程, 这样在调试循环结构中通过 WaitForDebugEvent函数捕获异常,根据需要对异常事件作处理(是已处理继续执行还是未处理抛出)。
1.0 CreateProcess //创建调试进程
参数creation flags 选择debug类型
2.0 调试循环结构
for(;;)
{ //出自MSDN
WaitForDebugEvent(&DebugEv, INFINITE);
switch (DebugEv.dwDebugEventCode) //调试异常代码(异常的类别)
{
case EXCEPTION_DEBUG_EVENT: //调试异常事件
switch (DebugEv.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION: //访问异常
case EXCEPTION_BREAKPOINT: //断点异常
case EXCEPTION_DATATYPE_MISALIGNMENT:
case EXCEPTION_SINGLE_STEP: //单步
case DBG_CONTROL_C:
}
case CREATE_THREAD_DEBUG_EVENT: // 线程创建
case CREATE_PROCESS_DEBUG_EVENT: //进程创建
case EXIT_THREAD_DEBUG_EVENT:
case EXIT_PROCESS_DEBUG_EVENT:
case LOAD_DLL_DEBUG_EVENT: //载入DLL
case UNLOAD_DLL_DEBUG_EVENT: //卸载DLL
case OUTPUT_DEBUG_STRING_EVENT:
}
ContinueDebugEvent(DebugEv.dwProcessId,
DebugEv.dwThreadId, dwContinueStatus);
}
主要部分:
CREATE_PROCESS_DEBUG_EVENT:创建进程时再异常地址下断点,即OEP处
LOAD_DLL_DEBUG_EVENT:在载入DLL可以获取模块地址信息,以便解析函数
EXCEPTION_ACCESS_VIOLATION: 内存断点处理部分,根据异常异常类型地址判断是否命中
EXCEPTION_BREAKPOINT:软中断(0xCC)处理部分,注意系统的int3即第一次不处理
EXCEPTION_SINGLE_STEP: 最重要且复杂的部分,处理单步,恢复之前异常的有效性等。
大概的流程为:
那么WaitForDebugEvent中获取Debug_Event调试事件信息是从哪里获取的?
备注:
关于R3下调试的实现,可以参考科锐学员发的相关帖子,这里引用 "超然" 写的调试器供参考!
http://www.kanxue.com/showthread.php?t=111876