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檢視
★ Redhat 6.0 objdump命令的man手冊
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)
★ objdump應用舉例(待增加)
/*
g++ -g -Wstrict-prototypes -Wall -Wunused -o objtest objtest.c
*/
#include
#include
int main ( int argc, char * argv[] )
{
execl( "/bin/sh", "/bin/sh", "-i", 0 );
return 0;
}
g++ -g -Wstrict-prototypes -Wall -Wunused -o objtest objtest.c
objdump -j .text -Sl objtest | more
/main(查詢)
08048750 :
main():
/home/scz/src/objtest.c:7
*/
#include
#include
int main ( int argc, char * argv[] )
{
8048750: 55 pushl %ebp
8048751: 89 e5 movl %esp,%ebp
/home/scz/src/objtest.c:8
execl( "/bin/sh", "/bin/sh", "-i", 0 );
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
return 0;
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 :
main():
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