靜態逆向工程Shellcode技術(上)
Metasploit是一款開源的安全漏洞檢測工具,可以幫助安全和IT專業人士識別安全性問題,驗證漏洞的緩解措施,并管理專家驅動的安全性進行評估,提供真正的安全風險情報。這些功能包括智能開發,代碼審計,Web應用程序掃描,社會工程。團隊合作,在Metasploit和綜合報告提出了他們的發現。
本文研究的惡意樣本的MD5哈希:9d7e34250477acf632c6c32fc2c50d3b。
Shllcode分析第1階段:靜態分析
首先,你要在你選擇的反匯編程序中打開shellcode ,我個人更喜歡IDA Pro,但是我不會使用偽代碼功能,而是將重點放在反匯編視圖上,因此這應該適用于你選擇的任何工具。通過IDA Pro,你可以選擇如何加載二進制數據(16位、32位或64位),因此,我將首先選擇32位,如果反匯編有任何錯誤,我們可以對其進行簡單地更改。加載二進制文件后,選擇第一個字節并按“ C”,這將嘗試將第一個字節轉換為代碼。因此,重新分析該文件,然后嘗試將其余字節反匯編為部件。如下所示,入口點從位置0x00開始,shellcode一直向上到達位置0x2A,此時IDA無法將剩余的字節轉換為程序集。
僅基于這個事實,我們就可以假定這部分數據是以某種方式加密的,并且上面的shellcode解密并執行它。因此,讓我們來看看第一個要運行的函數sub_0()。此函數僅負責跳轉到偏移量0x25,它將執行sub_2(),我將其命名為main_func(),因為它包含了大部分代碼,因此,讓我們繼續研究該函數。
因此,這個函數內部的解密相當簡單,只是一個基本的XOR循環,它將[edi]指向的XOR數據與[esi]指向的數據結合起來。在每一次XOR操作之后,edi(存儲器地址)都會增加,并且程序會將[esi:esi + 1]與0x550D進行比較。在本例中,IDA以Little-Endian顯示該值,,因此它被顯示為0x0D55。如果值匹配,它將跳到ecx指向的地址,否則它將增加esi,將它現在指向的數據與0x73進行比較,如果匹配,它將恢復原始地址(存儲在ebx中)。如果不匹配,它將循環回到XOR代碼并繼續。
基于以上分析,我們知道esi用作密鑰,而edi被用作加密的shellcode。我們還知道密鑰長度可以是任何長度,并且ebx將包含指向密鑰首字節的地址。
利用所有這些信息,讓我們首先嘗試找出加密數據的開始和停止位置。從XOR循環(loc_F)開始并向上移動。我們可以首先看到存儲在edi中的地址被移動到ecx中,這是有意義的,因為一旦解密完成,程序就會跳轉到ecx中的地址。
現在,我們找到edi從ebx處獲取加密代碼地址,在函數的最頂部,彈出堆棧頂部的值,并將其存儲在ebx中,然后將該值移到edi中,然后將0x73移動到eax的較低位,調用cld,然后輸入a scasb循環。問題是,當它彈出ebx時,堆棧的頂部是什么?
好了,簡單地看一下調試器中的堆棧,可以發現,當調用一個函數時,堆棧頂部的值是要返回的地址,這是調用指令之后的指令地址。在下圖中,返回地址為0x013B1CAB,調用該函數的地址為0x013B1CA6(此處的調用指令占用5個字節)。那么,這如何適用于我們的shellcode?
上面我們說過,main_func是從位置0x25調用的。無法識別的數據從0x2A開始。位置0x25之后的5個字節可為調用指令騰出空間。因此,main_func()中位于堆棧頂部的數據為值0x2A。現在,我們終于知道了加密數據的起始位置!
不過不要高興得太早,還記得0x73移入al后如何調用cld嗎? cld指令負責刪除(設置為0)EFLAGS寄存器中的DF(direction)標志。當此標志為0時,任何字符串操作都會根據操作中使用的寄存器來遞增索引寄存器,尤其是esi或edi。調用cld后,將進入一個循環,該循環不斷執行scasb,直到ZF(0)標志被設置(設置為1)。 scasb會做什么?它所做的只是將al中的字節與[edi]進行比較,并根據結果設置狀態標志。如果不匹配,則ZF將保持刪除狀態,否則將被設置,并且程序會跳出循環。此外,由于scasb是字符串操作,因此它將在每個循環后增加edi中的地址,這意味著直到[edi]等于0x73為止,程序將永遠不會執行解密功能。現在我們知道,加密的數據從0x73開始,密鑰是從地址0x2A一直到[address] = 0x73的數據。如上圖所示,0x73是ebx指向的數據中的第二個字節。因此,XOR密鑰為0x06,加密的數據從0x2B開始!向下滾動到函數的最后,我們可以找到字節0x550D,這意味著加密的數據長401個字節!
了解了所有內容之后,讓我們進入解密階段!
Shllcode分析第2階段:解密
因此,我們現在有了XOR密鑰:0x06,以及加密數據開始的位置:0x2B。有了這些知識,我們就可以輕松地用Python編寫一個基本的XOR解密函數,該函數帶有2個參數:密鑰和加密的數據。向函數添加一個簡單的檢查,以查看數據是否與0x550D匹配并且腳本是否已完成!
但是,為了實際使用它,我們需要手動或使用YARA或Regex從IDA提取數據來定位它。然后我們必須在新的IDA會話中將其打開,并且在某些情況下第二個“階段”從第一階段開始調用函數,可能是對另一部分數據進行XOR。幸運的是,我們可以將此基本腳本轉換為IDAPython格式,并用解密的Shellcode覆蓋加密的Shellcode!
不用擔心,遷移到IDAPython的過程非常簡單。首先,我們需要導入所需的庫idaapi,然后將for循環更改為while循環,然后才能對傳入的數據調用len(),但是在這種情況下,我們不知道數據的長度如何,因為我們現在正在傳遞加密數據的地址。
除此之外,只要在address + i中仍有數據,就可以使while循環連續循環。這可以通過使用Byte()函數來實現,該函數從給定地址獲取一個字節的數據。在本文的示例中,該地址就是我們的加密blob。現在,我們就可以將該數據字節分配給一個變量字節,然后將其與0x55進行比較。我們還將address+(i+1)與0x0D進行比較,以確保這兩個標記都存在。
如果這些標記不存在,則使用給定的輸入執行XOR字節操作,然后調用PatchByte(),它將用我們的變量byte在address+i處覆蓋字節。最后,將i增加1,循環繼續!
將它導入IDA,并在命令行中輸入ida_xor_crypt(0x06, 0x2B),將執行我們的函數,覆蓋數據,如下圖所示!它不再以0x73開頭,因為現在是0x75。
將它導入IDA,并在命令行中輸入ida_xor_crypt(0x06, 0x2B),將執行我們的函數,覆蓋數據,如下圖所示我們可以在選擇0x75的情況下再次按“ C”,然后將其完全分解。
本文翻譯自:https://0ffset.net/reverse-engineering/malware-analysis/common-shellcode-techniques/如若轉載,請注明原文地址