INT 3 中断调试处理流程

Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html

INT 3 中断调试处理流程

一、调试器如何下INT 3 断点

  1)首先,调试器使用 ReadProcessMemory,读取断点内存地址的字节。

  2)之后,调试器再使用 WriteProcessMemory,将指定的内存地址指令写为0xCC。

  3)之后,当程序执行到这里,遇到CC指令,会从IDT表中查03号段描述符,其会定向到Trap03函数。

  4)经过一系列操作(下面会介绍),此时调试器就会接收到INT 3中断,程序暂停,用户可以用来进行一些处理。

  5)恢复时,将1)读取的字节再重新写入到CC处,这样就可以保证程序的正常执行。

 

二、INT 3 异常指令如何派发到调试器

  我们在 一、3) 中,其会经过 Trap03,因此INT3异常信息肯定是在这里发送的。

  我们前面学过异常等派发,其检测到存在三环调试器时会发送到三环调试器,因此其派发也就是在这时进行的。

  派发流程大体如下:

  

 

 

三、上面产生的两个疑问:

  1)在 _kiDispatchException 中存在 dec eip,为什么调试器还需要修复 eip

  注意:这个是Context.eip--,而三环与零环走的是 TrapFrame 结构。因此即使在这里 Context.eip--,调试器接收调试信息是关于TrapFrame的。

  如果调试器没有处理,则异常处理回重新回到三环,调用SEH异常处理结构,这时Context.eip就起作用了。

  因此,调试器手动修复 INT 3 断点时,必须将eip--,回到程序执行前。

  2)为什么INT 3异常时不会走内核调试器

  我们假设这种情况,利用windbg调试虚拟机,在此基础上再虚拟机中开启OD调试程序,这时你会发现,是OD接收异常,Windbg不会接收异常。

  具体情况可以查看KiDispatchException函数,其调用内核调试器的代码如下

 1             if ((KiDebugRoutine != NULL)  &&
 2                 ((PsGetCurrentProcess()->DebugPort == NULL &&
 3                   !KdIgnoreUmExceptions) ||
 4                  (KdIsThisAKdTrap(ExceptionRecord, &ContextFrame, UserMode)))) {
 5                 //
 6                 // Now dispatch the fault to the kernel debugger.
 7                 //
 8 
 9                 if ((((KiDebugRoutine) (TrapFrame,
10                                         ExceptionFrame,
11                                         ExceptionRecord,
12                                         &ContextFrame,
13                                         PreviousMode,
14                                         FALSE)) != FALSE)) {
15 
16                     goto Handled1;
17                 }
18             }

  可以查看 _KdIsThisAdktrap函数,当存在三环调试器时,对于INT 3 异常不会走内核调试器。

  

 

四、异常处理的整体流程

  

 

 

 

 

posted @ 2019-12-04 17:21  OneTrainee  阅读(3979)  评论(0编辑  收藏  举报