楊東霖
國際關系學院 北京 100091
PE文件格式(Portable Execute),它是WIN32環(huán)境下自帶的可執(zhí)行文件格式, 在Windows系統(tǒng)之下常見的EXE、DLL、SYS、COM 等等文件格式均屬于 PE格式。由于 Windows系統(tǒng)的用戶眾多,故針對PE文件的加殼較為常見。對于知識產(chǎn)權保護來講,這樣的加殼能夠較好地保護程序的源代碼。此外,加殼可以在改變代碼特征的同時不影響程序的執(zhí)行結果,所以很多的惡意代碼也會利用加殼技術來保護自己,從而使殺毒軟件無法查殺。當遇到一個未知惡意程序時,對其研究的第一步工作便是對其進行分析,然后找到清除方案。常用的人工分析手段大致分為靜態(tài)分析和動態(tài)分析兩種。不論使用那種分析方法,基本上對樣本的操作都要從脫殼開始,如果分析人員不能有效地脫殼,那么后面的工作便無法開展。
PE文件的結構是一個統(tǒng)一的地址空間,文件的數(shù)據(jù)以及代碼被整合成為一個統(tǒng)一的結構。其中文件的內容被分為一個個屬性相同的區(qū)塊,每個區(qū)塊按頁邊界對齊,沒有固定的大小限制。每個區(qū)塊的功能以不同的名字表示。通過對 PE文件結構各個部分的關系進行分析,可以得到一個PE文件的總體結構框圖,如圖1所示。如果將PE文件看作一個圖書館,將每個section看作圖書館中的每本書。那么塊表就相當于是以每本書的名字建立的書目表,有塊表就可以找到相應的塊;而data directory就好比是按照每本書的索引號而建立的一個類似于索引的目錄,利用它能夠更快得找到想要的數(shù)據(jù)。此外,塊表對于區(qū)塊的定位是一對一的,而數(shù)據(jù)目錄對于區(qū)塊的定位是多對一的。
圖1 PE文件的總體結構框圖
殼是一個相對直觀的概念,比如在日常生活中,殼的作用是用來保護重要的東西不受傷害。同樣,在計算機領域中的加殼,是一種通過一系列運算處理,將可執(zhí)行程序文件或動態(tài)鏈接庫文件的代碼改變,以達到縮小文件體積或加密程序源碼的目的。它們一般都是先于程序運行,然后完成它們保護軟件的任務。以EXE文件為例,如圖2所示,我們能夠更加直觀的理解其原理。
圖2 EXE文件原理
對于惡意程序而言,加殼無疑是一項必需的反檢測技術,不論是對于給分析人員增加分析難度還是就傳播和隱藏而言,都是起著至關重要的作用。
加殼軟件按照其加殼目的和作用,可分為兩類:一是壓縮,二是加密。壓縮這類殼的主要目的是減小程序體積,如ASPacK、UPX和PECompact等。另一類是加密程序,用上了各種反跟蹤技術保護程序不被調試、脫殼等,其加殼后的體積大小不是其考慮的主要因素,如ASProtect、Armadillo、Themida等。隨著加殼技術的發(fā)展,這兩類軟件之間的界線越來越模糊,很多加殼軟件除具有較強的壓縮性能,同時也有了較強的保護性能。
加密殼與壓縮殼最大的不同在于加密殼有較強的反跟蹤能力,同時會設置很多 SEH 異常。加密殼通過對堆棧進行檢查,調用 IsDebugerPresent函數(shù),檢測調試器句柄等方法判斷自己是否被跟蹤調試。因此脫加密要在脫壓縮殼的基礎上,隱藏調試器進程,同時處理SEH異常機制。
道高一尺魔高一丈,伴隨著加殼技術的精進,脫殼技術的發(fā)展速度也是非常之快的,大多數(shù)加了殼軟件在一段時間之后都能找到特定的方法進行手工脫殼。此外,針對使用一些已有的加殼工具所加的殼還有對應的脫殼機來完成自動脫殼,這也促使加殼軟件的進一步發(fā)展。
(1) 識別殼的種類:這個一般都是通過使用工具來實現(xiàn)的,最著名的工具為PEID,其數(shù)量已超過470種PE文檔的加殼類型和簽名。查殼的原理是將程序OEP附近的代碼和各種殼代碼進行比較,從而判斷程序是否加殼以及加哪種殼。
(2) 尋找OEP:OEP(OriginalEntryPoint),及程序原始入口點。我們之前也介紹過,殼在完成功能后會將控制權交給真正的程序,也就是會運行到OEP。一般而言在對有殼PE文件分析時,殼的區(qū)段和程序真正開始區(qū)段之間會有很大的跳轉。而且,根據(jù)編寫語言的不同,程序的OEP特征也就不同。
(3) Dump內存:所謂dump就是轉存, 將內存中的進程數(shù)據(jù)抓取出來轉存為文件格式。一般調試跟蹤到程序 OEP時, 就可以dump程序。這里需要用到LordPE工具。
(4) 修復IAT:這一步驟主要是用在脫加密殼之后需要做的。加密殼都會對輸入表中的IAT進行加密處理,IAT(ImportAddressTable)是輸入地址表, 它保存著 PE程序要調用的外部函數(shù)地址信息。如果IAT表出錯, 程序將無法運行。修復原理是根據(jù)原加殼程序的IAT表重新構造一份IAT表,當加殼程序運行到OEP處時,其IAT已經(jīng)釋放出來,此時就可以重新構造一個區(qū)段存放輸入表, 從而解密IAT經(jīng)常會用到的工具是ImportREC。
(1) 單步跟蹤法:就是一步一步跟蹤指令的執(zhí)行,一直到程序真正的入口點(OEP)。這方法是最簡單的,但也是最費時費力的。因為在調試時會遇到大量的跳轉語句,為了更加方便的找到OEP,向上的跳轉我們是不去理會的,直接跳過。當入到很大段的跳轉時,一般也就到達了程序的OEP。
(2) ESP定律:ESP(extended stack pointer)棧指針寄存器,它的內存中存放著一個指針,這個指針默認指向系統(tǒng)棧最頂端的一個棧幀的棧頂。這個方法運用的是堆棧平衡的原理。其原理在于當程序使用函數(shù)或者子程序后,當遇到返回時,要保證ESP指向的是剛才壓入棧的地址。在加殼程序中,反匯編時一般一開始都會發(fā)現(xiàn) PUSHAD指令,其作用就是將所有寄存器壓入堆棧保存,在殼程序運行完畢后,會通過POPAD指令恢復堆棧狀態(tài)再返回到源程序。
(3) 內存鏡像法:內存鏡像法的原理是依據(jù)殼代碼對原程序的解壓過程。殼程序運行時需要先對原來壓縮的各個區(qū)段進行解壓,解壓完畢后將會跳到解壓后的代碼段(.text段)開始執(zhí)行,若在此處下斷點,程序則會中斷在OEP處。內存鏡像法又稱為兩次內存斷點法,但兩次內存斷點的本質卻不一樣。第一次是資源解壓,程序對資源寫入時中斷,是內存寫入中斷。第二次是訪問代碼段,準備執(zhí)行代碼時中斷,是內存執(zhí)行中斷。該方法也有其局限性,當殼在 JMP到 OEP前的一行代碼時仍在對代碼段解壓,則該方法將不再適用。
(4) 快速查找法:該方法使用的就是ESP定律的原理。使用方法是在調試器中查找“POPAD”,基本上就可以到達OEP。
(5) 最后一次異常法:這個方法主要適用于加密殼。加密殼的反跟蹤代碼中,會設置很多SEH陷阱,從而使OD等調試器產(chǎn)生異常。但是當殼代碼運行完畢后,將沒有異常。所以可以通過忽略異常讓程序運行,記下程序運行到正常時產(chǎn)生異常的次數(shù)。那么OEP便在最后一次產(chǎn)生異常的后面附近,通過在最后一個異常處指向的SEH句柄處下斷點,然后運行到該位置,繼續(xù)單步跟蹤就會到OEP。
本文介紹了PE文件結構、殼的相關概念以及脫殼原理和五種常見的脫殼方法,不過脫殼技術歸根到底是不會有太強規(guī)律可循的,脫殼技術隨著加殼技術的進步而進步,兩者在一個相互較量的過程中發(fā)展。而且在實踐中還會遇到各種各樣沒有遇到的新殼和組合殼。這些都需要我們自己去花大量的時間和精力去總結和實踐,才能不斷的去提高自己的能力。
[1]徐向陽,解慶春,劉勇,俞笛,劉寅.PE文件隱型加殼技術的研究與實現(xiàn)[J].計算機應用研究.2009.
[2]王清,張東輝,周浩,王繼剛,趙雙.0day安全:軟件漏洞分析技術[M].2011.
[3]張中華.PE程序加殼的研究與實現(xiàn)[J].2009.
[4]李露,劉秋菊,徐汀榮. PE文件中脫殼技術的研究[J].計算機應用與軟件.2010.