惡意樣本分析精要及實踐8-IDA使用(一)
聲明
由于傳播、利用此文所提供的信息而造成的任何直接或者間接的后果及損失,均由使用者本人負責,雷神眾測及文章作者不為此承擔任何責任。
雷神眾測擁有對此文章的修改和解釋權。如欲轉載或傳播此文章,必須保證此文章的完整性,包括版權聲明等全部內容。未經雷神眾測允許,不得任意修改或者增減此文章內容,不得以任何方式將其用于商業目的。
分子實驗室 https://molecule-labs.com/
前言
相關說明及聲明:
文章原文為K A, Monnappa. 2018年發表的《Learning Malware Analysis》,本文的相關內容均為相關內容翻譯及實踐記錄,僅為學術交流使用,如要引用請做原文引用如下所示:
[序號]K A, Monnappa. Learning Malware Analysis[M]. 2018.06. Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
許久沒更新了,由于前段時間精力放在另一邊,二進制這邊一直放小同學這邊維護,也是因為種種原因還是需要自己來把坑填完,近期接著之前的進度終于啃完了這一章,這里給大家繼續同步K A, Monnappa.《Forensic Learning Malware Analysis》精要翻譯,以及翻譯過程中的一些小實踐記錄。
此外,我們成立了一個二進制交流群大家對二進制方面如果有興趣歡迎來群里一起參與知識庫的維護,不定期組織交流,氛圍搞起來,讓有興趣的同學們有個歸屬~
dingding聯系@xtpeeps
使用IDA反匯編
代碼分析常用語了解惡意樣本內部源碼不可見時使用。
1. 代碼分析工具
代碼分析工具可以根據他們的功能、描述、數量進行分類。
反匯編程序是一個可以將機器語言轉匯編代碼;并且可以靜態代碼分析。靜態代碼分析可以在不執行二進制程序的時候讓你了解到程序的行為。
一個調試器是個應用程序同時也是可以反匯編代碼;除此之外也可以執行控制匯編二進制執行。使用調試工具,你不僅可以執行單條指令,或選擇函數,或執行整個程序。調試工具可以動態分析,還可以在程序執行的過程中檢查可疑的二進制。
反編譯器是一個將機器碼轉成更高級語言的程序(偽代碼)。反編譯器能夠很好輔助反推工程進程并能夠簡化工作。
2. 靜態代碼分析(使用IDA反匯編)
Hex-Rays IDA pro
https://www.hex-rays.com/products/ida/
IDA是最有影響力且流行的商業反編譯調試工具;常被用于逆向工程,惡意病毒分析以及脆弱性研究。IDA可以運行在不同平臺(macOS、Linux和windows)支持分析不同的文件類型(PE/ELF/Macho-O)。除商業版本之外,IDA還提供2個其他版本:IDA demo版本(評估版本)和IDA免費版本;兩個版本都有一定的限制,都可以反編譯32和64位windows程序,但是免費版無法調試二進制,demo版本無法調試64位二進制,demo版本也無法保存數據庫,并且demo版本和免費版都無法支持IDApython。
本部分和下一部分將會看下IDA pro的特征,并且使用IDA施行靜態代碼分析。這一部分僅包含與惡意代碼分析相關的功能。
IDA相關深入了解圖書推薦《The IDA Pro Book》by Chris Eagle
2.1 在IDA中加載二進制
IDA會像windows一樣加載文件到內存中。IDA可以通過判斷文件頭確定最可能適合的加載器。在選擇文件后IDA會加載對話框,用于確認合適的加載起和進程類型。文件設置(file option)選項是用于加載未識別的文件,一般使用該選項處理shellcode。默認情況下IDA不會在反編譯中加載PE頭和源部分。通過使用手動加載checkbox選項,可以手動選擇加載基址和加載位置,IDA將會在加載的每個部分包括PE頭給予相應的提示。點擊OK,IDA將文件加載到內存,并且開始反編譯相關代碼。
2.2 擴展IDA顯示
IDA桌面版結合了很多靜態分析工具的特征到一個單獨特窗口中。下面將對IDA卓敏啊版和它不同窗口進行介紹。其包含多個不同的標簽(IDA View-A,Hex View-1,等等),也可以通過點擊添加標簽按鈕或者點擊View/open subviews菜單進行添加。
2.2.1 反匯編窗口
當二進制文件被加載,IDA展示的窗口就是反匯編編輯窗口(也叫做IDA-view窗口),這是個主要窗口,用于分析和展示反匯編代碼,并且可以用于分析反匯編二進制。
IDA可以使用兩個模式展示反編譯的代碼:Graph view(graph diassembly view)和Text view(實際應該叫text diassembly view),默認進入的是graph view,這里可以使用空格快捷鍵進行切換。

