目标:我想获取 hex 和 ascii 数据(从使用 xxd 的二进制文件派生)并使用 Objdump(或 Linux 附带的其他合适的工具)输出内存地址/偏移量、汇编代码和文本数据。
目前我可以获得偏移量和汇编代码,但不能同时获得文本字符串。
我使用了以下内容:
objdump -D -b binary -mi386 -Maddr16,data16 <filename>
我需要使用-s
开关吗?
目标:我想获取 hex 和 ascii 数据(从使用 xxd 的二进制文件派生)并使用 Objdump(或 Linux 附带的其他合适的工具)输出内存地址/偏移量、汇编代码和文本数据。
目前我可以获得偏移量和汇编代码,但不能同时获得文本字符串。
我使用了以下内容:
objdump -D -b binary -mi386 -Maddr16,data16 <filename>
我需要使用-s
开关吗?
这里假设正在分析 Linux ELF32 二进制文件。
代码和数据(例如字符串)存储在 ELF 二进制文件的不同部分中。
objdump -dj .text <binary_name>
.readelf -x .rodata <binary_name>
目前我可以获得偏移量和汇编代码,但不能同时获得文本字符串。
代码和硬编码字符串不会混合在 x86 或 x86-64 ELF 二进制文件中。当编译器工具链生成二进制文件时,硬编码的字符串被放置在二进制文件的一个与可执行代码不同的区域中,并通过它们的虚拟内存地址进行引用/访问。这是Ange Albertini 的图表,展示了 ELF 二进制文件中不同部分的布局:
为了使这更清楚,下面是的Linux工具可视化ls
,cat
,mkdir
和mv
(通过完成binvis.io)。蓝色实心区域由 ASCII 字符串数据(.rodata
例如段)组成,蓝色、白色、红色和黑色混合在一起的大块是由可执行代码(.text
例如段)组成的区域。
* ls cat mkdir mv
从这些可视化中可以看出,这些二进制文件的组织方式类似。每个二进制都有包含不同信息的离散区域或部分。我们在这里也可以看到,有多个区域(即段)包含 ASCII 字符串数据,而不仅仅是一个。
具有可执行指令的部分将不包含有意义的字符串,只包含代码。在检查Linux实用程序的部分时,可以通过使用-s
with 选项直接观察到这一点:objdump
.text
date
$ objdump -sj .text /bin/date
/bin/date: file format elf64-x86-64
Contents of section .text:
401af0 41574531 ff415645 31f64155 41544531 AWE1.AVE1.AUATE1
401b00 e45589fd 534889f3 4881ecd8 00000048 .U..SH..H......H
401b10 8b3ee8f9 530000be a1c84000 bf060000 .>..S.....@.....
401b20 00e8bafe ffffbe87 944000bf 61944000 .........@..a.@.
401b30 e83bfcff ffbf6194 4000e811 fcffffbf .;....a.@.......
401b40 102c4000 e8877800 00c64424 0f0048c7 .,@...x...D$..H.
< snip >
在 ELF 二进制文件中,该.text
部分包含程序的可执行指令。组成指令的字节在此十六进制转储中被视为 ASCII,因此打印出无意义的字符序列。
objdump
依赖于 ELF 二进制文件的节头来确定二进制文件的哪些部分包含代码,哪些部分包含数据。只.text
应使用 反汇编包含指令的部分(例如)objdump
。-D
参数 toobjdump
将导致 ELF 二进制文件的所有部分都被反汇编,即使是非代码部分,如.data
和.rodata
。
从手册页:
-D
--disassemble-all
类似于 -d,但反汇编所有部分的内容,而不仅仅是那些预期包含指令的部分。
即使一节包含硬编码字符串,这意味着(.dynstr
,.shstrtab
,.rodata
等)objdump
将会把这个数据作为说明和相应dissasemble他们。
下面是一个使用 /bin/date 的例子:
/bin/date: file format elf64-x86-64
Disassembly of section .rodata:
0000000000409400 <.rodata>:
409400: 01 00 add %eax,(%rax)
409402: 02 00 add (%rax),%al
409404: 74 69 je 40946f <__sprintf_chk@plt+0x798f>
409406: 6d insl (%dx),%es:(%rdi)
409407: 65 20 25 73 20 69 73 and %ah,%gs:0x73692073(%rip) # 73a9b481 <stderr+0x7348d131>
40940e: 20 6f 75 and %ch,0x75(%rdi)
409411: 74 20 je 409433 <__sprintf_chk@plt+0x7953>
409413: 6f outsl %ds:(%rsi),(%dx)
409414: 66 data16
409415: 20 72 61 and %dh,0x61(%rdx)
409418: 6e outsb %ds:(%rsi),(%dx)
409419: 67 65 00 0a add %cl,%gs:(%edx)
40941d: 52 push %rdx
40941e: 65 gs
40941f: 70 6f jo 409490 <__sprintf_chk@plt+0x79b0>
< snip >
看起来像是在反汇编指令,而实际上是将数据视为代码:
$ readelf -x .rodata /bin/date
Hex dump of section '.rodata':
0x00409400 01000200 74696d65 20257320 6973206f ....time %s is o
0x00409410 7574206f 66207261 6e676500 0a526570 ut of range..Rep
此外,这些参数-b binary
导致objdump
将二进制文件视为具有单个部分的 blob,从而消除了二进制文件中代码和数据之间的任何区别,从而导致二进制文件的全部内容都被视为代码。
参考:System V ABI第 4 节:“目标文件”