《python灰帽子》之调试器中的断点

2639阅读 0评论2012-04-19 XylDll
分类:Python/Ruby

在调试程序时,通过设置断点我们可以使一个进程的执行暂停在一个符合某种特定条件的位置上。一般情况下,调试器会提供三种基本类型的断点:

软断点、硬件断点、内存断点

软断点

目前在调试应用程序时最常用的断点类型。软断点的实质只是一个单字节长的指令,该指令可以使被调试的目标进程暂停执行并将控制权转交给调试器的异常处理例程。实际处理过程是将指令的操作码的第一个字节存放在断点列表中,然后用INT3中断指令的操作码0xCC填充该地方;当CPU试图执行操作码CC时,将触发一个端点事件,或被我们成为INT3事件;接着调试器将检查指令指针是否正指向一个此前被我们设置了断点的内存地址,如果这个地址在调试器内部的断点列表中被查到,那么调试器则会将之前存储的字节数据写回此内存地址中,这样,当此进程恢复执行后,正确的指令操作码将被执行。

假设指令 mov EAX, EBX位于内存地址0x44332211中,操作码为0x8BC3

0x44332211: 8BC3 mov EAX, EBX

设置软断点之后:

0x44332211: CCC3 mov EAX, EBX

软断点的执行流程图

软断点的使用改变了内存中的可执行代码,实际上同时也就改变了运行程序的循环冗余校验值(CRC)。CRC校验算法是一种非常非常非常严格的算法,可以检测出程序是否被改动过,即使是一个字节的改变,这种算法可被用于检查文件、内存、文本、网络封包或者任何需要监控数据篡改的场合。软断点会引起CRC校验失败。

硬件断点

硬件断点的设置是通过位于CPU上的一组特殊的寄存器(DR0~DR7)(都是32位)来实现的。硬件断点使用INT1中断。

DR0~DR3:存放硬件断点的内存地址,故最多可设置四个硬件断点。

DR4~DR5:保留

DR6:调试状态寄存器,记录上次断点触发的事件类型信息。

DR7:硬件断点的开关以及各个端点的触发条件信息。

DR7寄存器的布局图:

0~7位的L和G对应的是局部断点和全局断点,只要两个域均设置为1,就可以使断点工作。 16~31位决定了有关调试寄存器上所设断点的类型和长度。
断点类型(Type): 00--执行断点;01--数据写入断点;11--数据读写(但非执行)断点
断点长度(Len):00--1字节;01--2字节;11--四字节
IR7和一个设置与0x55667788上的双字节数据读写断点
   DR1
 
内存断点

本质上不是真正的断点。当一个调试器设置一个内存断点时,调试器实质上所做的是改变一个内存区域或一个内存页的访问权限。

内存页访问权限中有种保护页,对保护页的任何类型的访问将导致一次性异常,之后这个内存页会恢复到之前的状态。利用该特性,当进程访问一个特定区域内的内容时,我们让进程暂停执行。


上一篇:Python中的ctypes库
下一篇:《Python灰帽子》之构建自己的windows调试器1--加载进程