x/16i 0xdeadbeef
产生:
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-27“里面”有一些多汁的指令,如果我能看到它们是什么就好了。x/16s 0xdeadbeef
得到:
0x80481be <_init+22>: "\300t\005\350:~\373\367\203\304\b"
型
这一点也不有趣。
我正在写一个ROP链生成器,所以我需要找到可以通过跳转到其他指令的“中间”来执行的指令。(非常)慢的方法是简单地运行x/i 0xdeadbeef; x/i 0xdeadbef0, ...
。有没有更快的方法?
我试过x/i+<offset> 0xdeadbeef
:* 第一个 * 产生的指令在x/i 0xdeadbeef的中间,但是后续的指令并不是“索引到”的中间,这使得这种方式与慢速方式相同。
1条答案
按热度按时间cu6pst1q1#
GDB是为调试CPU将要执行的代码的正常用例而设计的,因此下一条指令的反汇编从上一条指令的末尾开始。如果您主要是手动查看,您可以定义一个GDB函数来反汇编从范围内的每个字节偏移量开始的短序列。您可以直接输入此函数(一次一行)在GDB的交互式命令行上,或者我认为把它放在你的
.gdbinit
或你的源文件中。这定义了一个接受2个参数的函数:起始地址和从每个起始字节开始的反汇编字节长度。
字符串
您也可以将长度(32字节)参数化为
$arg2
进行搜索。请参阅GDB手册(https://sourceware.org/gdb/current/onlinedocs/gdb.html/Define.html),其中有示例。在交互式使用中,这看起来像:
型
abort
只是在objdump -drwC -Mintel /lib/libc.so.6 | less
中早期出现的符号名称。我的.gdbinit
使用set disassembly-flavor intel
。所以它是嘈杂的,2行开始/结束“的汇编转储”周围的每个块,但这不是那么糟糕时,看块的多个指令。(GDB将反汇编到一个指令的末尾是disas范围包括第一个字节。)
重要的是CPU将从任何给定的起始点执行的指令序列,所以我使用了16字节的范围,而不仅仅是
1
来查看您在给定起始点获得的指令。当然,这并不是对以
ret
或pop reg
/jmp reg
结尾的序列进行过滤,也许可以使用GDB命令来实现这一点。或者,如果你想编写一个完整的程序来分析你粘贴的一段机器代码,或者甚至在可执行文件和库中搜索字节,或者在运行的进程中搜索字节,那么可以使用像capstone和XED这样的反汇编器库。x86机器码是一个字节流,它不是自同步的,但是从给定的起始点唯一解码。对于典型的用例,如果跳转目标地址错误,查看它将如何解码是没有用的。GDB没有这样做的选项。
尽管不是真正的自我同步(你不能只看一个字节就知道它是不是一条指令的开始或结束),相当多的字节是单字节指令的前缀或操作码,所以re-sync通常发生在2到10个字节内。IDK如果你想过滤掉或不。可能不会,只是看看所有不同的选项,导致一个
ret
。