linux 下使用 objdump 反彙編
objdump有點象那個快速檢視之流的工具,就是以一種可閱讀的格式讓你更多地了解二進制檔案可能帶有的附加資訊。對于一般隻想讓自己程式跑起來的程式
員,這個指令沒有更多意義,對于想進一步了解系統的程式員,應該掌握這種工具,至少你可以自己寫寫shellcode了,或者看看人家給的exploit
中的shellcode是什麼東西。
目錄:
測試練習前的準備工作
Redhat 6.0 objdump指令的man手冊
objdump應用舉例(待增加)
相關指令
cp /usr/lib/libpcap.a /home/scz/src
nm -s libpcap.a | more
ar tv libpcap.a
ar xv libpcap.a inet.o
nm -s inet.o
關于nm -s的顯示請自己man nm檢視
objdump - 顯示二進制檔案資訊
objdump
[-a] [-b bfdname |
--target=bfdname] [-C] [--debugging]
[-d] [-D]
[--disassemble-zeroes]
[-EB|-EL|--endian={big|little}] [-f]
[-h] [-i|--info]
[-j section | --section=section]
[-l] [-m machine ] [--prefix-addresses]
[-r] [-R]
[-s|--full-contents] [-S|--source]
[--[no-]show-raw-insn] [--stabs] [-t]
[-T] [-x]
[--start-address=address] [--stop-address=address]
[--adjust-vma=offset] [--version] [--help]
objfile...
--archive-headers
-a 顯示檔案庫的成員資訊,與 ar tv 類似
objdump -a libpcap.a 和 ar -tv libpcap.a 顯示結果比較比較顯然這個選項沒有什麼意思。
--adjust-vma=offset
When
dumping information, first add offset to all the section addresses.
This is useful if the section addresses do not correspond to the symbol
table, which can happen when putting sections at particular addresses
when using a format which can not represent section addresses, such as
a.out.
-b bfdname
--target=bfdname
指定目标碼格式。這不是必須的,objdump能自動識别許多格式,
比如:objdump -b oasys -m vax -h fu.o
顯示fu.o的頭部摘要資訊,明确指出該檔案是Vax系統下用Oasys
編譯器生成的目标檔案。objdump -i将給出這裡可以指定的
目标碼格式清單
--demangle
-C 将底層的符号名解碼成使用者級名字,除了去掉所有開頭的下劃線之外,還使得C++函數名以可了解的方式顯示出來。
--debugging
顯示調試資訊。企圖解析儲存在檔案中的調試資訊并以C語言的文法顯示出來。僅僅支援某些類型的調試資訊。
--disassemble
-d 反彙編那些應該還有指令機器碼的section
--disassemble-all
-D 與 -d 類似,但反彙編所有section
--prefix-addresses
反彙編的時候,顯示每一行的完整位址。這是一種比較老的反彙編格式。顯示效果并不理想,但可能會用到其中的某些顯示,自己可以對比。
--disassemble-zeroes
一般反彙編輸出将省略大塊的零,該選項使得這些零塊也被反彙編。
-EB
-EL
--endian={big|little}
這個選項将影響反彙編出來的指令。
little-endian就是我們當年在dos下玩彙編的時候常說的高位在高位址,x86都是這種。
--file-headers
-f 顯示objfile中每個檔案的整體頭部摘要資訊。
--section-headers
--headers
-h 顯示目标檔案各個section的頭部摘要資訊。
--help 簡短的幫助資訊。
--info
-i 顯示對于 -b 或者 -m 選項可用的架構和目标格式清單。
--section=name
-j name 僅僅顯示指定section的資訊
--line-numbers
-l 用檔案名和行号标注相應的目标代碼,僅僅和-d、-D或者-r一起使用使用-ld和使用-d的差別不是很大,在源碼級調試的時候有用,要求編譯時使用了-g之類的調試編譯選項。
--architecture=machine
-m machine
指定反彙編目标檔案時使用的架構,當待反彙編檔案本身沒有描述架構資訊的時候(比如S-records),這個選項很有用。可以用-i選項列出這裡能夠指定的架構
--reloc
-r 顯示檔案的重定位入口。如果和-d或者-D一起使用,重定位部分以反彙編後的格式顯示出來。
--dynamic-reloc
-R 顯示檔案的動态重定位入口,僅僅對于動态目标檔案有意義,比如某些共享庫。
--full-contents
-s 顯示指定section的完整内容。
objdump --section=.text -s inet.o | more
--source
-S 盡可能反彙編出源代碼,尤其當編譯的時候指定了-g這種調試參數時,效果比較明顯。隐含了-d參數。
--show-raw-insn
反彙編的時候,顯示每條彙編指令對應的機器碼,除非指定了
--prefix-addresses,這将是預設選項。
--no-show-raw-insn
反彙編時,不顯示彙編指令的機器碼,這是指定 --prefix-addresses
選項時的預設設定。
--stabs
Display
the contents of the .stab, .stab.index, and .stab.excl sections from an
ELF file. This is only useful on systems (such as Solaris 2.0) in which
.stab debugging symbol-table entries are carried in an ELF section. In
most other file formats, debugging symbol-table entries are interleaved
with linkage symbols, and are visible in the --syms output.
--start-address=address
從指定位址開始顯示資料,該選項影響-d、-r和-s選項的輸出。
--stop-address=address
顯示資料直到指定位址為止,該選項影響-d、-r和-s選項的輸出。
--syms
-t 顯示檔案的符号表入口。類似于nm -s提供的資訊
--dynamic-syms
-T 顯示檔案的動态符号表入口,僅僅對動态目标檔案有意義,比如某些
共享庫。它顯示的資訊類似于 nm -D|--dynamic 顯示的資訊。
--version 版本資訊
objdump --version
--all-headers
-x 顯示所有可用的頭資訊,包括符号表、重定位入口。-x 等價于
-a -f -h -r -t 同時指定。
objdump -x inet.o
參看 nm(1)
/*
g++ -g -Wstrict-prototypes -Wall -Wunused -o objtest objtest.c
*/
#include
int main ( int argc, char * argv[] )
{
execl( "/bin/sh", "/bin/sh", "-i", 0 );
return 0;
}
objdump -j .text -Sl objtest | more
/main(查找)
08048750 :
main():
/home/scz/src/objtest.c:7
8048750: 55 pushl %ebp
8048751: 89 e5 movl %esp,%ebp
/home/scz/src/objtest.c:8
8048753: 6a 00 pushl $0x0
8048755: 68 d0 87 04 08 pushl $0x80487d0
804875a: 68 d3 87 04 08 pushl $0x80487d3
804875f: 68 d3 87 04 08 pushl $0x80487d3
8048764: e8 db fe ff ff call 8048644
8048769: 83 c4 10 addl $0x10,%esp
/home/scz/src/objtest.c:9
804876c: 31 c0 xorl %eax,%eax
804876e: eb 04 jmp 8048774
8048770: 31 c0 xorl %eax,%eax
8048772: eb 00 jmp 8048774
/home/scz/src/objtest.c:10
8048774: c9 leave
8048775: c3 ret
8048776: 90 nop
如果說上面還不夠清楚,可以用下面的指令輔助一下:
objdump -j .text -Sl objtest --prefix-addresses | more
objdump -j .text -Dl objtest | more
去掉調試編譯選項重新編譯
g++ -O3 -o objtest objtest.c
objdump -j .text -S objtest | more
08048778 :
8048778: 55 pushl %ebp
8048779: 89 e5 movl %esp,%ebp
804877b: 6a 00 pushl $0x0
804877d: 68 f0 87 04 08 pushl $0x80487f0
8048782: 68 f3 87 04 08 pushl $0x80487f3
8048787: 68 f3 87 04 08 pushl $0x80487f3
804878c: e8 db fe ff ff call 804866c
8048791: 31 c0 xorl %eax,%eax
8048793: c9 leave
8048794: c3 ret
8048795: 90 nop
與前面-g編譯後的二進制代碼比較一下,有不少差別。
至于如何寫shellcode、如何了解别人給出的shellcode,請參看華中站系統安全版精華區中的"如何寫自己的shellcode"
man objcopy
man nm
man gdb | dbx | sdb
###################################################################################################################
以上轉載内容
我測試了下while(1)和for(;;)循環的彙編比較:
g++ -g -Wstrict-prototypes -Wall -Wunused -o test main.cpp
objdump -j .text -Sl test > test.txt
while(1)
out = 2;
400a1f: c7 45 fc 02 00 00 00 movl $0x2,0xfffffffffffffffc(%rbp)
/home/lihe/hanxinsemi/trunk/sandbox/cplusplus/recursion/main.cpp:73
400a26: eb f7 jmp 400a1f <main+0x4d>
0000000000400a28 <_Z41__static_initialization_and_destruction_0ii>:
__static_initialization_and_destruction_0():
for(;;)
out = 1;
return 0;