PE文件加密方法

對于一個軟件開發(fā)商來說,要想了解PE文件加密處理的技術(shù),第一步必須要研究PE文件格式,研究PE文件格式不但可以給我們洞悉Windows結(jié)構(gòu)的良機(jī),而且對于如何去保護(hù)自己開發(fā)的軟件,有非常好的幫助,那么PE文件能否加密呢?下面我們就給大家介紹一下如何給PE文件加密。

一、什么是PE文件

PE文件的意思就是Portable Executable(可移植的執(zhí)行體)。它是Win32環(huán)境自身所帶的執(zhí)行體文件格式,它的一些特性繼承自Unix的Coff(common object fileformat)文件格式?!皃ortable executable”(可移植的執(zhí)行體)意味著此文件格式是跨win32平臺的,即使Windows運(yùn)行在非Intel的CPU上,任何win32平臺的PE裝載器都能識別和使用該文件格式。當(dāng)然,移植到不同的CPU上PE執(zhí)行體必然得有一些改變。所有win32執(zhí)行體都使用PE文件格式,包括動態(tài)庫NT的內(nèi)核模式驅(qū)動程序(kernel?mode drivers)。EXE與DLL的差別完全是語義上的,它們使用格式,其實(shí)都是PE文件格式。唯一的區(qū)別就是其中有一個字段標(biāo)識出是EXE還是DLL,還有很多DLL的擴(kuò)展比如OCX,CPL等都是PE文件格式。

二、PE文件加密

對被保護(hù)軟件的可執(zhí)行文件加密是軟件保護(hù)產(chǎn)品的重要組成部分,一般的加密思路是對可執(zhí)行文件進(jìn)行加一層保護(hù)殼,即對原始文件的代碼段、數(shù)據(jù)段、引入表和原始入口點(diǎn)等進(jìn)行加密,只有在運(yùn)行完加殼的代碼,才對以上內(nèi)容進(jìn)行解密。對PE文件加密是軟件開發(fā)商保護(hù)自己合法軟件的一個重要步驟,它可以極大的提高被保護(hù)軟件的安全性。下面介紹一下加過密的可執(zhí)行文件的裝載過程。

1、加密過程

a、獲取殼自己所需要使用的API地址

b 、解密原程序的各個區(qū)塊的數(shù)據(jù)

c、重定位

d、HOOK-API

e、跳轉(zhuǎn)到程序的原入口點(diǎn)

在外殼中可以實(shí)現(xiàn)很多軟件保護(hù)技術(shù),同時對于軟件開發(fā)商來說是透明的,不需要軟件開發(fā)商了解低層的保護(hù)技術(shù),只需要使用外殼工具進(jìn)行簡單設(shè)置,即可生成被保護(hù)軟件。在外殼中,目前常見的比較成熟的技術(shù)有:垃圾代碼插入、壓縮、調(diào)用變換、花指令、指令集轉(zhuǎn)換、系統(tǒng)函數(shù)隱藏技術(shù)、防篡改保護(hù)、反調(diào)試技術(shù)等。

關(guān)于象反調(diào)試技術(shù)和反篡改等技術(shù),已經(jīng)有很多相關(guān)的資料和文檔有很詳細(xì)的介紹,下面我們將重點(diǎn)介紹關(guān)于如何讓加密代碼和被保護(hù)軟件的代碼融合在一起,讓破解者很難通過內(nèi)存dump的方法得到原始的數(shù)據(jù)段和代碼段等進(jìn)行重構(gòu)新的未加密的程序。如何讓加密代碼和被保護(hù)代碼融合為一體?我們可以采用以下技術(shù)來保護(hù)PE文件格式。

2、多態(tài)和變形

多態(tài)既是指完成同一功能采用了不同的方法。多態(tài)的特點(diǎn)是隨機(jī)性和變化性。例如一個檢查過程,調(diào)用了3個子過程完成全部安全檢查機(jī)制。應(yīng)用多態(tài)技術(shù),這個檢查過程在每次程序運(yùn)行時,會隨機(jī)調(diào)用不同的子程序并以不同的調(diào)用次序來完成全部的安全檢查計劃。如此,破解者很難跟蹤,并做出通用破解補(bǔ)丁。這個隨機(jī)的初始化過程一般由一個初始化程序完成,這個程序通常稱為“多態(tài)引擎”。

變形:基于多態(tài)技術(shù),它發(fā)展和提升了多態(tài)技術(shù)。它可以動態(tài)生成更復(fù)雜的檢查過程,包括對重要程序片斷的動態(tài)加密、解密,動態(tài)變換全部檢查過程的代碼和數(shù)據(jù),基于內(nèi)置的各種不同加密算法、解密算法。對目標(biāo)代碼段進(jìn)行動態(tài)控制和編/解碼。這其中可能還包括代碼混淆過程。使得跟蹤者迷惑于復(fù)雜的變換和還原過程,無法找到真正的檢查過程和解碼程序。如果其中包含復(fù)雜的加密算法會使得整個安全檢查機(jī)制十分難于分析和最終的破解。

其實(shí)多態(tài)和變形技術(shù)最開始是使用在病毒上,但是技術(shù)本身沒有對錯之分,如今我們也可以用于對PE文件加密上,它可以保證每次產(chǎn)生的加密文件所使用的保護(hù)代碼是不一樣的,并且每次執(zhí)行的代碼也具有隨即性,這樣可以增大破解者脫殼的難度。

那么我們?nèi)绾蝸砭帉懸粋€多態(tài)呢?首先,我們必須在必須在腦海中清楚想要保護(hù)的代碼是什么,以及解密程序是什么樣。例如下面代碼所示:

movecx,virus_size

leaedi,pointer_to_code_to_crypt

moveax,crypt_key

@@1:

xordword ptr [edi],eaxaddedi,4

loop@@1

這是一個非常簡單的例子,主要有6條指令。多態(tài)的主要思想就是:改變寄存器,修改指令的執(zhí)行順序,為了達(dá)到同樣的目的使用不同的指令,插入什么也不做的指令,插入垃圾等等。讓我們看看對這個同樣的解密程序,用一個簡單的多態(tài)引擎初始的可能解密代碼:

shleax,2

addebx,157637369h

imuleax,ebx,69

movecx,virus_size

rclesi,1

cli

leaedi,pointer_to_code_to_crypt

xchgeax,esi

moveax,crypt_key

movesi,22132546h

andebx,0FF242569h

xordword ptr [edi],eax

oreax,34548286h

addesi,76869678h

addedi,4

stc

pusheax

xor_edx,24564631h

pop _esi

loop _ 00401013h _cmc

or edx,132h

3、截獲系統(tǒng)函數(shù)調(diào)用

處理引入表函數(shù)的目的就是讓程序正常運(yùn)行起來后,仍然需要定期執(zhí)行加殼程序,否則破解者可以很輕松的對運(yùn)行程序的內(nèi)存進(jìn)行dump,進(jìn)行脫殼處理。其基本原理就是一般的win32應(yīng)用程序都會調(diào)用向Kernel32.dll等系統(tǒng)核心動態(tài)庫,通過截獲對系統(tǒng)函數(shù)的調(diào)用達(dá)到保護(hù)的目的。

(1)修改代碼

直接修改可執(zhí)行文件的代碼段中通過CALL或者JMP調(diào)用的函數(shù)地址,這種方法需要通過一定程度的反匯編分析代碼段的二進(jìn)制文件,找到相關(guān)的調(diào)用點(diǎn),修改其地址,到殼的處理函數(shù)中,然后在殼的處理函數(shù)中,做完相應(yīng)的檢查措施后,再重新恢復(fù)堆棧,及相關(guān)寄存器的內(nèi)容,跳回到原來需要jump的地址。這種方法實(shí)現(xiàn)難度比較大,但是安全性非常的高,一般破解者很難把修改過的代碼重新恢復(fù)成原始代碼。

PE文件加密方法

另外一種方法實(shí)現(xiàn)起來也是非常的復(fù)雜。簡而言之,就是通過確定原始函數(shù)的地址,然后使用JMP指令修改其中起始的幾個字節(jié),重定向到自定義的函數(shù),這種方法非常的巧妙,包括需要對沒一個函數(shù)進(jìn)行一系列的恢復(fù)操作。原理如下圖所示,左圖為沒有經(jīng)過加密處理的反匯編代碼,右圖為加密過的反匯編代碼。通過加密后,原本應(yīng)該跳到Target Function的指針被修改成跳到Target Function+5的地址去執(zhí)行了,執(zhí)行完后再重新跳到Target Function地址繼續(xù)執(zhí)行。但是這種方式在多線程的環(huán)境下可能會又有一定問題。不過這種方式確實(shí)是一種非常好的解決方案,不但適用于PE文件加密,還適用于解決多種問題,比如如何把單機(jī)的PE文件轉(zhuǎn)變成支持網(wǎng)絡(luò)版的程序。

PE文件加密方法

(2)加密引入表

在我們討論修改引入表(IAT)之前,我們先闡述以下PE文件調(diào)用引入函數(shù)的過程。程序加載器的主要任務(wù)是負(fù)責(zé)把PE文件和相關(guān)的DLL加載到內(nèi)存當(dāng)中,但是每個DLL將被加載到什么地址,事先是不知道的。加載器是不能夠決定實(shí)際的引入函數(shù)的地址。加載器必須執(zhí)行其它一些工作來保證程序可以正確的調(diào)用每個引入函數(shù)。但是如果在內(nèi)存中遍歷每個可執(zhí)行文件,然后去修改每一個引入表地址將會浪費(fèi)大量的時間。實(shí)際上每一個調(diào)用引入函數(shù)的CALL動作都將被引入表使用JMP指令改成一個間接調(diào)用,這種設(shè)計的好處是加載器不需要去搜索整個映象文件,同時這種方式也比較簡單,只是去修改在引入表的所有地址。如下圖使用工具對PE文件的引入表的顯示??梢钥吹皆谝氡碇蠯ernel32.dll中保護(hù)兩個引入函數(shù)CreateFileA ()和CloseHandle()。

PE文件加密方法

如果我們對PE文件的原始引入表進(jìn)行加密,在運(yùn)行的時候進(jìn)行解密,同時在調(diào)用引入函數(shù)的時候進(jìn)行hook,同時再把以上提到的文件加密技術(shù)應(yīng)用上,那么破解者將很難進(jìn)行解密。

小知識之COFF

COFF –通用對象文件格式(Common Object File Format),是一種很流行的對象文件格式(注意:這里不說它是“目標(biāo)”文件,是為了和編譯器產(chǎn)生的目標(biāo)文件(*.o/*.obj)相區(qū)別,因為這種格式不只用于目標(biāo)文件,庫文件、可執(zhí)行文件也經(jīng)常是這種格式)。大家可能會經(jīng)常使用VC吧?它所產(chǎn)生的目標(biāo)文件(*.obj)就是這種格式。其它的編譯器,如GCC(GNU Compiler Collection)、ICL(Intel C/C++ Compiler)、VectorC,也使用這種格式的目標(biāo)文件。不僅僅是C/C++,很多其它語言也使用這種格式的對象文件。