在graph view模式下,IDA一次只顯示一個函數,在一個流程圖的窗口中函數在基本塊區中斷。這個模式可以快速識別分支和循環生命。在Graph view模式下,顏色和箭頭的指示方向都是根據判斷顯示的。條件跳轉使用紅色和綠色的箭頭,true條件用綠色箭頭表示,false使用紅色箭頭表示。藍色的箭頭是被用來表示無條件跳轉,循環使用的是向上的藍色的箭頭表示。在graph view中虛擬地址默認不顯示(每個基礎塊僅顯示最基本的信息展示)。如果需要顯示虛擬地址信息,需要點擊Options/general然后點擊Line prefixes以啟用。

下圖中可以觀察到條件跳轉中,綠色箭頭(條件true)進行跳轉,對應的虛擬地址也是跳轉,而紅色箭頭指向正常的數據流,虛擬地址為連續。

在text view模式中,整個反編譯目前處于線性方式展示。整個虛擬地址默認展示,
:格式。在text view窗口中最左邊的部分被稱為箭頭窗口,用于展示程序的非線性流。虛線箭頭代表條件跳轉,實線箭頭表示無條件跳轉,加粗的箭頭表示循。

2.2.2 函數窗口function widnow
函數窗口顯示所有IDA識別出來的函數,該窗口同時也顯示每個函數可以被找到的虛擬地址,每個函數的大小,以及其他函數相關信息。雙擊可以定位跳轉到對應函數的位置。每個函數與大量的標志相關聯(例如R、F、L等等標志)。通過F1按鈕可以獲取更多關于相關標志的幫助信息。一個有用的標志L標志,代表函數的庫函數。庫函數是編譯器產生而非惡意軟件作者編寫的函數;從代碼分析的角度來看,惡意樣本分析的重點應該在惡意代碼上,而不是庫函數本身。
2.2.3 輸出窗口out window
輸出窗口展示的是IDA以及IDA插件輸出的相關信息。這些對于分析惡意樣本以及樣本對系統操作分析提供很多信息。可以通過查看輸出在output窗口的內容可以獲取IDA執行加載過程中的相關信息。
2.2.4 十六進制窗口Hex view window
通過點擊HexView-1標簽可以展示Hex窗口。Hex窗口可以展示一系列的十六進制轉儲內容以及ASCII字符。默認情況下,十六進制窗口(hex window)。默認情況下十六進制窗口同步反編譯窗口(disassembly window)內容;也就是在反匯編窗口中選擇了一部分字節的數據,相應的在十六進制窗口中同樣的會進行標記高亮相關的內容,這對于標記內存地址很有幫助。
2.2.5 結構窗口structures window
點擊structures windows標簽,可以進入借口窗口。結構窗口展示程序使用的標準的數據結構,并且允許創建自建的數據結構。

2.2.6 引用窗口imports window
引用窗口是所有二進制程序引用的函數的列表。展示了引用的函數以及相關函數引用的庫函數內容。

2.2.7 出口窗口exports window
出口窗口展示的是程序出口函數的列,出口函數通常在DLL動態鏈接庫中,因此對于分析惡意樣本DLL時有用。
2.2.8 字符窗口string window
IDA默認不展示字符窗口,你可以通過點擊view/open subviews/strings(或者使用Shift+F12快捷方式打開)字符窗口。字符窗口展示的是從二進制和地址中能夠發現字符列表。默認情況下,字符窗口僅展示長度不小于5的null-terminated ASCII字符串。有些惡意樣本的二進制使用的是UNICODE字符。可以通過配置IDA顯示不同的字符,右擊Setup(或者Ctrl+U)檢測Unicode C-style(16比特),點擊ok即可。

