1. Use objdump dump ELF binary
如果想 dump 每個 section 的 binary, 可以用objdump
$ objdump --full-contents /bin/ls Contents of section .interp: 400238 2f6c6962 36342f6c 642d6c69 6e75782d /lib64/ld-linux- 400248 7838362d 36342e73 6f2e3200 x86-64.so.2. Contents of section .note.ABI-tag: 400254 04000000 10000000 01000000 474e5500 ............GNU. 400264 00000000 02000000 06000000 18000000 ................ Contents of section .note.gnu.build-id: 400274 04000000 14000000 03000000 474e5500 ............GNU. 400284 64d095bc 6589dd4b fbf1c6d6 2ae98538 d...e..K....*..8 400294 5965461b YeF. Contents of section .gnu.hash: 400298 03000000 72000000 02000000 07000000 ....r........... 4002a8 a201400c 12010c3f 28440003 a8040000 ..@....?(D...... 4002b8 72000000 75000000 7e000000 281d8c1c r...u...~...(... 4002c8 4245d5ec bbe3927c bc50769e 86f0967c BE.....|.Pv....| 4002d8 96a08997 3cad390d d871581c ce2c6372 ....<.9..qX..,cr 4002e8 e46241f5 b88df10e 39f28b1c 32c4f712 .bA.....9...2... 4002f8 ead3ef0e b3a2f712 ........
但示通常會印出一堆, 所以通常會看特定的section
可以用 objdump 找 section
$ objdump --section-headers /bin/ls
/bin/ls:     file format elf64-x86-64
Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .interp       0000001c  0000000000400238  0000000000400238  00000238  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .note.ABI-tag 00000020  0000000000400254  0000000000400254  00000254  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .note.gnu.build-id 00000024  0000000000400274  0000000000400274  00000274  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .gnu.hash     00000068  0000000000400298  0000000000400298  00000298  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .dynsym       00000c18  0000000000400300  0000000000400300  00000300  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .dynstr       00000593  0000000000400f18  0000000000400f18  00000f18  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .gnu.version  00000102  00000000004014ac  00000000004014ac  000014ac  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .gnu.version_r 00000090  00000000004015b0  00000000004015b0  000015b0  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .rela.dyn     000000a8  0000000000401640  0000000000401640  00001640  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .rela.plt     00000a80  00000000004016e8  00000000004016e8  000016e8  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 10 .init         0000001a  0000000000402168  0000000000402168  00002168  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 11 .plt          00000710  0000000000402190  0000000000402190  00002190  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 12 .text         0000f65a  00000000004028a0  00000000004028a0  000028a0  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
......
找到想要印的section
$ objdump --full-contents --section .interp /bin/ls /bin/ls: file format elf64-x86-64 Contents of section .interp: 400238 2f6c6962 36342f6c 642d6c69 6e75782d /lib64/ld-linux- 400248 7838362d 36342e73 6f2e3200 x86-64.so.2.
也可以指定範圍, 比如說 .interp 從 0x400238 到 0x400253
$ objdump --full-contents --start-address=0x400238 --stop-address=0x400253 /bin/ls /bin/ls: file format elf64-x86-64 Contents of section .interp: 400238 2f6c6962 36342f6c 642d6c69 6e75782d /lib64/ld-linux- 400248 7838362d 36342e73 6f2e32 x86-64.so.2
如果指定的範圍超過 section 邊界的話, 它會將跨過的 section 名字也印出來
$ objdump --full-contents --start-address=0x400238 --stop-address=0x400280 /bin/ls /bin/ls: file format elf64-x86-64 Contents of section .interp: 400238 2f6c6962 36342f6c 642d6c69 6e75782d /lib64/ld-linux- 400248 7838362d 36342e73 6f2e3200 x86-64.so.2. Contents of section .note.ABI-tag: 400254 04000000 10000000 01000000 474e5500 ............GNU. 400264 00000000 02000000 06000000 18000000 ................ Contents of section .note.gnu.build-id: 400274 04000000 14000000 03000000 ............
如果只想把 ELF 檔案當 binary 來印, 或是想印某些純 binary 檔
$ objdump --full-contents -b binary /bin/ls
2. Use objdump to disassemble file
假如有個 "hello.c", 內容如下:
// hello.c
#include <stdio.h>
int main() {
        printf("Hello World\n");
        return 0;
}
然後 compile : "gcc -c -g hello.c", "gcc -o hello hello.o"
可以用 objdump 反組譯
$ objdump -d hello.o hello.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <main>: 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: bf 00 00 00 00 mov $0x0,%edi 9: e8 00 00 00 00 callq e <main+0xe> e: b8 00 00 00 00 mov $0x0,%eax 13: 5d pop %rbp 14: c3 retq
使用 -d (--disassemble) 反組譯, 通常只會包含執行碼的 section (.text之類的)
如果想反組譯所有 section, 可以使用 -D ( --disassemble-all ), 但是會把不是程式碼的部份也當成程式碼反組譯
反組譯的輸出格式是
address <symbol>
    address:    code byte sequence        disassemble result
如果不想看到 code byte sequence
$ objdump -d --no-show-raw-insn hello.o hello.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <main>: 0: push %rbp 1: mov %rsp,%rbp 4: mov $0x0,%edi 9: callq e <main+0xe> e: mov $0x0,%eax 13: pop %rbp 14: retq
如果想看到逐行加上 symbol 的位置
$ objdump -d --prefix-address hello.o hello.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <main> push %rbp 0000000000000001 <main+0x1> mov %rsp,%rbp 0000000000000004 <main+0x4> mov $0x0,%edi 0000000000000009 <main+0x9> callq 000000000000000e <main+0xe> 000000000000000e <main+0xe> mov $0x0,%eax 0000000000000013 <main+0x13> pop %rbp 0000000000000014 <main+0x14> retq此時 code byte sequence 就會被忽略, 如果想加回code byte sequence
$ objdump -d --prefix-address --show-raw-insn hello.o hello.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <main> 55 push %rbp 0000000000000001 <main+0x1> 48 89 e5 mov %rsp,%rbp 0000000000000004 <main+0x4> bf 00 00 00 00 mov $0x0,%edi 0000000000000009 <main+0x9> e8 00 00 00 00 callq 000000000000000e <main+0xe> 000000000000000e <main+0xe> b8 00 00 00 00 mov $0x0,%eax 0000000000000013 <main+0x13> 5d pop %rbp 0000000000000014 <main+0x14> c3 retq
如果只想反組譯特定的 section
$ objdump -d --section .init hello hello: file format elf64-x86-64 Disassembly of section .init: 00000000004003e0 <_init>: 4003e0: 48 83 ec 08 sub $0x8,%rsp 4003e4: 48 8b 05 0d 0c 20 00 mov 0x200c0d(%rip),%rax # 600ff8 <_DYNAMIC+0x1d0> 4003eb: 48 85 c0 test %rax,%rax 4003ee: 74 05 je 4003f5 <_init+0x15> 4003f0: e8 3b 00 00 00 callq 400430 <__gmon_start__@plt> 4003f5: 48 83 c4 08 add $0x8,%rsp 4003f9: c3 retq反組譯的部份跟之前一樣, 也可以設定 --start-address 以及 --stop-address
如果 object file 包含 debug information, 加上 -l (--line-numbers) 可以把指令與原始碼行號對應資訊印出來, 但如果 object file 沒有 debug information 就沒有任何效果
$ objdump -d -l hello.o hello.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <main>: main(): /home/william/temp/hello.c:3 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp /home/william/temp/hello.c:4 4: bf 00 00 00 00 mov $0x0,%edi 9: e8 00 00 00 00 callq e <main+0xe> /home/william/temp/hello.c:5 e: b8 00 00 00 00 mov $0x0,%eax /home/william/temp/hello.c:6 13: 5d pop %rbp 14: c3 retq
如果加上 -S (--source), 如果找的到原始檔就會顯示對應的原始碼, 但如果 object file 沒有 debug information 就沒有作用
$ objdump -d -S hello.o
hello.o:     file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
#include <stdio.h>
int main() {
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
        printf("Hello World\n");
   4:   bf 00 00 00 00          mov    $0x0,%edi
   9:   e8 00 00 00 00          callq  e <main+0xe>
        return 0;
   e:   b8 00 00 00 00          mov    $0x0,%eax
}
  13:   5d                      pop    %rbp
  14:   c3                      retq
-S 與 -l 可以同時使用其中可以注意的是, 在 printf 下面的 address 4, bf 00 00 00 00, 後面的位置都是00, 是因為檔案還沒 reallocate, 在 linking 之後才會嵌入位置
$ objdump -S hello ...... 000000000040052d <main>: 40052d: 55 push %rbp 40052e: 48 89 e5 mov %rsp,%rbp 400531: bf d4 05 40 00 mov $0x4005d4,%edi 400536: e8 d5 fe ff ff callq 400410 <puts@plt> 40053b: b8 00 00 00 00 mov $0x0,%eax 400540: 5d pop %rbp 400541: c3 retq 400542: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 400549: 00 00 00 40054c: 0f 1f 40 00 nopl 0x0(%rax) ......
可以看到執行檔裡已經嵌入位置 bf d4 05 40 00




