糜嫻雅 張怡 王寶生 國防科學(xué)技術(shù)大學(xué)
二進(jìn)制軟件防篡改技術(shù)研究
糜嫻雅 張怡 王寶生 國防科學(xué)技術(shù)大學(xué)
隨著軟件安全性問題日益嚴(yán)重,軟件防篡改技術(shù)作為軟件保護(hù)的重要手段之一,越來越得到國內(nèi)外研究者的重視。本文首先介紹軟件破解與保護(hù)的基本概念,針對軟件防篡改的主要目標(biāo),即能夠準(zhǔn)確地檢測到正常功能之外的對程序進(jìn)行的異常修改行為;對這種修改行為進(jìn)行恰當(dāng)?shù)摹⒂行У姆磻?yīng),重點(diǎn)介紹了幾種基于“檢測-響應(yīng)”的二進(jìn)制軟件防篡改技術(shù),對其具體實現(xiàn)方法進(jìn)行分類和總結(jié),詳細(xì)分析和討論各類方法的優(yōu)劣和局限性,提出了一套評價體系,并展望了軟件防篡改技術(shù)的發(fā)展前景,提出了自己的見解。
軟件保護(hù);防篡改;檢測-響應(yīng)
隨著軟件破解技術(shù)的發(fā)展,軟件安全性問題日益突出,保護(hù)軟件知識產(chǎn)權(quán)成為一個越來越艱巨的任務(wù)。攻擊者獲取軟件副本后,借助一些工具,通過技術(shù)手段可以輕易地理解和修改二進(jìn)制代碼,從而達(dá)到破解軟件、非法使用的目的。二進(jìn)制軟件防篡改技術(shù)作為軟件保護(hù)的重要方法之一,越來越得到國內(nèi)外研究者的重視。本文研究了防篡改技術(shù)的基本原理和實現(xiàn)方法,對當(dāng)前主流的防篡改技術(shù)進(jìn)行分析和評價,并就該技術(shù)的應(yīng)用和發(fā)展前景提出見解。
1.1 軟件篡改的實現(xiàn)方法
軟件篡改通常發(fā)生在攻擊者對代碼進(jìn)行有效分析之后,具體說來有三種實現(xiàn)方法:(1)在可執(zhí)行文件運(yùn)行之前,刪掉其中的一些代碼,同時/或者往其中加一些代碼;(2)從正在運(yùn)行的程序中,刪掉一些代碼,同時/或者往其中加入一些代碼;(3)借助模擬器、調(diào)試器或修改過的操作系統(tǒng)等工具,影響程序運(yùn)行時的行為。其中(1)屬于靜態(tài)篡改,即直接修改二進(jìn)制代碼,原代碼不會進(jìn)入內(nèi)存。(2)、(3)屬于動態(tài)篡改,即邊運(yùn)行邊篡改,原代碼要進(jìn)入內(nèi)存,與調(diào)試的原理比較相似。
1.2 防篡改技術(shù)的主要目標(biāo)

