原文:https://www.securityartwork.es/2018/04/09/reversing-of-malware-network-protocols-with-angr/
在分析惡意二進位程式時,最困難的任務之一就是找出程式提供的所有功能。此外,如果程式具體執行哪些功能完全由攻擊者通過其控制中心進行遙控的話,局面就會變得更加複雜。由於某些原因,很多時候根本就無法進行全面的動態分析,例如惡意軟件基礎架構的崩潰或樣本的隔離導致惡意軟件無法與C&C進行通信,等等。在這些情况下,攻擊者的服務器與樣本之間的互動分析通常非常耗時,因為我們必須創建一個偽裝的服務器或不斷修補/欺騙樣本程式碼,才能考察所有不同的執行路徑。根據所分析程式碼的大小和複雜程度或分析目標的不同,這項任務的難度和廣度也會隨著時間的推移而不斷發生變化。
在本文中,我們以一個虛構的RAT為例,講解如何找出它的各種功能。其中,這個RAT會根據C&C面板的命令來執行某些功能。我們的目標是創建一個類比攻擊者的服務器。為此,我們必須瞭解服務器和安裝在受害者設備上的惡意軟件之間的通信協議。
在本文中,我們不會使用常見的反彙編和調試工具來分析樣本的內部工作機制,而是借助於一個新工具,即Angr來完成部分分析工作。Angr是一個分析二進位檔案的工作環境,可用來對程式碼進行靜態和動態符號分析。這個工具的用法也很豐富,具體請參攷其網站的介紹,同時,該網站也提供了很多具體的分析示例。在本例的分支分析中,我們將重點關注符號執行,即通過分析程式,以確定出執行程式碼的各個分支時必須滿足哪些分支條件。
由於該工具非常複雜,為了便於理解,請參攷下列連結,它對用於演示其用法的程式碼進行了簡要的分析:
https://gist.github.com/halos/15d48a46556645ae7ff2ecb3dfc95d73
上面的程式碼類比了一個通過函數call_home接收C&C命令的RAT。在該程式碼中,首先會初始化全域變數c2_resp的值,該變數用於存放假想的C&C命令。然後,執行exec_order函數,而該函數的作用,就是根據保存在c2_resp結構中的資訊來執行相應的操作。
該結構不同欄位的取值,已經在程式碼開頭部分以常數的形式給出了相應的定義。其中,包含了某些隨機值,目的是擾亂視聽,提高惡意軟件分析人員的工作難度。
但是,我們在實驗室中分析惡意軟件時,手頭上通常沒有對應的原始程式碼,只有編譯後的二進位檔案。如果我們編譯前面的C程式碼,得到的exec_order函數如下所示:
通過進一步的分析,可以將彙編程式碼組織成更容易理解的形式:
如圖所示,經過適當的組織,程式碼已經展現出更容易理解的結構,但它仍然還是一些程式碼,由於比較冗長,分析起來還是比較困難,例如當我們深入瞭解函數時,將會面對:
然而,在平常的惡意軟件中,程式的邏輯通常沒有這麼清晰,這倒不是因為惡意軟體作者不知道如何程式設計,而是因為他們總是設法提高惡意軟件的分析難度。
為了用Angr來研究這個樣本,我需要知道4個記憶體位址的值,以告訴該工具:
- 目標程式碼是從哪裡開始的?
- 它在哪裡結束?
- 到底要抵達哪些位置?
- 可以使用哪些變數?
其中,前兩個問題用於為Angr劃定待考察的所有路徑所在的範圍,這樣就可以避免將時間浪費在對本研究無用的路徑上了。對於第三個問題,用於確定那些需要仔細研究的記憶體區域的起始地址,然後將研究的重點放在這些區域就行了。第四個問題涉及存放服務器數據的“緩衝區”,對於該惡意軟件來說,當緩衝區的取不同的值時,它將去往第三個問題對應的不同區域。
從第一幅圖可以看出,待分析的函數的起始地址為0x0804844d,囙此,該地址將會賦值給常數START_ADDR。此外,待尋找的地址將存放到FIND_ADDRS清單中。例如,“push str.Creando_file:__ s”指令的地址0x8048483已經添加至該錶中,該指令來自創建檔案的執行分支(地址為0x804847b的區塊)。
對於其他程式碼,我們不做深入介紹,只需注意的是,這裡用C程式碼編譯得到的可執行文件a.out來初始化分析器,從而為其傳遞起始地址。此外,這裡也標出了服務器的響應緩衝區(BUFF_ADDR),這段記憶體將用於工作變數,同時,我也標出了從哪裡開始停止分析。最後,讓它探索所有帶有這些標識的程式碼,並以一種易於理解的管道輸出相應的結果:
出現的第一個條目的意思是說,如果C&C想要給這個bot發佈命令,它必須删除一個檔案(在地址0x80485050處執行該操作),這時會發送一個位元組內容為“00 E9 BB 64 D4 D4 01 1F AF 78 09 6E 00 00 00 00 00 00 00 00 00 00 00 00 00 00”的“緩衝區”。
接下來的輸出結果,解釋了如何通過BUFF_ADDR處的內容抵達該地址。應該注意的是,Angr是在比特級別上工作的,囙此表示只有20個位元組的緩衝區的時候,只用高位索引就行了(‘c2_resp_0_160[159:128]’)。
第一個約束條件表明,第四個DWORD必須包含值0x64bbe900(T_FILESYSTEM,可以從C原始程式碼中看出來)。但是,第三個位元組的內容有三個約束條件:它不可以是0xaff80c17和0xc6e6ef6b,並且還必須包含值0x1f01d4d4。不難看出,這裡只要有第三個約束條件就足够了,但是,之所以提出三個約束條件,自然有其道理:在類比執行時,Angr必須避免進入某些分支,所以第三個位元組不得出現使其進入條件分支的值。如果我們查看相應的C原始程式碼就會發現,對應於‘fs_order’欄位的第三個位元組,首先會與常數FSO_CREATE(第55行)和FSO_WRITE(第67行)進行比較,當它與常數FSO_DELETE(第71行)相等的時候,就會進入删除分支。
這些資訊能够幫助我們理解通信協議,一旦瞭解了該協定,我們就可以進一步獲得新IOC,搭建偽裝成攻擊者的服務器,實时修改示例緩衝區來直接瞭解某些功能,等等。