如何在Linux中反汇编二进制可执行文件以获取汇编代码?

我被告知使用反汇编。 gcc是否有内置的东西? 什么是最简单的方法来做到这一点?

我不认为gcc有一个标志,因为它主要是一个编译器,但另一个GNU开发工具。 objdump需要一个-d / --disassemble标志:

 $ objdump -d /path/to/binary 

反汇编看起来像这样:

 080483b4 <main>: 80483b4: 8d 4c 24 04 lea 0x4(%esp),%ecx 80483b8: 83 e4 f0 and $0xfffffff0,%esp 80483bb: ff 71 fc pushl -0x4(%ecx) 80483be: 55 push %ebp 80483bf: 89 e5 mov %esp,%ebp 80483c1: 51 push %ecx 80483c2: b8 00 00 00 00 mov $0x0,%eax 80483c7: 59 pop %ecx 80483c8: 5d pop %ebp 80483c9: 8d 61 fc lea -0x4(%ecx),%esp 80483cc: c3 ret 80483cd: 90 nop 80483ce: 90 nop 80483cf: 90 nop 

objdump的一个有趣的替代方法是gdb。 您不必运行二进制文件或具有debuginfo。

 $ gdb -q ./a.out Reading symbols from ./a.out...(no debugging symbols found)...done. (gdb) info functions All defined functions: Non-debugging symbols: 0x00000000004003a8 _init 0x00000000004003e0 __libc_start_main@plt 0x00000000004003f0 __gmon_start__@plt 0x0000000000400400 _start 0x0000000000400430 deregister_tm_clones 0x0000000000400460 register_tm_clones 0x00000000004004a0 __do_global_dtors_aux 0x00000000004004c0 frame_dummy 0x00000000004004f0 fce 0x00000000004004fb main 0x0000000000400510 __libc_csu_init 0x0000000000400580 __libc_csu_fini 0x0000000000400584 _fini (gdb) disassemble main Dump of assembler code for function main: 0x00000000004004fb <+0>: push %rbp 0x00000000004004fc <+1>: mov %rsp,%rbp 0x00000000004004ff <+4>: sub $0x10,%rsp 0x0000000000400503 <+8>: callq 0x4004f0 <fce> 0x0000000000400508 <+13>: mov %eax,-0x4(%rbp) 0x000000000040050b <+16>: mov -0x4(%rbp),%eax 0x000000000040050e <+19>: leaveq 0x000000000040050f <+20>: retq End of assembler dump. (gdb) disassemble fce Dump of assembler code for function fce: 0x00000000004004f0 <+0>: push %rbp 0x00000000004004f1 <+1>: mov %rsp,%rbp 0x00000000004004f4 <+4>: mov $0x2a,%eax 0x00000000004004f9 <+9>: pop %rbp 0x00000000004004fa <+10>: retq End of assembler dump. (gdb) 

完整的debugging信息,甚至更好。

 (gdb) disassemble /m main Dump of assembler code for function main: 9 { 0x00000000004004fb <+0>: push %rbp 0x00000000004004fc <+1>: mov %rsp,%rbp 0x00000000004004ff <+4>: sub $0x10,%rsp 10 int x = fce (); 0x0000000000400503 <+8>: callq 0x4004f0 <fce> 0x0000000000400508 <+13>: mov %eax,-0x4(%rbp) 11 return x; 0x000000000040050b <+16>: mov -0x4(%rbp),%eax 12 } 0x000000000040050e <+19>: leaveq 0x000000000040050f <+20>: retq End of assembler dump. (gdb) 

objdump有一个类似的选项(-S)

Agner Fog的反汇编 , objconv ,相当不错。 它将为反汇编输出添加注释以解决性能问题(例如,来自具有16位立即数常量的指令的可怕的LCP失速)。

 objconv -fyasm a.out /dev/stdout | less 

(它不能识别-作为标准输出的简写,并默认输出到与input文件类似名称的文件,并添加.asm 。)