圖1 一個完整的防篡改系統(tǒng)示意圖
防篡改技術(shù)的主要目標(biāo)在于檢測對程序的修改行為并做出相應(yīng)的反應(yīng),因此其重要的技術(shù)原則有兩條:(1)能夠準(zhǔn)確地檢測到正常功能之外的對程序進(jìn)行的異常修改行為;(2)對這種修改行為進(jìn)行恰當(dāng)?shù)摹⒂行У姆磻?yīng)。目前常見的軟件防篡改實現(xiàn)方法基本上都是基于這兩條原則實現(xiàn)的,即“檢測-響應(yīng)”機(jī)制。從概念上來說,一個完整的防篡改系統(tǒng)應(yīng)該是由CHECK和RESPOND兩個函數(shù)組成,如圖1所示,CHECK函數(shù)用來測試異常修改行為是否發(fā)生并返回結(jié)果,而RESPOND函數(shù)則根據(jù)CHECK函數(shù)的返回結(jié)果來判斷是否觸發(fā)對篡改行為的響應(yīng)。
防篡改的具體實現(xiàn)方法有基于源代碼和基于二進(jìn)制代碼兩種,由于源代碼方法有一定的局限性,本文主要研究基于二進(jìn)制代碼的軟件防篡改技術(shù)。
根據(jù)CHECK和RESPOND函數(shù)的實現(xiàn)思想不同,當(dāng)前主流的軟件防篡改實現(xiàn)方法可以分為4種,分別是:(1)基于保護(hù)網(wǎng)絡(luò)的防篡改方法,(2)基于Oblivious Hashing的防篡改方法,(3)遠(yuǎn)程防篡改方法,以及(4)基于監(jiān)測運(yùn)行環(huán)境的防篡改方法。
2.1 保護(hù)網(wǎng)絡(luò)
Hoi Chang建立了一種由稱之為guards的代碼片段組成的保護(hù)網(wǎng)絡(luò)[1],guards分為兩類,一類是校驗和代碼,用來計算一段程序的校驗和并驗證完整性,即檢查是否被篡改。一旦發(fā)現(xiàn)被篡改,校驗和代碼會做出反應(yīng),觸發(fā)一定的行為,比如使軟件無法繼續(xù)使用、中斷程序等等,即檢查完整性功能。另一類是修復(fù)代碼,用來將被破壞的代碼和數(shù)據(jù)恢復(fù)到原來的樣子,具體方法是在別處存放該段代碼的原始備份,一旦被篡改則原樣復(fù)制過來,即自治愈功能。
2.2 Oblivious Hashing
實際上Hoi Chang的保護(hù)網(wǎng)絡(luò)所運(yùn)用的是防篡改技術(shù)中非常普遍的一種方法:自監(jiān)測原理,基本的思想就是計算某一代碼區(qū)域的hash值,并根據(jù)這個值做出反應(yīng)。可以把hash值作為程序中將要進(jìn)行的算數(shù)運(yùn)算中的一部分?jǐn)?shù)據(jù),或者把hash值用在其他變量地址的計算上。然而,上述自監(jiān)測算法有兩個根本性缺陷:(1)讀取自己代碼段的操作很容易被檢測出來,即算法隱蔽性不高;(2)只檢查代碼正確性,攻擊者可以修改運(yùn)行時的數(shù)據(jù)來影響程序行為,比如使用調(diào)試器,在某個關(guān)鍵函數(shù)返回之前修改其返回值,即不能抗動態(tài)篡改。
由此產(chǎn)生了另一種防篡改思想:oblivious hashing[2],即“易遭忽視的hashing”,因為此方法中hash是作為軟件的一部分在正常的計算過程中被計算出來的,攻擊者很容易忽視它。圖2顯示了這種方法的基本原理,即通過結(jié)合源代碼中的指令和內(nèi)存中的指令來計算hash值。
Y.Chen提出了一種巧妙的方法[3],直接在源碼中插入了hash計算代碼,根據(jù)變量的值和控制流控制語句輸出結(jié)果計算hash。它不記錄程序trace,而是往程序中插入相關(guān)代碼,計算trace的hash,來監(jiān)測變量的改變和控制流執(zhí)行情況。可以通過調(diào)整所插入的,用以計算hash的代碼數(shù)量來調(diào)和性能開銷和保護(hù)級別之間的矛盾。

圖2 通過內(nèi)存中的指令和源代碼指令結(jié)合計算hash值
Mattias Jacob和Mariusz H.Jakubowski提出了另一種算法[3]。x86體系結(jié)構(gòu)使用變長指令編碼方式且指令無需對齊,可以利用這兩個特性,把指令相互重疊,相互重疊的指令甚至可以屬于兩個不同的基本塊。這個算法就是通過重疊基本塊中的x86指令進(jìn)行防篡改,當(dāng)一個基本塊執(zhí)行的時候,另一個基本塊的hash就被它“順便”算了出來。這一技術(shù)的優(yōu)點(diǎn)在于,計算hash不需要顯式地讀取代碼,所以內(nèi)存復(fù)制的攻擊方法對這個是無效的。這個算法的缺點(diǎn)是,無法預(yù)計監(jiān)測代碼的及時性。
本節(jié)所闡述的方法的根本原理在于,運(yùn)行時檢查程序中使用的數(shù)據(jù)值是否在正常的取值范圍之內(nèi),程序的控制流是否沿著一個合理的路徑流動。
2.3 遠(yuǎn)程防篡改
遠(yuǎn)程防篡改的思想是,將想要保護(hù)的程序C運(yùn)行在攻擊者控制下的不可信主機(jī)(客戶端)上,客戶端必須和開發(fā)者的主機(jī)(服務(wù)器)上一個可信的程序S保持通信。除了向客戶端提供服務(wù),服務(wù)器還必須對C可能遭到的篡改進(jìn)行監(jiān)測和響應(yīng)。
Xiangyu Zhang把程序拆成兩個部分[4],一個是可以放在客戶端中運(yùn)行的公開部分,另一個是放在服務(wù)器里運(yùn)行的隱藏部分。此算法通過只考慮標(biāo)量數(shù)據(jù)(處理數(shù)組和鏈?zhǔn)浇Y(jié)構(gòu)數(shù)據(jù)的函數(shù)全部放在客戶端中)和確保客戶端和服務(wù)器處于同一個局域網(wǎng)中這兩個方法來解決網(wǎng)絡(luò)延遲和帶寬這兩個問題。
Christian Collberg將反分析和防篡改的方法相結(jié)合,具體說來是將反靜態(tài)分析的自修改代碼的思想運(yùn)用在了這種遠(yuǎn)程防篡改的機(jī)制上。圖3顯示了這種遠(yuǎn)程防篡改方法的運(yùn)行原理。通過經(jīng)常變化客戶端程序中的代碼,使它難以分析。理想情況下,攻擊者將會發(fā)現(xiàn)客戶端程序中的代碼變化太快,以至于在他完成分析并對當(dāng)前的客戶端程序進(jìn)行修改之前,服務(wù)器又發(fā)了一個新的程序過來。然而,這個思路雖然很好,卻還僅僅停留在理論上,目前還沒有已知系統(tǒng)實現(xiàn)了這個通過不斷改變代碼進(jìn)行防篡改的想法。

