Linux下C程序的反匯編【轉】


轉自:http://blog.csdn.net/u011192270/article/details/50224267

前言:本文主要介紹幾種反匯編的方法。

gcc

gcc的完整編譯過程大致為:預處理->編譯->匯編->鏈接

前三個步驟分別對應了-E、-S、-c三個選項。

今天我要介紹的第一種方法就是使用-S這個選項。

源程序main.c:

/*************************************************************************  > File Name: main.c  > Author: AnSwEr  > Mail: 1045837697@qq.com  > Created Time: 2015年12月08日 星期二 20時06分19秒 ************************************************************************/ #include<stdio.h> int i = 1; int main(void) {  ++i;  printf("%d\n",i);  return 0; }

 

執行以下命令:

gcc -S -o main.s main.c

查看匯編源程序main.s:

    .file "main.c" .globl i .data .align 4 .type i, @object .size i, 4 i: .long 1 .section .rodata .LC0: .string "%d\n" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl i(%rip), %eax addl $1, %eax movl %eax, i(%rip) movl i(%rip), %eax movl %eax, %esi movl $.LC0, %edi movl $0, %eax call printf movl $0, %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size main, .-main .ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2" .section .note.GNU-stack,"",@progbits

 

哈哈,大家看是不是成功了?至於匯編程序的具體解釋則不在本文的討論范疇。

最后介紹一下gcc的具體過程:
參考: https://github.com/1184893257/simplelinux/blob/master/gcc.md#top

編譯階段 命令 截斷后的產物
    C源程序
預處理 gcc -E 替換了宏的C源程序(沒有了#define,#include…), 刪除了注釋
編譯 gcc -S 匯編源程序
匯編 gcc -c 目標文件,二進制文件, 允許有不在此文件中的外部變量、函數
鏈接 gcc 可執行程序,一般由多個目標文件或庫鏈接而成, 二進制文件,所有變量、函數都必須找得到

objdump

objdump是linux下一款反匯編工具,能夠反匯編目標文件、可執行文件。

主要選項:

objdump -f 顯示文件頭信息 objdump -d 反匯編需要執行指令的那些section objdump -D 與-d類似,但反匯編中的所有section objdump -h 顯示Section Header信息 objdump -x 顯示全部Header信息 objdump -s 將所有段的內容以十六進制的方式打印出來

 

目標文件

反匯編:

gcc -c -o main.o main.c objdump -s -d main.o > main.o.txt
  • 1
  • 2

查看匯編文件:


main.o: 文件格式 elf64-x86-64 Contents of section .text: 0000 554889e5 8b050000 000083c0 01890500 UH.............. 0010 0000008b 05000000 0089c6bf 00000000 ................ 0020 b8000000 00e80000 0000b800 0000005d ...............] 0030 c3 . Contents of section .data: 0000 01000000 .... Contents of section .rodata: 0000 25640a00 %d.. Contents of section .comment: 0000 00474343 3a202855 62756e74 7520342e .GCC: (Ubuntu 4. 0010 382e322d 31397562 756e7475 31292034 8.2-19ubuntu1) 4 0020 2e382e32 00 .8.2. Contents of section .eh_frame: 0000 14000000 00000000 017a5200 01781001 .........zR..x.. 0010 1b0c0708 90010000 1c000000 1c000000 ................ 0020 00000000 31000000 00410e10 8602430d ....1....A....C. 0030 066c0c07 08000000 .l...... Disassembly of section .text: 0000000000000000 <main>: 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # a <main+0xa> a: 83 c0 01 add $0x1,%eax d: 89 05 00 00 00 00 mov %eax,0x0(%rip) # 13 <main+0x13> 13: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 19 <main+0x19> 19: 89 c6 mov %eax,%esi 1b: bf 00 00 00 00 mov $0x0,%edi 20: b8 00 00 00 00 mov $0x0,%eax 25: e8 00 00 00 00 callq 2a <main+0x2a> 2a: b8 00 00 00 00 mov $0x0,%eax 2f: 5d pop %rbp 30: c3 retq 

 

可執行文件

反匯編:

gcc -o main main.c objdump -s -d main > main.txt

 

查看匯編文件(由於文件較大,只取部分展示):

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 Disassembly of section .plt: 0000000000400400 <printf@plt-0x10>: 400400: ff 35 02 0c 20 00 pushq 0x200c02(%rip) # 601008 <_GLOBAL_OFFSET_TABLE_+0x8> 400406: ff 25 04 0c 20 00 jmpq *0x200c04(%rip) # 601010 <_GLOBAL_OFFSET_TABLE_+0x10> 40040c: 0f 1f 40 00 nopl 0x0(%rax) 0000000000400410 <printf@plt>: 400410: ff 25 02 0c 20 00 jmpq *0x200c02(%rip) # 601018 <_GLOBAL_OFFSET_TABLE_+0x18> 400416: 68 00 00 00 00 pushq $0x0 40041b: e9 e0 ff ff ff jmpq 400400 <_init+0x20>

 

linux 下目標文件(默認擴展名是.o)和可執行文件都是 ELF 格式(文件內容按照一定格式進行組織)的二進制文件; 類似的,Windows 下 VISUAL C++ 編譯出來的目標文件 (擴展名是.obj)采用 COFF 格式,而可執行文件 (擴展名是.exe)采用 PE 格式, ELF 和 PE 都是從 COFF 發展而來的。

因為 linux 下目標文件和可執行文件的內容格式是一樣的, 所以 objdump 既可以反匯編可執行文件也可以反匯編目標文件。

總結

掌握了反匯編的方法,當你的程序遇到一些未知的變量錯誤等,可以直接反匯編來查看匯編代碼,一切一目了然。PS:匯編我已經忘得差不多了。

參考

  1. https://github.com/1184893257/simplelinux

反饋與建議

版權聲明:本文為博主原創文章,未經博主允許不得轉載。 http://blog.csdn.net/u011192270/article/details/50224267


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM