-
-
[原创]硬件断点和原理与实现
-
发表于:
2018-12-30 15:52
9917
-
Intel 80306以上的CPU给我们提供了调试寄存器用于软件调试,硬件断点是通过设置调试寄存器实现的。
图1 调试寄存器
图1为Intel手册提供的32位操作系统下8个调试寄存器的图示(Intel手册卷3 17章第二节 Debug Registers,有兴趣的朋友可以查阅),根据介绍,DR0-DR3为设置断点的地址,DR4和DR5为保留,
DR6为调试异常产生后显示的一些信息,DR7保存了断点是否启用、断点类型和长度等信息。
我们在使用硬件断点的时候,就是要设置调试寄存器,将断点的位置设置到DR0-DR3中,断点的长度设置到DR7的LEN0-LEN3中,将断点的类型设置到DR7的RW0-RW3中,将是否启用断点设置到DR7的L0-L3中。
设置硬件断点需要的DR0-DR3很简单,就是下断点的地址,DR7寄存器很复杂,位段信息结构体如下:
需要注意的是,设置硬件断点时,断点的长度、类型和地址是有要求的。
图2 调试寄存器的设置要求
如图2所示,保存DR0-DR3地址所指向位置的断点类型(RW0-RW3)与断点长度(LEN0-LEN3),状态描述如下:
00:执行 01:写入 11:读写
00:1字节 01:2字节 11:4字节
设置硬件执行断点时,长度只能为1(LEN0-LEN3设置为0时表示长度为1)
设置读写断点时,如果长度为1,地址不需要对齐,如果长度为2,则地址必须是2的整数倍,如果长度为4,则地址必须是4的整数倍。
原理大概就是这么多了,下面就是实现了。
实现硬件断点,首先要获取当前线程环境
在CONTEXT结构体中,存放了诸多当前线程环境的信息,以下是从winnt.h文件中找到的CONTEXT结构体
从CONTEXT结构体中我们可以看到存放了调试寄存器 Dr0-Dr3和Dr6、Dr7,通过设置这些寄存器我们可以实现硬件断点。
已经获取了当前线程环境,接下来就是设置调试寄存器
调试寄存器的信息设置好之后,我们要将当前环境保存
由此,硬件断点的大致实现思路已经完成。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)