我们在 (一)中调试了一个程序 接着我们开始继续学习
常见的断点
这里有
INT 3断点
硬件断点
内存断点
消息断点等
1.INT 3 断点
我们在OllyDbg中 可以使用 命令 bp 或者 F12进行断点
INT3断点 就是在程序中 对该位置的代码 进行替换
替换为INT3
INT3 是一个软中断指令
在x86框架中触发进行调试
INT3就是最常用的断点
其中软中断 是 代码触发的 而不是硬件问题触发的中断
在ollydbg中 其实我们按下F2 程序就会在这里设置 INT3 只是ollydbg进行了隐藏
显示出来的是中断前的指令
INT3 机器码是 0xCC 也叫做 CC指令
在程序执行到INT3指令导致的异常时候
调试器会捕捉到异常
从而停在断点处
然后把断点处的代码恢复为之前的代码
INT3的优点是可以设置无数个断点
缺点是改变了代码 容易被软件检测到
检测
如果软件防止API被下断点
有一些软件检测API的首地址是否为0xCC
这里给出检测方式
用C语言检测
这个方法就是 取得检测函数的地址
然后读取第一个字节
判断是否为CC
这里是检测的代码 对MessageBoxA
FARPROC Uaddr ;
BYTE Mark = 0;
(FARPROC&) Uaddr = GetProcAddress (LoadLibrary("user32.dll"),"MessageBoxA");
加载 user32.dll库中的 MessageBoxA函数
Mark = *((BYTE*))Uaddr; 把Mark 设定为 指向 Uaddr的指针
if(Mark == 0xCC) 判断第一个字节是否为0xCC 即INT3
return TRUE
当程序执行后 对MessageBoxA下断点 程序就会发现
绕过
如果我们要躲过检测 就把断点设置在函数的尾部或者内部
例如把断点设置在函数入口的下一行 这样我们就可以绕过检测
2.硬件断点
硬件断点和BRx调试寄存器有关
RBx调试寄存器中的 x可以是 0~3的数字
RBx调试寄存器用于设置硬件断点 在CPU执行到设置的地址的时候
就会触发中断 然后交给调试器进行调试
DRx调试寄存器具有8个寄存器 (DR0~DR7) 其中 某些寄存器又有自己的特性
DR0~DR3:调试地址寄存器 用于保存需要监视的地址 例如设置硬件断点
DR4~DR5:保留 未公开作用
DR6:调试寄存器组状态寄存器
DR7:调试寄存器组控制寄存器
原理
硬件断点的原理是
使用DR0 DR1 DR2 DR3设定地址 (最多设置4个断点)
然后使用DR7 设定状态
硬件执行断点和CC指令执行断点的作用一样
但是 硬件并不会修改地址第一字节为CC 所以更难检测
在调试器检测到DR0~DR3中的地址的时候 就会触发中断 交给调试器
而不是修改代码 进行中断
在ollydbg中也可以设置硬件中断
我们给出硬件中断的例子
还是之前的TraceMe.exe
在CPU窗口的寄存器窗口 右键->查看调试寄存器
然后我们在004013AA处设置硬件中断
然后F9执行程序
我们发现 DR0变为中断地址
在我们设置断点后
其实OllyDbg是在DR0~DR3中的一个设置为中断地址
然后再DR7中设置相应的控制位
当程序调试到中段地址 CPU就会向OllyDbg发送异常信息
然后可以中断
删除硬件断点
调试->硬件断点
当然也有快捷键
在地址按下F4 可以进行硬件中断 并且在中断后自动删除断点
硬件中断对比INT3中断 不容易被程序察觉 并且运行速度快
缺点是 只能设置4个断点