[异常分发]一:R3调试器流程
一 : 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