我们在 (一)中调试了一个程序 接着我们开始继续学习
常见的断点
这里有
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
这里是检测的代码 对MessageBoxAFARPROC Uaddr ;
BYTE Mark = 0;
(FARPROC&) Uaddr = GetProcAddress (LoadLibrary("user32.dll"),"MessageBoxA");
加载 user32.dll库中的 MessageBoxA函数
Mark = *((BYTE*))Uaddr; 把Mark 设定为 指向 Uaddr的指针
if(Mark == 0xCC) 判断第一个字节是否为0xCC 即INT3return 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个断点
3.内存断点
OllyDbg 可以设置内存访问断点 或者 内存写入断点
原理
对所设置的地址 赋予不可访问 不可写 属性就这样 当 访问和写入 就会发生异常OllyDbg捕获异常比较异常是不是我们设置断点地址如果是 就中断 然后用户进行操作
因为每一次都要进行比对 来确定是否中断 所以执行速度会慢所以OllyDbg可能出于执行考虑 内存中断 只能下一个断点
程序运行有3种状态 分别是 读取 写入 和执行
mov dword ptr [405528],edx 对内存进行写入
mov dword ptr edx,[405528] 对内存数据进行读取
例子
使用OllyDbg调试 TraceMe.exe
我们可以看到 这个 是写入内存中的 汇编指令
我们使用这个下内存断点
我们需要进入数据面板
先对这个地址在数据面板跟随
然后F9运行
发现他中断在这个地址
删除
如果我们要删除中断 右键->删除内存断点 即可
在这个场景中 硬件断点也可以实现和内存断点相同的效果
单个硬件写入/访断点可以设置为 1字节 2字节 4字节
而且无论选择的数据范围多大 只有前4个字节会起作用
还是在内存地址中 对地址选择 硬件写入 然后选择 word 就是4个字节
还是会中断在 这个地址上的下一条指令
区别
硬件写入/访问断点是在执行的下一条进行中断
内存断点是在触发点的指令处进行中断
对代码也可以下内存访问断点
在代码处 右键 内存访问 然后运行程序 就会断在这个地方
总结
在内存执行的地方 也可以通过内存访问中断内存访问断点不会修改代码 不会和INT3一样修改代码而被程序校验所以如果在遇到程序校验 并且硬件断点失灵的情况下 可以使用内存断点
4.内存访问一次性断点
Windows对内存使用段分页式管理
在OllyDbg中
按ALT+M 就可以看内存
这里出现很多段 然后每个段都有不可访问 读 写 执行属性
在相应的段 右键
这个就可以用于整个内存开设置该类断点
这个断点是一次性断点 所在段在被读取或者执行就会中断
中断以后 就会删除该断点
如果想捕捉调用 或者返回某个模块该类断点就特别有用
其中还有断点 设置内存访问断点 这个断点和在访问上设置断点 命令的功能大致相同所不同的是这个 内存访问断点不是一次性的并且这个断点是要在NT框架下使用并且仅在这个框架下使用
5.消息断点
Windows本身就是消息驱动的 如果调试的时候没有合适的断点
可以尝试使用消息断点
当某个特定窗口接收到某个特定消息时
消息断点将程序中断消息断点和INT3断点的区别在于:INT3断点可以在程序启动之前设置
消息断点只有在 窗口被创建后才可以被设置 并且拦截消息
当用户单击一个按钮、移动光标或者向文本框输入文字