網(wǎng)絡(luò)安全攻防:軟件逆向之脫殼
“殼”是一種對(duì)程序進(jìn)行加密的程序,“殼”形象地表現(xiàn)了這個(gè)功能。我們可以把被加殼的程序當(dāng)成食物,而加殼程序就是在外面加上一層堅(jiān)硬的外殼,防止別人去竊取其中的程序。加殼后的程序依然可以被直接運(yùn)行。在程序運(yùn)行時(shí)殼的代碼先運(yùn)行,然后再運(yùn)行原來(lái)的程序。主要目的是為了隱藏程序的OEP(入口點(diǎn)),防止外部軟件對(duì)程序的反匯編分析或動(dòng)態(tài)分析。許多病毒通過(guò)加殼來(lái)達(dá)到免殺的目的,但殼也用在保護(hù)正版軟件不被破解。技術(shù)沒(méi)有對(duì)錯(cuò)之分,關(guān)鍵看使用的目的。
1. 殼的分類
(1)壓縮殼
壓縮殼的作用就是壓縮程序的大小。壓縮殼并不會(huì)對(duì)程序進(jìn)行修改,而是改變了存儲(chǔ)方式,使程序更小。運(yùn)行程序時(shí)先運(yùn)行殼的解壓縮程序,解壓源程序到內(nèi)存中,然后執(zhí)行。常見(jiàn)的壓縮殼有UPX,可以將一般程序壓縮到原來(lái)體積的30%。對(duì)upx_test進(jìn)行壓縮,原來(lái)大小為188 KB,壓縮后為33 KB,只有原來(lái)的17.54%,詳細(xì)信息如圖1所示。
圖1 壓縮upx_test
用PEiD進(jìn)行查殼,測(cè)試一下是不是有殼,如圖2所示,確實(shí)已經(jīng)有了UPX的壓縮殼。
圖2 PEiD查殼(UPX)
(2)加密殼
加密殼的作用是保護(hù)程序不被破解。一般情況下,加密殼加密之后的程序大小視情況而定,有些加密殼也有壓縮殼的效果。加密殼會(huì)對(duì)程序進(jìn)行修改,如打亂代碼、混淆等。常見(jiàn)的加密殼有ASProtect、EXECrptor、Armadillo等。如圖3所示是用ASProtect進(jìn)行加密。
圖3 ASProtect加密
用PEiD進(jìn)行查殼,測(cè)試一下是不是有殼,如圖4所示,確實(shí)已經(jīng)有了APS的加密殼。
圖4 PEiD查殼(APS)
(3)虛擬機(jī)保護(hù)殼
虛擬機(jī)保護(hù)殼是近些年開(kāi)始流行的加密保護(hù)方案,關(guān)鍵技術(shù)是軟件實(shí)現(xiàn)CPU的功能。由于程序不遵循Intel的OPCode標(biāo)志,所以分析起來(lái)會(huì)很麻煩。
2. 脫殼
對(duì)于不同的殼,網(wǎng)上有很多對(duì)應(yīng)的脫殼工具。在脫殼前一般先用查殼工具,查加的是什么殼,然后找到對(duì)應(yīng)的脫殼工具進(jìn)行脫殼。以之前的UPX殼壓縮的upx_test.exe為例,進(jìn)行脫殼演示。如圖5是PEiD查殼結(jié)果,通過(guò)查殼我們知道這是UPX的殼,然后用對(duì)應(yīng)的脫殼工具進(jìn)行脫殼。
圖5 PEiD查殼結(jié)果
這里用的是UPXshell進(jìn)行演示。將程序拖入到UPXshell中單擊“GO”即可得到脫殼之后的程序。脫殼之后會(huì)覆蓋原來(lái)的帶殼的程序,所以在脫殼前要做好備份,如圖6所示。
圖6 脫殼
脫殼是逆向分析的必備技能之一。雖然用軟件脫殼十分方便,但還是會(huì)存在許多限制,如要找對(duì)應(yīng)的脫殼軟件,較新、較強(qiáng)的殼一般無(wú)法用軟件脫殼等。所以還是有必要了解一些脫殼的基本知識(shí)。
(1)OEP
脫殼的第一步是找到源程序的OEP(Original Entry Point)。OEP標(biāo)志是否已經(jīng)運(yùn)行到源程序。對(duì)于一些簡(jiǎn)單的壓縮殼,找到OEP就意味著已經(jīng)脫殼成功。
單步調(diào)試法:加殼程序開(kāi)始運(yùn)行時(shí),棧的情況與解壓后主程序的棧情況完全相同。所以很多加殼程序載入 OD 后都會(huì)停留在 pushad/pushfd 處,將原來(lái)的棧先保存下來(lái),所以,pushad/pushfd肯定就有對(duì)應(yīng)的popad/popfd。只要找到popad/popfd就可以快速地找到OEP。將upx_test.exe載入OllyDbg,一直按F8,如果遇到向上跳轉(zhuǎn)就按F4運(yùn)行到下一行。直到遇到popad,下面會(huì)有一個(gè)比較大的jmp跳轉(zhuǎn)。如圖7和圖8所示。跳轉(zhuǎn)之后的地方就是程序的OEP,如圖9所示。
圖7 單步調(diào)試1
圖8 單步調(diào)試2
圖9 查找到OEP
這里只介紹了比較簡(jiǎn)單而且比較通用的一種脫殼方法。實(shí)際中還有很多巧妙的方法,如ESP定律、利用編輯語(yǔ)言的特點(diǎn)等。
(2)內(nèi)存映像轉(zhuǎn)存
找到OEP之后,程序已經(jīng)在內(nèi)存中,這時(shí)內(nèi)存中的程序最接近加殼前的程序。只需要將內(nèi)存中的映像轉(zhuǎn)存出來(lái),一般的殼就結(jié)束了。內(nèi)存映像轉(zhuǎn)存(dump)工具有好多,如LordPE、PETools。而且OllyDbg中也有OllyDump插件可以使用。
下面就可以進(jìn)行脫殼了。右鍵單擊“push ebp”選擇dump process,單擊“dump”按鈕脫殼。會(huì)生成一個(gè)脫殼后的程序,默認(rèn)文件名會(huì)在原文件名后面加上“_dump”。最后進(jìn)行查殼,顯示已經(jīng)無(wú)殼,并且成功運(yùn)行,表示脫殼成功,如圖10所示。
圖10 內(nèi)存映像轉(zhuǎn)存
(3)重建導(dǎo)出表
很多加密殼會(huì)對(duì)導(dǎo)入表做手腳。這時(shí),就算成功脫殼,程序也是無(wú)法運(yùn)行的。在導(dǎo)入表中起關(guān)鍵作用的是IAT,所以很多時(shí)候修復(fù)導(dǎo)出表也叫修復(fù)IAT??梢允褂胕mportREC重建導(dǎo)出表,如圖11所示。
圖11 重建導(dǎo)出表