探秘INT3指令


简介


INT3指令是专门用来支持调试的一条指令,它对应的机器码是0xCC。当cpu执行到这条指令是会产生异常并调用相应的异常处理程序(3号中断)进行进一步的处理。

详细分析


int3指令原理

cpu在指令完int3指令后会引发异常,此异常会使操作系统从中断向量表中调用3号中断处理程序,此中断处理程序即函数 nt!KiTrap03( ),此函数进行一些处理后又会继续调用nt!KiDisPatchException( )函数来进行异常的分发。而此函数会先去检查是否存在调试器(即程序是否正在被调试),如果存在调试器则把异常交给调试器,调试器处理完之后在返回到。如果调试器不处理或者就不存在调试器则异常会传递到程序自身的异常处理中,然后返回。

在这里插入图片描述

int3指令在调试器中的应用

我们都知道调试器中有int3断点,而int3断点就是基于int3指令实现的。以OD为例当我们在某一汇编指令处设下断点后,调试器会把所设断点地址处的第一个字节改为0xCC(即INT3指令),并把原字节保存。之所以我们看起来OD的此地址处字节没有发生任何变化是因为OD为了维持汇编代码的可读性并没有将改变后的指令进行重新反汇编。我们可以利用如下方法来查看其地址处的实际数据。

首先我们用OD随便加载一个程序,我们在入口点下发任意一条汇编指令处下断点,我们发现此地址处的数据并没有变化,这是OD为了维护代码可读性,实际此地址数据已经变为了0xCC

在这里插入图片描述

我们接下来用把即将运行的第一条指令修改为 mov al , byte ptr ds:[0x401830]。也就是将此断点地址处的值读到al中

在这里插入图片描述

F8执行此代码后,我们发现eax值为0x000000CC。证明此断点地址处的值已经被修改为0xCC。

在这里插入图片描述所以当cpu执行到此断点时就会执行0xCC(即INT3指令),接着产生异常去执行函数nt!KiTrap03( ),此函数会将指令指针(eip)的值减一,因为其刚执行完0xCC此时eip指向0xCC的下一个字节,所以减一后eip重新指向0xCC(断点处)。接着会调用nt!KiDisPatchException( )函数并将异常分发给调试器,而OD调试器将先还原此断点处的原字节,然后使返回程序将停在此断点处等待用户的进一步操作。我们可以通过如下方法进行验证。

接着上一次我们分析的程序,我们把断点处的指令更改为mov al , byte ptr ds:[0x401830]。

在这里插入图片描述

F8向下执行,当执行完断点处的指令后,我们发现al的值A0。说明断点处的字节已被修复。

在这里插入图片描述然后为了使下次运行到此处时断点还有效,程序会利用单步异常来把断点处的值在该为0xCC。其在执行完断点处的指令后,会产生单步异常从而被调试器捕捉,然后调试器会将此断点处的值更改为0xCC。我们可以利用如下方法验证。

我们将断点后的指令改为mov al , byte ptr ds:[0x401830],然后F8执行代码后发现al的值为0xCC,说明断点已在执行完断点处指令后恢复。

在这里插入图片描述

int3与它的兄弟int 3

int3指令的机器码为0xCC ,而int 3也就时我们所了解的软中断int n的机器码为 0xCD 0x03。二者不光时机器码不同,系统会对int3指令一些特殊待遇而int 3却没有此待遇。
其不同在调试器调试过程中也有反映,我们下面利用OD来分析一下在调试器中其会有哪些不同。
在分析之前我们要设置一下OD,让OD忽略int3断点。这样OD就不会处理int3产生的异常了。

在这里插入图片描述

我们随便拿一个程序用OD分析,我们发程序入口的指令改为int3(即0xCC)

在这里插入图片描述

然后我们运行程序我们发现eip还是指向此地址处。原因是产生异常后系统调用了nt!KiTrap03( )时令eip - 1,所以返回后eip还指向地址处。

在这里插入图片描述

我们接下来把此地址处指令改为 int 3。即字节0xCD 0x03,其余的自动用nop填充。

在这里插入图片描述

然后我们运行代码发现eip指向了地址0x004010c3即入口地址+1处。原因是我们在执行完int 3指令后也产生异常,系统同样调用的nt!KiTrap03(),其令eip -1。但是int 3 指令是两个字节,减一后eip指向的是字节0x03。如此一来在返回后OD会重新对eip后面的代码进行组合和反汇编。

在这里插入图片描述
如果我们继续执行代码则会发生意想不到的异常,因为后面的代码都是错误的反汇编代码。

int3指令在其他方面的应用

我们知道栈一般是用0xcc初始化,而堆一般使用0xcd初始化。而0xcc对应汉字编码为 烫,int3指令机器码也为0xcc。而这并非偶然,当发生指针栈溢出时eip会指向初始化时填充的0xcc从而引发int3断点异常,使程序中断。

int3断点的优缺点

  • 优点:数量没有限制,操作简单。
  • 缺点:因为改变机器码所以易被检测,只能在代码段中使用,而且因为其是基于中断的所以当中断描述符表被破坏时其将无效。

总结


int3指令在软件调试中被广泛运用。因为int3指令基于中断和异常处理,所以利用int3指令在软件的安全反面也有很大用处。

参考:软件调试