如何在GDB中根据二进制文件偏移地址设置观察点?
解决无调试信息二进制中基于文件偏移设置GDB观察点的问题
我完全懂你的痛点——逆向没有调试信息的二进制时,把静态文件偏移映射到运行时内存地址,确实是设置观察点的关键障碍,尤其是你试过直接用文件偏移设置却没效果的时候。下面一步步教你怎么搞定:
核心思路
GDB的观察点只能作用于运行时内存地址,而文件偏移是相对于二进制文件本身的位置,两者之间需要通过二进制的段信息来转换。你需要先找到目标偏移所在的段,再计算它对应的内存地址。
步骤1:分析二进制的段信息
首先用工具查看二进制的段布局,推荐用objdump或者readelf:
objdump -h your_binary
或者:
readelf -S your_binary
输出里会列出所有段,找到你的目标偏移0x85c6d所属的段(比如.text、.data或者.rodata)。重点关注两个字段:
Offset:该段在二进制文件中的起始偏移VMA:该段加载到内存后的虚拟起始地址
举个例子:假设.text段的Offset是0x1000,VMA是0x400000,而你的目标偏移0x85c6d在这个段里,那么内存地址的计算公式是:
内存地址 = 段VMA + (目标文件偏移 - 段Offset)
代入数值就是:0x400000 + (0x85c6d - 0x1000) = 0x4075c6d
步骤2:处理ASLR(地址空间随机化)
如果系统开启了ASLR(大多数默认开启),二进制的实际加载地址会和VMA不一样。这时候你需要在GDB里启动程序后,获取实际的段起始地址:
- 在GDB里启动程序:
run(或者start让程序停在入口点) - 查看进程的内存映射:
info proc mappings - 在输出里找到目标段(比如
.text)的起始地址(第一列的起始值)
接着用同样的公式计算:实际内存地址 = 实际段起始地址 + (目标文件偏移 - 段Offset)
步骤3:设置观察点
拿到正确的内存地址后,用GDB的watch命令监控这个地址的读写:
watch *0x<计算出的内存地址>
比如如果计算出的地址是0x5555555d9c6d,就输入:
watch *0x5555555d9c6d
如果只想监控写操作,可以用watch -w,读操作用watch -r。
为什么之前的方法无效?
watch 0x85c6d:GDB会把这个当作一个值,监控的是“某个寄存器或变量等于0x85c6d”的情况,完全不是你要的内存监控,所以无效。watch *0x85c6d:这个命令监控的是内存地址0x85c6d,但二进制加载后的内存地址通常远高于这个值(比如64位程序一般从0x555555554000开始),所以你监控的是一个无关的内存区域,自然看不到预期的变化。
内容的提问来源于stack exchange,提问作者Minerscale
相关产品推荐
相关产品推荐