2.2.9 段窗口segments window
段窗口可以通過view/open subviews/segments(或者使用shift+F7開啟)。段窗口是展示(.text,.data等等)部分內容的列表。顯示信息包括開始地址,以及結束地址,每個部分的內存權限。開始和結束的地址都有每個部分的虛擬地址的詳細說明,可用于定位對應內存中的位置。
2.3 使用IDA提高反匯編
本部分將結合之前相關的知識內容進行反編譯分析。考慮下面一個小程序從一個本地函數拷貝到另外一個變量中:
int main(){ int x=1; int y; y=x; return 0;}
以上代碼編譯之后在IDA反匯編之后如下:
.text:00401000 ; Attributes: bp-based frame ?.text:00401000.text:00401000 ; ? int __cdecl main(int argc, const char **argv, const char **envp).text:00401000 ? _main proc near.text:00401000.text:00401000 var_8= dword ptr -8 ?.text:00401000 var_4= dword ptr -4 ?.text:00401000 argc= dword ptr 8 ?.text:00401000 argv= dword ptr 0Ch ?.text:00401000 envp= dword ptr 10h ?.text:00401000.text:00401000 push ebp ? .text:00401001 mov ebp, esp ?.text:00401003 sub esp, 8 ? .text:00401006 mov ? [ebp+var_4], 1.text:0040100D mov eax, [ebp+var_4] ?.text:00401010 mov ? [ebp+var_8], eax.text:00401013 xor eax, eax .text:00401015 mov esp, ebp ?.text:00401017 pop ebp ?.text:00401018 retn
當加載可執行之后,IDA在每一個函數執行分析,反匯編確定棧框架。除此之外,使用大量的簽名和運行特殊算法匹配提供IDA識別反匯編函數。注意到?在執行過初始化分析之后,IDA添加了一個批注,用分號開頭;這意味著ebp寄存器被局部變量和函數參數使用(前章節提到的函數在ebp堆棧寄存器基址中)。在?中,IDA使用其規則可以確定main函數并添加在關于此函數的批注,這一特點可以用于確定函數需要接收多少個參數,以及參數的類型。
在?中,IDA提供了一個總的棧的視角,IDA能夠判斷局部變量和函數參數。在主函數中IDA定義兩個局部變量,并自動命名為var_4和var_8并分別賦值。-4和-8對應著與dbp(框架指針)的距離。?和?是IDA替換[ebp-4]與[ebp-8]的內容。
IDA會自動對變量或參數進行命名,并在代碼中應用這些名稱;IDA標記的var_xxx和arg_xxx可以節約人工標記并替換參數的工作,并便于識別變量名和參數。
function prologue, funcktion epilogue和在?中用于分配的空間給局部變量的指令可以簡易的忽略。這些函數僅用于設定函數的環境。梳理之后匯編代碼簡化為:
.text:00401006 mov [ebp+var_4], 1.text:0040100D mov eax, [ebp+var_4].text:00401010 mov [ebp+var_8], eax.text:00401013 xor eax, eax.text:00401018 retn
2.3.1 重命名地址
當分析惡意病毒的時候,可以將這些變量或函數改成更有意義的名字。有勁啊變量或者參數名,選擇重命名(rename或者按快捷鍵“N”)。當重命名之后IDA將會同步新名字到與其相關的項目上。通過重命名可以給予變量或函數更加有意義的名字。
.text:00401006 mov [ebp+x], 1.text:0040100D mov eax, [ebp+x].text:00401010 mov [ebp+y], eax.text:00401013 xor eax, eax.text:00401018 retn
2.3.2 IDA標注功能
標注對于提示某一函數的作用很有幫助。為了添加一個合規的注釋,首先將光標放在任何一個反編譯列表里的一行中,然后使用快捷鍵(“:”),通過在新的對話框中填寫相關信息并確定,完成相關備注。
.text:00401006 mov [ebp+x], 1.text:0040100D mov eax, [ebp+x].text:00401010 mov [ebp+y], eax.text:00401013 xor eax, eax.text:00401018 retn
常規的備注對于單行描述但行比較有用(多行也可以),但是如果可以把描述匯總到一起描述,類似主函數的描述就更好了。IDA提供了另一種備注,函數備注,允許組合備注,并且可以顯示在函數反匯編列中。首先選擇函數所在的虛擬地址,然后通過快捷鍵“:”添加備注即可,這里為sub_140001230,偽代碼添加函數備注。可以看到這些備注與函數使用相同的虛擬地址。

