如何让GDB无视指令边界反汇编指定内存范围以寻找内嵌指令?
如何让GDB无视指令边界高效反汇编内存范围?
我正在编写ROP链生成器,需要查找可通过跳转到其他指令中间执行的内嵌指令。目前逐个地址执行x/i 0xdeadbeef; x/i 0xdeadbef0...的方法效率极低。尝试x/i+<offset> 0xdeadbeef仅第一条指令从目标位置开始解析,后续仍按正常指令边界走,和慢方法无异。
此前执行x/16i 0x80481be得到结果:
0x80481be <_init+22>: shlb $0x3a,-0x18(%ebp,%eax,1) 0x80481c3 <_init+27>: jle 0x80481c0 <_init+24> 0x80481c5 <_init+29>: .byte 0xf7 0x80481c6 <_init+30>: add $0x8,%esp 0x80481c9 <_init+33>: pop %ebx 0x80481ca <_init+34>: ret
可见_init+22到_init+27区间内存在可执行的内嵌指令,但无法直接查看。执行x/16s 0x80481be得到结果:
0x80481be <_init+22>: "\300t\005\350:~\373\367\203\304\b"
完全没有参考价值。请问是否存在更高效的方法,让GDB无视指令边界反汇编特定内存范围?
解决方案
1. 自定义GDB命令实现逐字节反汇编
GDB没有原生的强制逐字节反汇编命令,但可以编写一个简单的循环脚本:
define disasm-byte set $addr = $arg0 set $end = $arg1 while $addr < $end x/i $addr set $addr = $addr + 1 end end
将这段代码保存到.gdbinit,或直接在GDB交互界面执行。调用时输入disasm-byte 0x80481be 0x80481c3,即可从起始地址逐字节反汇编到结束地址,每个偏移都会被当作指令起点解析。
2. 结合objdump与内存转储实现高效反汇编
如果GDB内的方法效率不足,可以先转储目标内存,再用objdump强制反汇编所有字节:
- 在GDB中转储内存:
dump binary memory mem_dump.bin 0x80481be 0x80481c3 - 用objdump反汇编(以x86架构为例):
objdump -D -b binary -m i386 --adjust-vma=0x80481be mem_dump.bin-D参数强制反汇编所有字节,无视指令边界--adjust-vma设置反汇编时的基地址,与原内存地址对应,方便定位
3. 利用GDB Python API实现精准反汇编
如果需要更灵活的逻辑,可以用GDB的Python脚本调用反汇编接口,配合第三方库提升效率:
import gdb # 若安装了capstone库,可更精准计算指令长度,避免逐字节冗余 # from capstone import Cs, CS_ARCH_X86, CS_MODE_32 def disasm_range(start, end): current = start while current < end: try: insn = gdb.execute(f"x/i {current}", to_string=True) print(insn.strip()) # 若使用capstone,可替换为获取指令长度后直接跳转 # md = Cs(CS_ARCH_X86, CS_MODE_32) # for i in md.disasm(gdb.selected_inferior().read_memory(current, 15), current): # print(f"0x{i.address:x}: {i.mnemonic} {i.op_str}") # current = i.address + i.size # break current += 1 except: current += 1 # 调用示例:disasm_range(0x80481be, 0x80481c3)
安装capstone库后,可直接计算指令长度,跳过已解析的字节,大幅提升反汇编效率。
内容的提问来源于stack exchange,提问作者brunge
相关产品推荐
相关产品推荐

