2019年11月8日 星期五

壓縮殼(Compression Packer)逆向分析

現今的惡意程式大多數都會加殼(Packer)來保護自己,因為它不想那麼容易被防護軟體或者被別人逆向出運作原理,所以它會透過加殼(Packer)的方式來保護自己,因此如果想要靜態分析(動態分析不一定要解殼(Unpacker),就需要將它解殼(Unpacker)才能完整地看到程式碼。

我們知道加殼的方式可以很多種,像是壓縮殼(Compression Packer)、加密殼(Encryption Packer)和VMP (Virtual Machine Protect),每種的解殼(Unpacker)難易度其實是依賴它們有多少Anti-Debugger的技術,越多則越難,因為需要花大量的時間去測試它是哪種的Anti-Debugger,不然每次Debugger工具去附加(Attach)程式,都會崩潰掉,很難找出真正原因。

一、Anti-Debugger

Anti-Debugger的技術有非常多種類,常見的有混淆程式碼(將call指令改成push和ret或jmp)、PEB(Process Environment Block)檢測Debugger旗標(BeingDebugged flag)、SEH(Structured Exception Handling)或VEH(Vectored Exception Handler)檢測中斷異常(int3、int1、int2d)、Hook Debugger Function(DebugActiveProcess、DebugBreakProcess、DbgBreakPoint、DbgUiRemoteBreakin等等)、FindWindow、EnumProcesses、CRC(Cyclic redundancy check)、time檢測等等,通常只要存在至少一種檢測技術,在Deubgger時都會自動結束或程式崩潰。

二、壓縮殼(Compression Packer)

壓縮殼(Compression Packer)的主要目的為,讓程式壓縮成比較小一點,不過後來都是用來防止程式被靜態分析,因為它會修改EntryPoint和壓縮IAT(Import Address Table)、rdate(Read-only)的Section,讓分析者很難找到程式真正的入口點位址,當下也看不到相關的字串,這樣在靜態分析下是毫無任何進展,因此需要脫殼(Unpacker)才能繼續靜態分析。

三、修改EntryPoint

加殼程式需要將當初壓縮的區塊進行解壓縮,然後再跳進真正的程式碼,因此一開始需要修改EntryPoint(程式一開始的執行位址)才能進入解壓縮的程式碼區塊。



四、壓縮IAT(Import Address Table)

IAT主要是存放API(Application Programming Interface)的進入點位址,通常查看此表,可以知道這個程式用了哪些API,可以推測它的行為,不過已加殼的程式,是看不出原來用了哪些API,因為被壓縮了,那麼觀察已加殼的IAT,只會看到解殼需要用到的API。



五、壓縮String

想要壓縮String(字串),需要壓縮rdate(Read-only),因為字串會被放置此Section,那麼只要將它壓縮,就不知道原來的字串有哪些,是一個隱蔽分析的技巧。


六、解壓縮

在運行原來的主程式之前,需要將之前壓縮的Section進行解壓縮,因此會透過LoadLibrary和GetProcAddress獲取其他的API(透過這種方式獲取API,也能隱蔽解殼會用到的API),這樣才能順利的進行解壓縮。



在解壓縮完成後,會運行到原來主程式的區塊,它有一個特徵,就是會進入一個與現在不同Section的位址(跳到其他的Section),那麼這個位址就是原先的EntryPoint,不過透過靜態分析觀察,只會看到一連串的十六進制的數值,如果想要將它順利解殼,需要在401500下中斷點,然後將它Dump下來,由於之前的IAT有被移動到其他的位址,因此需要將它修正回來,我們可以使用x64dbg內建修正IAT的功能(Scylla)。