它还将分支目标添加到代码中。 其他反汇编程序通常只用一个数字目标来拆卸跳转指令,不要在分支目标上放置任何标记来帮助您find循环的顶部等等。

它也比其他反汇编更清楚地表明NOP(在有填充的情况下明确表示NOP,而不是像另一个指令那样拆分它)。

它是开放源代码的,并且易于为Linux编译。 它可以反汇编成NASM,YASM,MASM或GNU(AT&T)语法。

示例输出:

 ; Filling space: 0FH ; Filler type: Multi-byte NOP ; db 0FH, 1FH, 44H, 00H, 00H, 66H, 2EH, 0FH ; db 1FH, 84H, 00H, 00H, 00H, 00H, 00H ALIGN 16 foo: ; Function begin cmp rdi, 1 ; 00400620 _ 48: 83. FF, 01 jbe ?_026 ; 00400624 _ 0F 86, 00000084 mov r11d, 1 ; 0040062A _ 41: BB, 00000001 ?_020: mov r8, r11 ; 00400630 _ 4D: 89. D8 imul r8, r11 ; 00400633 _ 4D: 0F AF. C3 add r8, rdi ; 00400637 _ 49: 01. F8 cmp r8, 3 ; 0040063A _ 49: 83. F8, 03 jbe ?_029 ; 0040063E _ 0F 86, 00000097 mov esi, 1 ; 00400644 _ BE, 00000001 ; Filling space: 7H ; Filler type: Multi-byte NOP ; db 0FH, 1FH, 80H, 00H, 00H, 00H, 00H ALIGN 8 ?_021: add rsi, rsi ; 00400650 _ 48: 01. F6 mov rax, rsi ; 00400653 _ 48: 89. F0 imul rax, rsi ; 00400656 _ 48: 0F AF. C6 shl rax, 2 ; 0040065A _ 48: C1. E0, 02 cmp r8, rax ; 0040065E _ 49: 39. C0 jnc ?_021 ; 00400661 _ 73, ED lea rcx, [rsi+rsi] ; 00400663 _ 48: 8D. 0C 36 ... 

请注意,此输出已准备好汇编回目标文件,因此您可以在asm源代码级调整代码,而不是在机器代码中使用hex编辑器。 (所以你不限于保持相同的大小。)没有变化,结果应该是几乎相同的。 不过,这可能不是,因为反汇编这样的东西

  (from /lib/x86_64-linux-gnu/libc.so.6) SECTION .plt align=16 execute ; section number 11, code ?_00001:; Local function push qword [rel ?_37996] ; 0001F420 _ FF. 35, 003A4BE2(rel) jmp near [rel ?_37997] ; 0001F426 _ FF. 25, 003A4BE4(rel) ... ALIGN 8 ?_00002:jmp near [rel ?_37998] ; 0001F430 _ FF. 25, 003A4BE2(rel) ; Note: Immediate operand could be made smaller by sign extension push 11 ; 0001F436 _ 68, 0000000B ; Note: Immediate operand could be made smaller by sign extension jmp ?_00001 ; 0001F43B _ E9, FFFFFFE0 

在源代码中没有任何东西,以确保它组装到更长的编码,留下重定位的空间重写它与32位偏移量。


如果你不想安装它objconv,GNU binutils objdump -Mintel -d是非常有用的,并且如果你有一个普通的Linux gcc安装程序,就已经安装了。

使用IDA Pro和反编译器 。

还有ndisasm,它有一些怪癖,但如果你使用nasm可以更有用。 我同意迈克尔Mrozek objdump可能是最好的。

后来你可能也想看看Albert van der Horst的ciasdis: http : 它可能很难理解,但有一些有趣的function,你不可能在其他地方find。

你可能会发现ODA有用。 这是一个支持大量架构的基于Web的反汇编程序。

http://onlinedisassembler.com/

编辑器可以以多种格式反汇编二进制文件。 这与Hiew类似,但是开源。

要反汇编,打开一个二进制文件,然后按F6,然后select精灵/图像。