用 Hook 模拟断点问题
在进程内模拟调试器的断点操作:
1. 插入断点时, 改写断点位置的 5 个字节为一条调用断点处理函数的 call 指令. 比如 call __handle_break_point; 当然, 改写前会把原来的代码保存到相应的地方.
2. 断点命中后, 跳转到了 __handle_break_point 函数, 并在进行一系列的操作后, 得到 g 命令继续执行代码.
3. 要继续执行之前的代码, 我得把保存的代码还原回去, 然后在回到进入断点的地方开是执行.
这一切都没问题, 程序继续运行, 可是刚刚下断点已经不存在了, 被写回去了. 也就是说断点只能被命中一次!
为此, 我需要找到一个时机, 重新把下断点的 call __handle_break_point 指令写回去. 但是, 程序开是运行后我已经失去控制权了, 请教大家, 有没有好的办法来重新写入断点? 简单一点的, 最好是别要求用反汇编引擎去反汇编代码, 然后对反汇编的代码做很多分析的.
HOOK 断点 进程内调试
[解决办法]
一般来说, 调式器在恢复断点后会单步执行一次, 跳过了断点位置的指令后重新写入断点. 可以试试模仿这种行为. 不过调试器的断点指令只有 1 个字节, 你的断点指令有 5 个字节, 但步执行一次不一定就跳过去了.
[解决办法]
还那样.
我想不出什么完美的办法, 如果允许使用反汇编引擎, 可以找到跳过断点后的下一条指令, 在那个位置下一个临时断点, 临时断点命中的时候在去重新落实断点. 不过由于你的跳转指令占用了 5 个字节, 原始的指令可能包含各种跳转之类的, 它的下一条指令也不是那么好找的.
还有一种就是修改堆栈中断点所在函数的返回地址, 修改成自己的某个函数地址后函数返回的时候就会调用你的函数, 就可以去重新下断点了. 这样的缺点就是必须等到函数返回后才能重新下断点, 如果函数包含递归调用, 在递归的时候你的断点就没法命中了.
另外还有开个线程或者 Timer 来一直检测是否有断点没落实, 去执行下断点的操作. 但这个就更不可控了.
另外, 你这样的断点还有一个问题, 你的断点改写了 5 个字节, 里面可能包含多条指令, 其余位置的指令有可能跳转到你改动的字节的中间, 这样你的跳转不会触发, 而且接下来的代码会全都乱掉的.
[解决办法]
那这样看起来似乎无解了。