當前相關修改參數變量名稱、添加備注的名稱都只保存在IDA的數據庫中,并沒有保存在二進制可執行文件中。
2.3.3 IDA 數據庫
當可執行文件加載到IDA中,就會在工作目錄中創建一個數據庫該數據庫一共包含5個文件(擴展名為:.id0,.id1,.nam,.id2以及.til)。每一個文件保存了大量的與可執行文件匹配的相關信息。這些文件被壓縮和歸檔到以.idb(32進制)壓縮文件中。當加載可執行程序后,從中讀取創建信息保存在數據庫中。大量的信息展都保存在數據庫中以用于展示代碼分析時有用的信息。任何的修改操作(如重命名,注釋批注等等)都會顯示在view中并且般存在數據庫中,但是這些修改并不會修改原二進制文件。你可以通過關閉IDA保存數據庫;當關閉IDA的時候將會提示是否保存數據庫的提示框。默認情況下數據庫包配置(默認配置)會將所有文件保存在IDB(.idb)或者i64(.i64)。當重新打開.idb或者.i64文件的時候,會看到重命名的變量和標注都在。
下面通過另一個簡單的程序了解IDA的其他擴展特征。全局變量a、b,在主函數中賦值。參數x、y以及string為局部變量;a賦值給x,y和string都是保存的地址。
int a;char b;int main(){ a = 41; b = 'A'; int x = a; int *y = &a; char *string = "test"; return 0;}
程序轉化為下面的反匯編列表。IDA也定義了全局變量和匹配名字例如dword_403374和byte_403370;記錄如何補充內存地址并且在全局變量中被關聯。當一個變量被定義之后在全局數據區域,對編譯器來說變量的地址和變量的大小是明確的。全局的假的變量名被IDA詳細知名變量的地址以及他們確切的數據類型。例如dword_403374則是說地址為0x403374可以接受dword(4bytes大小)的值。
IDA使用offset關鍵字表示變量地址被使用(而不是現實他們的值),當var_8、var_c被分配局部變量值時,可以認為他們被分配了值(指針變量值)。IDA使用aTest給地址確定字符(字符變量),這個名用于表示字符串,test用于添加批注。
.text:00401000 var_C= dword ptr -0Ch ? .text:00401000 var_8= dword ptr -8 ? .text:00401000 var_4= dword ptr -4 ? .text:00401000 argc= dword ptr 8.text:00401000 argv= dword ptr 0Ch.text:00401000 envp= dword ptr 10h.text:00401000.text:00401000 push ebp.text:00401001 mov ebp, esp.text:00401003 sub esp, 0Ch.text:00401006 mov ? dword_403374, 29h .text:00401010 mov ? byte_403370, 41h .text:00401017 mov eax, dword_403374 ? .text:0040101C mov [ebp+var_4], eax.text:0040101F mov [ebp+var_8], offset dword_403374 ? .text:00401026 mov [ebp+var_C], offset aTest ; "test" ?.text:0040102D xor eax, eax.text:0040102F mov esp, ebp.text:00401031 pop ebp.text:00401032 retn
2.3.4 格式化轉化操作數
在?和?中操作數(29h和41h)代表16進制格式數值,然而在源碼中我們使用十進制的41和字符“A”。IDA可以將16進制值編碼為十進制、八進制、二進制。ASCII也可以轉為字符型。例如,如果要修改41h格式的值,右擊在這個值上選擇即可。

2.3.5 導航地址
IDA的另一個特征是可以在程序中導航任意地址更加方便。當程序被反編譯,IDA就會標記每一個程序中的地址,雙擊字符則會在顯示中跳轉到對應字符所在的位置。如函數名或變量。
IDA保持跟蹤導航歷史;任何時候被重定向到另外一個地址,都可以使用返回按鈕返回之前的地址。

