3

是否期望在反向调试期间不会恢复对程序地址空间所做的更改?

我一直在调试一个程序,当strlenGOT 中的指针在执行过程中损坏时,该程序会出现段错误。感谢来自对此问题的评论的建议,我通过链接选项将该程序的 GOT 设为只读-z relro;但是,这并不能防止有问题的指针被覆盖。即我可以在gdb中start的程序,跳到第一次出现的,strlen验证指针是否有效(例如:程序;例如:),提示.x/g 0x5555555d10a8 ==> 0x5555555d10a8 <strlen@got.plt>: 0x00007ffff7e8d1e0continuex/g 0x5555555d10a8 ==> 0x5555555d10a8 <strlen@got.plt>: 0x0000000000002156segv

但是,如果我record full整个执行(从第一行到程序段错误),然后awatch是带有指针的地址strlenduring reverse-continue,则观察点永远不会触发。当程序最终回到指令#0时,指针仍然指向它在段错误时所拥有的无效地址。

这导致了两个问题。首先,尽管有链接器选项,为什么 GOT 是可变的-z relro?其次,是否期望strlen在程序执行期间更改的内存中的某个位置(指向 的指针)在反向执行期间不会恢复到其原始值?

4

2 回答 2

2

首先,尽管有 -z relro 链接器选项,为什么 GOT 是可变的?

您申请-Wl,-z,relro的只是部分RELRO 保护。该选项的主要目的是将 GOT 移动到 BSS 之前以避免由于 BSS 中的缓冲区溢出而导致条目损坏,并且还使 GOT 的一小部分成为只读的。你想要的是完整的 RELRO,它是通过-Wl,-z,relro,-z,now. 链接器-z now标志使加载程序在启动时解析所有符号,然后在启动程序之前将包含 GOT 的段重新映射为只读。

其次,是否期望strlen在程序执行期间更改的内存中的某个位置(指向 的指针)在反向执行期间不会恢复到其原始值?

您可能在开始调试之前忘记设置target record-full,但我不确定这是否有任何效果,因为您已经使用record full. 逆向执行并不容易,调试器可能出于性能原因决定逆向 GOT(或其他部分)的内存修改(因为这些通常不应该被触及)。GDB 的记录功能还有其他一些限制,例如不支持 AVX 指令。我不知道更多可以给出更好的答案。你可以试试运气rr

于 2020-01-13T22:48:52.477 回答
1

-z relro选项仅部分只读(在部分RELRO中,该部分的非 PLT 部分GOT(来自 readelf 输出的.got)是只读的,但.got.plt仍然是可写的。而在完整的 RELRO 中,整个 GOT(.got.got.plt两者)被标记为只读。

如果您还想完全只读使用-z, now

使用重定位强化 ELF 二进制文件

于 2020-01-13T22:46:31.237 回答