有关几个断点的总结

软件断点(CC断点)

软件断点总述

使用readprocessmemory先保存第一个字节,而后writeprocessmemory将一个字节改为cc,然后执行一步,触发异常, writeprocessmemory将替换的字符恢复,eip-1;

原理

调试器让一个程序g(运行)起来的时候,才能 把int 3写到内存里面, 当程序执行起来碰到这个断点断(break)下来的时候,把int 3恢复成原来的内容 ,断下来的时候看不到int 3,因为调试器把int 3替换掉的内容又恢复回去,所以我们看到的是原来的指令,g起来的时候,再把这条指令(int 3)写下去

(我的理解:一开始在某一处下了个软件断点,只有在调试运行的时候才将int 3指令写到那个刚刚下断点的地方, 然后程序执行起来碰到cc就会断下来(碰到cc就会触发异常),调试器立即int 3替换掉的内容又恢复回去,所以我们看到的是原来的指令,g起来的时候,再把这条指令(int 3)写下去)

对于eip-1的理解:

值得注意的是,内存断点被触发后需要将EIP减1,还原内存数据,这样做是为了什么呢?
E912345678这是一条跳转指令,下了0xcc断点后变成了这样:
CC12345678,EIP不减1,CPU会从12345678处继续执行,这样下去,指令全部乱套.所以要将EIP减1
将EIP减1后,CPU重CC处执行,会继续触发异常,陷入死循环,所以要将内存数据还原
但是还原内存数据之后,这个断点下一次就不能使用了.
解决的办法就是恢复数据后触发TF断点,在TF断点触发时将CC重新写入.

举个例子:
E9 12345678 ,在这个指令地方下个int 3断点(软件断点)
将int 3指令写入下断点的地方,调试运行的时候刚执行完cc这个字节,就触发了这个异常,停下来,EIP-1(为什么要减1,如果不减1的话,下次执行就从12345678这里开始执行了,显然这是不行的!),同时,调试器立即int 3替换掉的内容又恢复回去,运行起来的时候,再把这条指令(int 3)写下去

注意:int3 是陷阱异常,陷阱异常就是当指令执行之后才会产生异常,因此,int3异常产生之后,eip就是已经执行了int 3指令之后的eip了,因此收到调试事件之后,需要将EIP减1,才能得到异常真正产生异常的地址;
在下软件断点之前,先读取一个字节的内存保存起来,再写入0xCC,执行完CC字节之后,产生异常,引发中断,中断之后,需将原先的一个字节的数据写回内存中,再将EIP-1

内存断点

调试器:OllyDbg
环境:win10 64位真机

如何设置:右击一行代码-断点-内存访问、写入断点
这里写图片描述
有三种功能:执行,写入,访问。
访问=写入+执行
执行即把机器码当成程序执行时被断下
写入即改写这部分机器码时被断下
内存断点的原理:内存断点的实现方式是将你欲下断地址所在的内存页增加一个名为PAGE_NOACCESS的属性,这个属性会把当前内存页设为禁止任何形式的访问,如果进行访问会触发一个内存访问异常。在这同时,od开始捕获目标程序中出现的这个异常,并判断触发这个异常的位置是否跟你下断的地址相同,如果相同则内存断点触发,暂停被调试程序的运行(详见下面的触发内存断点的过程),否则放行。
内存断点的局限性:
只能设置一次,不能设置多个,而且不会显示地点在哪,调试器不记录,所以要自己及时把内存断点记下来。而且当程序重新载入后也会自动消失

注:
1.新设置的内存断点后,原来的断点会被覆盖。
2.触发内存断点的过程:
把相关内存属性设置为PAGE_NOACCESS,这样当此页内的内存被读写的时候,就会有异常传给调试器,而后debuggee(被调试)进程被挂起,调试器把内存页属性重新修改回去,同时设置一个单步调试断点。这样debugee进程才可以正常执行过去,否则会一直被挂起。因为被设置了单步调试断点,所以执行一个指令就再次挂起,交给调试器去处理。这时候调试器把页面属性重新修改为PAGE_NOACCESS就可以了。

硬件断点

DR0-DR3存放断点位置; DR7对设置的硬件断点进行描述
在设置(硬件)断点的时候,调试器帮助我们把我们要监视的地址放到四个(DR0-DR3)当中的一个,然后DR7(对设置的硬件断点进行描述)设置一些标志位,比如我们要监视的这个地址是对它写的时候停下来,还是读写的时候都停下来;监视的长度是多少,R/W0,Len0是对断点0的设置,R/W1,Len1…(还有2,3共计四组标志位);
DR6是报告断点状态的
我们设置好断点之后,CPU每执行一条指令的时候,CPU都会做匹配,来检查当前这条指令访问的内存是不是和地址匹配,如果匹配 ,就设置DR6里面的标志位,然后一个异常报告给操作系统,操作系统断下来再检查这些标志位,就知道哪一个命中匹配了,DR7的标志位恰好支持4个硬件断点的,故DR4和DR5一直没有用,( 理论上每个CPU可以监视4个地址);软件层:每个线程可以设置4个地址;
读写(访问)断点,写入断点,执行断点,I/O断点
• 写入断点,类似于mov [0x0040 0000],eax,第一个操作数一定是0xXXXXXXXX
• 读写断点,类似于mov eax,[0x0040 0000],第二个操作数一定是0xXXXXXXXX
• 执行断点,有点类似于int3(软件断点)
硬件断点的优点是相对难检测,
缺点是数量有限,只能设置4个。和内存断点不同,硬件断点和CC断点重新载入后都不消失。

单步断点

如果单步执行的话,TF会被置1,置1之后,让 CPU恢复执行被调试的那个程序 ,CPU每执行一条指令,就检查这个标志位,看到这个标志位置位,立刻触发一个异常,这个程序就又断下来了,CPU看到TF之后,会自动清除 TF位,故在观察的时候我们是很难观察到TF位置1的,因为 CPU看到TF位会清0,否则会出问题,你想,CPU看到TF位就break,看到TF位了,肯定要执行处理异常的那个代码 ,CPU处理异常的那个代码,我们不希望再断下来,所以是很合理的,CPU自动清TF位,然后执行异常处理代码,通知调试器;
(我自己的理解:vs中按下F7,TF会被置1,置1之后CPU会检测到TF为1,触发异常,同时程序走到这里会断下来,而后CPU会立即将TF置为0,然后继续下一步,继续F7…而F8(单步步过)大体上和F7一样,只有一处,遇到调用函数的时候(即call 指令),会执行int3指令)

条件断点

调试器:OllyDbg

环境:win10 64位真机

示例:
这里写图片描述
这里写图片描述
这里写图片描述
如何设置条件断点

1 Shift+f2

2 右键-断点-条件,再输入条件:[UNICODE[ESP+4]]==”C:\KuGou\Temp\063289fd25addbca733ab967c5bffccb.kgtemp”(注:这里写UNICODE是因为这里的一个字符等价于2个字节)
esp+0为返回地址;
esp+4为函数第一个参数;
esp+8为函数第二个参数;

消息断点

参见
消息断点
消息断点及 RUN 跟踪
几种典型程序Button处理代码的定位

猜你喜欢

转载自blog.csdn.net/richard1230/article/details/80313680