圖3 Christian Collberg的遠(yuǎn)程防篡改方法示意圖
2.4. 監(jiān)測運(yùn)行環(huán)境
對于使用了自監(jiān)測原理的防篡改方法,攻擊者早已形成了與之對應(yīng)的攻擊方法。攻擊有兩種方法:(1)想辦法找到程序中的監(jiān)測代碼或相應(yīng)代碼,然后刪掉;(2)從外部進(jìn)行攻擊,即修改程序執(zhí)行的環(huán)境。
Glen Wurster提出了一種攻擊自hash算法,該算法的關(guān)鍵點(diǎn)在于,基于hash的防篡改算法中,代碼會被以兩種形式訪問:①當(dāng)被執(zhí)行時作為代碼,②當(dāng)計算hash時作為數(shù)據(jù)。當(dāng)把代碼當(dāng)作數(shù)據(jù)讀取的時候,應(yīng)該獲得未經(jīng)修改的代碼,這可以保證代碼hash值不變;當(dāng)執(zhí)行代碼時,應(yīng)執(zhí)行修改后的代碼。此方法將同一個虛擬內(nèi)存地址分別映射到兩個不同的物理內(nèi)存地址上:如果被訪問的是代碼,則映射其中一個地址;如果被訪問的是數(shù)據(jù),則映射到另一個地址上。對防篡改的攻擊有以下三個步驟:i.把程序P復(fù)制一份,復(fù)制品稱為;ii.對P進(jìn)行修改,將其制成破解版;iii.修改操作系統(tǒng)的內(nèi)核K,使計算機(jī)在讀取數(shù)據(jù)時從中讀取,而讀取代碼時則從中讀取。這一攻擊的具體實現(xiàn)方式有賴于具體的處理器型號和操作系統(tǒng)中內(nèi)存管理模塊的設(shè)計方式。
為了應(yīng)對這種攻擊,Jonathon Giffin提出了一種思路:向程序中加入新的代碼,監(jiān)測程序是否運(yùn)行在一個可信的環(huán)境中。他使用自修改代碼實現(xiàn)這種對抗攻擊的保護(hù)方法,如果程序監(jiān)測到自己運(yùn)行在一個修改只會作用于數(shù)據(jù)而不會影響代碼的系統(tǒng)中,它就會調(diào)用正常的篡改響應(yīng)代碼。
3.1 小結(jié)
綜上所述,可以總結(jié)出5種能使程序變得難以修改的基本方法:
(1)向程序中加入新的代碼,監(jiān)測程序中的代碼是否遭到了修改。Hoi Chang的保護(hù)網(wǎng)絡(luò)算法使用了這種方法。
(2)向程序中加入新的代碼,監(jiān)測程序是否運(yùn)行在一個可信的環(huán)境中。Jonathon Giffin的環(huán)境監(jiān)測算法使用了這種思想。
(3)運(yùn)行時檢查程序中使用的數(shù)據(jù)值是否在正常的取值范圍之內(nèi),程序的控制流是否沿著一個合理的路徑流動。Oblivious Hashing一節(jié)中的兩種算法使用了這種思想。
(4)遠(yuǎn)程防篡改:把程序割裂成兩個部分,其中一個部分可以運(yùn)行在服務(wù)器或者抗篡改硬件中,以避免被攻擊者修改。Xiangyu Zhang的拆分函數(shù)方法使用了這種思想。
(5)使用代碼混淆算法使攻擊者難以理解程序,因而也就難以篡改程序。Christian Collberg的自修改代碼機(jī)制使用了這種方法。
3.2 評價體系
在軟件防篡改技術(shù)研究領(lǐng)域中,尚無被普遍接受的評價體系。本文借鑒ChristianCollberg提出的代碼混淆的評價定義,建立了一套防篡改適用的評價標(biāo)準(zhǔn),主要從防篡改強(qiáng)度、開銷、隱蔽性三個方面對上述防篡改實現(xiàn)方法作定性分析。
防篡改強(qiáng)度 表示該算法對抗攻擊者進(jìn)行篡改的效果,可分為抗靜態(tài)篡改和抗動態(tài)篡改兩個方面。開銷分為空間開銷和性能開銷兩個方面,空間開銷包括代碼增加的大小、對于硬件和其他環(huán)境條件的需求等;性能開銷主要關(guān)注增加保護(hù)代碼之后程序運(yùn)行時間的增加。隱蔽性表示該算法是否容易被攻擊者發(fā)現(xiàn)并進(jìn)行篡改攻擊。
Hoi Chang的保護(hù)網(wǎng)絡(luò)方法有一個非常好的特性就是其提供的安全性可以由我們自己隨意調(diào)節(jié),具體說來,就是通過調(diào)整保護(hù)代碼的數(shù)量和防御圖的復(fù)雜度來做到這一點(diǎn)。遠(yuǎn)程防篡改方法從理論上來說,對于動態(tài)篡改的抵抗效果是非常好的。然而,Xiangyu Zhang的拆分函數(shù)方法顯然對服務(wù)器端的計算能力有很高的要求,對網(wǎng)絡(luò)實時帶寬的要求也比較高,因此實現(xiàn)成本是很高的。在性能開銷方面,如果硬件條件不夠好,會造成較大的延遲。此方法的性能開銷往往依賴于有多少代碼存放在服務(wù)器中。
監(jiān)測運(yùn)行環(huán)境的實現(xiàn)實際上是自修改代碼的一種應(yīng)用。對于以內(nèi)存復(fù)制為主的動態(tài)篡改方式,這種方法效果還是比較明顯的。據(jù)該算法的作者估計,在最壞的情況下將會導(dǎo)致一個與輕量級的系統(tǒng)調(diào)用近似的開銷。
通過對當(dāng)前主流軟件防篡改技術(shù)的介紹,可以看出基本上沒有突破“檢測-響應(yīng)”機(jī)制的框架。然而,響應(yīng)部分往往是整個防篡改機(jī)制中的弱點(diǎn),大部分攻擊防篡改的破解技術(shù)以此作為突破口,一旦攻破,會使整個防篡改機(jī)制失去功效。另外,當(dāng)前軟件破解技術(shù)的主流傾向于將防篡改技術(shù)與其他軟件反破解技術(shù)進(jìn)行結(jié)合。如防篡改技術(shù)與代碼混淆技術(shù)結(jié)合,增加“檢測-響應(yīng)”機(jī)制的隱蔽性;防篡改技術(shù)與軟件水印技術(shù)結(jié)合,由于水印技術(shù)中的完整性驗證要求軟件遭到修改后水印即被破壞,實際上與防篡改技術(shù)的原理有相通之處,如何將二者結(jié)合亦是一項有意義的課題;總而言之,將防篡改技術(shù)與其他軟件保護(hù)技術(shù)相結(jié)合能夠大大增加軟件保護(hù)的力度。
[1] Chang H,Atallah M J.Protecting software by guards[M]//Security and privacy in digital rights management.Springer Berlin Heidelberg,2002:160-175.
[2] Y.Chen,R.Venkatesan,M.Cary,R.Pang,S.Sinha,and M. Jakubowski.Oblivious hashing:A stealthy software integrity verification primitive.In 5th Information Hiding Workshop(IHW),pages 400-414,October 2002.Springer LNCS 2578.
[3] Mattias Jacob,Mariusz H.Jakubowski,and Ramarathnam Venkatesan.Towards integral binary execution:implementing oblivious hashing using overlapped instruction encodings.In Proceedings of the 9th workshop on Multimedia & Security,pages 129-140,New York,2007.ACM
[4] Xiangyu Zhang and Rajiv Gupta.Hiding program slices for software security.In CGO'03: Proceedings of the International Symposium on code Generation and Optimization, pages 325-336, Washington,DC,2003.IEEE.