跳轉到指定地址可以點擊jump/jump to Address(或者使用快捷鍵G)來跳轉到地址。點擊OK完成跳轉。
2.3.6 交叉參考cross References
其他方式導航是通過交叉參考實現(也稱為Xrefs)。交叉參考鏈接與地址鏈接關聯。交叉參考可以不僅數據交叉,也可以代碼交叉參考。
數據交叉參考描述了數據在二進制中如何交互。如?、?、?。例如數據交叉,?描述的是數據與命令相關聯,從主函數開始偏移0x6長度。字符w表示一個交叉關聯寫;代表命令寫入內存地址。字符r代表讀相互關聯,代表從內存中讀取信息。省略號...代表更多相關聯,但是他們由于顯示限制不能顯示。其他種類的關聯數據是一個補充(使用o表示),代表地址正在被使用,而不是內容。數組和字符型數組被開始的地址使用,因為字符數據?被標記為一個參考偏移值。
.data:00403000 aTest db 'test',0 ?; DATA XREF: _main+26o Similarly, double-clicking on the address dword_403374 relocates to the virtual address shown here: .data:00403374 dword_403374 dd ? ?; DATA XREF: _main+6w .data:00403374 ?; _main+17r ...
一個代碼交叉參考代表一個到另一個的數據流(如jump或者function調用),下面顯示的一個c語言的if語句:
int x = 0;if (x == 0){ x = 5;}x = 2;
程序反編譯如下,jnz反編譯為C語言中==條件語句(也就是jne或者jump,if not equal的別名);執行結束將會執行分支(如? to ?)。jump交叉關聯命令?為jump天轉后直行的命令,從主函數偏移0xF。字符j表示jump跳轉后的結果。這里可以雙擊(_main+Fj)來改變跳轉命令關聯的顯示。
.text:00401004 mov [ebp+var_4], 0.text:0040100B cmp [ebp+var_4], 0.text:0040100F jnz short loc_401018 ?.text:00401011 mov [ebp+var_4], 5.text:00401018.text:00401018 loc_401018: ?; CODE XREF: _main+Fj.text:00401018 ? mov [ebp+var_4], 2
之前的列可以通過按空格鍵切換視圖查看。graph視角對于獲取虛擬分支/循環說明特別有用。綠色箭頭為跳轉條件滿足,紅色箭頭為跳轉條件不滿足,藍色箭頭為正常部分。
下面針對函數內調用函數的情況來看:
void test() { }void main() { test();}
下面是main函數的反匯編列表。sub_401000代表了test函數。IDA自動使用sub_前綴命函數地址,指向子函數或者函數。例如當看到sub_401000(你可以直接把它當作子函數地址sub_401000閱讀)。當然這里也可以通過雙擊函數名定位到函數。
.text:00401010 push ebp.text:00401011 mov ebp, esp.text:00401013 call sub_401000 ?.text:00401018 xor eax, eax
在sub_401000(test函數)開始處,IDA添加了一處代碼交叉關聯代碼,用于代表這是函數,sub_401000,位于主函數main偏移3的位置,可以通過雙擊_main+3p跳轉到該位置。p后綴代標控制器調用地址為(0x401000)函數的結果并繼續后續的執行。
.text:00401000 sub_401000 proc near ?; CODE XREF: _main+3p.text:00401000 push ebp.text:00401001 mov ebp, esp.text:00401003 pop ebp.text:00401004 retn.text:00401004 sub_401000 endp
2.3.7 列出所有交叉引用
交叉參考可以在審計代碼的過程中快速定位字符或者函數的引用。IDA的交叉引用是定位地址的不錯的方式,但是只能顯示2個參數,因此你不會看到所有的交叉參考。另外...代表還有更多的交叉引用。
如果想要列出所有的交叉參考只需要點擊地址名然后按X。

一個程序通常包含很多函數。一個函數可以被一個或多個函數調用,或者調用一個或多個函數。在樣本分析的時候,為了快速瀏覽一個函數的相關信息,例如在本例中,你可以通過選擇view | open subviews | function calls 來獲取函數的函數調用情況。如圖所示上半部分展示函數被調用情況,下半部分展示函數調用其他函數情況。通過函數調用情況,一般就可以判斷這個函數的功能情況。

2.3.8 相鄰視角和圖形化
IDA圖形化選項是一個很好的形象化展示交叉引用的方式。在IDA圖形化之前,可以使用相鄰視角proximity view展示函數調用情況。點擊view | open subviews | proximity browser。相鄰視角中國呢,函數的數據通過節點以及交叉引用相互關聯。你可以通過雙擊“+”鉆入相鄰節點函數/子函數,擴展/折疊節點。同時可以通過ctrl+鼠標滑輪,控制放大和縮小。退出相鄰視角只需要在空白處右鍵,選擇圖形視圖后者字符視圖即可。

與自帶的視圖不同,IDA還可以展示第三方應用。要使用這些圖形配置,可以右鍵工具欄,選擇Graphs,會顯示5個按鈕:

通過點擊這5個不同的視圖,可以分別展示不同的展示方式,但是這5個視圖不像圖形化和相鄰視角基于匯編視圖可以交互。下面是不同的圖形對應的不同的功能介紹:
展示當前函數的外部流圖表。展示的圖形與IDA的交互視角很像。 展示當前函數的調用視圖;這可以用來快速查看程序中函數調用關系情況;但如果程序的函數很多的話,這個視圖就會顯得非常大,被塞滿。 這個視圖顯示一個函數的被交叉引用情況;如果想看一個程序的訪問某個函數的不同路徑,這個視圖就相對比較清晰。 這個視圖展示的是一個函數的交叉引用其他函數的情況;可以很清晰的展示函數調用所有其他函數。 這是一個自定義交叉引用視圖,這個功能可以允許使用者定義交叉引用的一些視圖生成內容和方式。 |
實踐IDA的各項功能有助于提高逆向的水平。下面我們將根據windowsAPI影響我們的windows操作系統。我們將學到如何分辨以及解釋32位和64位Windows API的功能。




