網(wǎng)絡(luò)安全攻防:軟件逆向之反匯編
1. 逆向工程
逆向工程(RE,Reverse Engineering)是一種技術(shù)過程,即對(duì)一項(xiàng)目標(biāo)產(chǎn)品進(jìn)行逆向分析及研究,從而演繹并得出該產(chǎn)品的處理流程、組織結(jié)構(gòu)、功能性能規(guī)格等設(shè)計(jì)要素,以制作出功能相近,但又不完全一樣的產(chǎn)品。逆向工程源于商業(yè)及軍事領(lǐng)域中的硬件分析。其主要目的是,在不能輕易獲得必要的生產(chǎn)信息下,直接從成品的分析,推導(dǎo)出產(chǎn)品的設(shè)計(jì)原理。
2. 基本概念
機(jī)器碼(Machine Code):電腦CPU可直接解讀的數(shù)據(jù),也被稱為原生碼(Native Code),與運(yùn)行平臺(tái)有關(guān)。
匯編語言(Assembly Language):用助記符代替機(jī)器指令的操作碼,用地址符號(hào)或標(biāo)號(hào)代替指令或操作數(shù)的地址,方便程序員編寫代碼。匯編語言和特定的機(jī)器語言指令集是一一對(duì)應(yīng)的,不同平臺(tái)之間不可直接移植。主流的有ARM匯編和x86匯編。
CPU寄存器:用來暫時(shí)存儲(chǔ)指令、數(shù)據(jù)和地址,包括通用寄存器、專用寄存器和控制寄存器。逆向分析時(shí)需要注意特殊寄存器的變化。
WinAPI:Windows 操作系統(tǒng)中可用的內(nèi)核應(yīng)用程序編程接口,在 Windows 平臺(tái)研究學(xué)習(xí)逆向工程需要了解一些WinAPI編程。
3. 反匯編
反匯編是把目標(biāo)代碼轉(zhuǎn)化為匯編代碼、將低級(jí)代碼轉(zhuǎn)化為高級(jí)代碼的過程。
以最著名的HelloWorld為例,先在Visual Studio中新建一個(gè)HelloWorld項(xiàng)目如下所示。
- //HelloWorld.cpp: 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。
- #include"stdafx.h"
- #include<stdio.h>
- int_tmain(int argc,_TCHAR*argv[])
- {
- printf("HelloWorld\n");
- return 0;
- }
在生成→配置管理器→活動(dòng)解決方案配置選擇Release。選擇Release模式生成可執(zhí)行文件,程序代碼會(huì)更簡潔,方便調(diào)試,如圖1所示。
圖1 Release模式
此時(shí)生成的是HelloWorld.exe的可執(zhí)行文件,已經(jīng)不能直接看到程序的源碼。通過該可執(zhí)行文件還原出匯編代碼的過程就是反匯編。我們用OllyDbg加載該程序可以輕松地看到反匯編代碼,如圖2所示。
圖2 反匯編代碼
4. 常見的工具
OllyDbg是一個(gè)新的動(dòng)態(tài)追蹤工具,將IDA與SoftICE結(jié)合起來的思想,Ring 3級(jí)調(diào)試器,非常容易上手,已代替SoftICE成為當(dāng)今最為流行的調(diào)試解密工具。同時(shí)還支持插件擴(kuò)展功能,是目前最強(qiáng)大的調(diào)試工具。運(yùn)行界面如圖3所示。
圖3 OllyDbg運(yùn)行界面
IDA Pro 32/64:IDA Pro簡稱IDA(Interactive Disassembler),是一個(gè)世界頂級(jí)的交互式反匯編工具,有兩種可用版本。標(biāo)準(zhǔn)版(Standard)支持20多種處理器,高級(jí)版(Advanced)支持50多種處理器,運(yùn)行界面如圖4所示。
圖4 IDA Pro運(yùn)行界面
SoftIce:SoftIce是Compuware NuMega公司的產(chǎn)品,是Windows2000及之前的內(nèi)核級(jí)調(diào)試工具,兼容性和穩(wěn)定性極好,可在源代碼級(jí)調(diào)試各種應(yīng)用程序和設(shè)備驅(qū)動(dòng)程序,也可使用TCP/IP連接進(jìn)行遠(yuǎn)程調(diào)試。但目前微軟的Windbg方便性、可靠性及可用性遠(yuǎn)遠(yuǎn)超出SoftICE,且免費(fèi)使用。所以SoftIce并沒有推后續(xù)版本。
WinDbg:WinDbg 是在 Windows 平臺(tái)下,強(qiáng)大的用戶態(tài)和內(nèi)核態(tài)調(diào)試工具。相比較于Visual Studio,它是一個(gè)輕量級(jí)的調(diào)試工具,所謂輕量級(jí)指的是它的安裝文件大小較小,但是其調(diào)試功能,卻比Visual Studio更為強(qiáng)大。它的另外一個(gè)用途是可以用來分析Dump數(shù)據(jù),程序運(yùn)行如圖5所示。
圖5 WinDbg運(yùn)行界面
5. 分類識(shí)別工具
在第一次拿到一個(gè)文件時(shí),我們需要確定這是一個(gè)什么類型的文件。通??梢酝ㄟ^文件擴(kuò)展名確定。有時(shí)候文件擴(kuò)展名并沒有什么實(shí)際意義,所以不能通過擴(kuò)展名來確定文件類型。
(1)file
在大多數(shù) Linux 系統(tǒng)中都帶有這個(gè)實(shí)用工具。file 通過檢查某些特定字段來確定文件類型,如下。
- root@kail:~/Desktop# file HelloWorld.exe
- HelloWorld.exe: PE32 executable for MS Windows(console)Intel 80386 32-bit
- root@kali:~/Desktop# file a
- a:ASCII text
常見命令:file[-bchikLnNprsvz][-f namefile][-F separator][-mmagicfiles]file。命令參數(shù)及描述如表1所示。
表1 file命令參數(shù)及描述
(2)PE tools
PE tools用于分析Windows系統(tǒng)中正在運(yùn)行的進(jìn)程和可執(zhí)行文件,主界面如圖6所示,列出了所有活動(dòng)進(jìn)程和每個(gè)進(jìn)程調(diào)用的動(dòng)態(tài)鏈接庫。
圖6 PE tools主界面
(3)PEiD
PEiD 是一款著名的查殼工具,其功能強(qiáng)大,幾乎可以偵測出所有的殼,其數(shù)量已超過470種PE文檔的加殼類型和簽名,運(yùn)行界面如圖7所示。
圖7 PEiD運(yùn)行界面
6. 摘要工具
一般情況下,我們可以獲得的都是二進(jìn)制程序文件,所有也只能對(duì)二進(jìn)制程序進(jìn)行逆向。在對(duì)文件有了初步的了解和分類后,需要對(duì)特定的文件格式進(jìn)行解析。
(1)nm
nm是names的縮寫。nm命令主要是用來列出某些文件中的符號(hào),如一些函數(shù)和全局變量。在Linux下面重新編譯生成了Helloworld,用nm命令分別查看效果,命令:nm Helloworld,運(yùn)行如下。
- root@kali:~/Desktop# nm Helloworld
- 00000000006008e8 B __bss_start
- 00000000006008e8 b completed.6979
- 00000000006008d8 D __data_start
- 00000000006008d8 W data_start
- 0000000000400420 t deregister_tm_clones
- 00000000004004a0 t__do_global_dtors_aux
- 00000000006006c8 t__do_global_dtors_aux_fini_array_entry
- 00000000006008e0 D__dso_handle
- 00000000006006d8 d_DYNAMIC
- 00000000006008e8 D_edata
- 00000000006008f0 B_end
- 0000000000400574 T_fini
- 00000000004004c0 t frame_dummy
- 00000000006006c0 t__frame_dummy_init_array_entry
- 00000000004006b8 r__FRAME_END__
- 00000000006008b0 d_GLOBAL_OFFSET_TABLE_
- w__gmon_start__
- 0000000000400590 r__GNU_EH_FRAME_HDR
- 0000000000400390 T_init
- 00000000006006c8 t__init_array_end
- 00000000006006c0 t__init_array_start
- 0000000000400580 R_IO_stdin_used
- w_ITM_deregisterTMCloneTable
- w_ITM_registerTMCloneTable
- 00000000006006d0 d__JCR_END__
- 00000000006006d0 d__JCR_LIST__
- w_Jv_RegisterClasses
- 0000000000400570 T__libc_csu_fini
- 0000000000400500 T__libc_csu_init
- U__libc_start_main@@GLIBC_2.2.5
- 00000000004004e6 T main
- U puts@@GLIBC_2.2.5
- 0000000000400460 t register_tm_clones
- 00000000004003f0 T_start
- 00000000006008e8 D__TMC_END__
輸出字符含義如表2所示。
表2 輸出字符含義
(2)ldd
ldd(List Dynamic Dependencies)是Linux上自帶的腳本,用來列出可執(zhí)行文件所需的動(dòng)態(tài)庫。命令:ldd Helloworld。
- root@kali:~/Desktop#ldd Helloworld
- linux-gate.so.1=>(0xb77ef000)
- libc.so.6=>/lib/tls/i686/cmov/libc.so.6(0xb7683000)
- /lib/ld-linux.so.2(0xb77f0000)
(3)Objdump
Objdump 是一個(gè)十分強(qiáng)大的工具,可以靈活地查詢文件的各種信息,有大概 30個(gè)可選項(xiàng),可以通過objdump –help查詢。簡單查看反匯編代碼使用如下:Objdump-d helloworld,運(yùn)行部分如下。
- root@kaili:~/Desktop# objdump-d Helloworld
- HelloWorld:文件格式 elf64-x86-64
- Disassembly of section.init:
- 0000000000400390 <_init>:
- 400390:48 83 ec 08 sub $0x8,%rsp
- 400394:48 8b 05 0d 05 20 00 mov 0x20050d(%rip),%rax #6008a8<_DYNAMIC+0x1d0>
- 40039b:48 85 c0 test %rax,%rax
- 40039e: 74 05 je 4003a5<_init+0x15>
- 4003a0: e8 3b 00 00 00 callq 4003e0<__libc_start_main@plt+0x10>
- 4003a5: 48 83 c4 08 add $0x8,%rsp
- 4003a9: c3 retq
- Disassembly of section.plt:
- 00000000004003b0 <puts@plt-0x10>:
- 4003b0:ff 35 02 05 20 00 pushq 0x200502(%rip) # 6008b8<_GLOBAL_OFFSET_TABLE_+0x8>
- 4003b6:ff 25 04 05 20 00 jmpq *0x200504(%rip) # 6008c0<_GLOBAL_OFFSET_TABLE_+0x10>
- 4003bc: 0f 1f 40 00 nopl 0x0(%rax)
(4)Otool
可以獲取OS X二進(jìn)制文件的相關(guān)信息。類似objdump的實(shí)用工具。
(5)Dumpbin
微軟VisualStudio工具套件里的一個(gè)命令行工具。主要用于Windows PE文件相關(guān)信息的獲取。用法類似Objdump。
7. 深度檢測工具
strings實(shí)用工具專門用于提取文件中的字符串內(nèi)容,通常使用該工具不會(huì)受到文件格式的限制。使用strings的默認(rèn)設(shè)置(至少包含4個(gè)字符的7位ASCII序列)。用strings對(duì)Helloworld進(jìn)行檢測,部分代碼如下。
- root@kaili:~/Desktop# strings Helloworld
- /lib64/ld-linux-x86-64.so.2
- libc.so.6
- puts
- __libc_start_main
- __gmon_start__
- GLIBC_2.2.5
- AWAVA
- AUATL
- []A\A]A^A_
- HelloWorld