基於虛擬機的軟件保護技術

本文並不打算對vmprotect或其它某款軟件安全套件進行深刻討論,而着眼於研究基於虛擬機的軟件保護技術的起源、思想和實現。java

基於虛擬機的軟件保護技術基於虛擬機的軟件保護技術

現有軟件保護技術概述linux

傳統的軟件保護技術,根據針對對象不一樣,可分爲反靜態調試和反動態調試兩大類。反靜態調試主要針對對象爲反彙編器。反彙編器經過面向特定平臺的反彙編引擎(如PC平臺即爲X86反彙編引擎),將編譯器生成的二進制文件還原成彙編代碼,有經驗的逆向工程師能夠據此還原出算法等核心運算機制。反靜態調試主要是經過特定區段加密等方式,將核心信息保護起來,只在運行期才經過解密等算法動態還原,阻礙反彙編器靜態地將二進制文件還原成彙編碼。
反動態調試主要針對對象爲調試器,因爲通過靜態加密的二進制碼最終必須解密才能執行,所以經過Ollydbg等動態調試器仍然能夠加以查看,反動態調試經過檢測調試器和屏蔽調試端口等各類反調試技術阻止逆向工程師經過調試器跟蹤軟件進程的運行狀況,使得軟件的運行時情況始終保持處於黑盒狀態。
被動型軟件保護概念上述兩種保護方案均採起主動出擊的策略,意圖「禦敵於國以外」,中心思想是一個「擋字」,阻止逆向工程是窺視軟件內部機理,但盾與矛的對抗老是無休止的,並無任何一種主動型軟件保護手段能真正完全阻斷逆向工程,所以另外一種「以人爲本」的被動型軟件保護技術開始走向鬥爭舞臺的中央。
被動型軟件保護手段基於一個假設,即逆向工程師已經經過各類辦法突破了主動型軟件保護措施,能夠爲所欲爲地觀察一切,此時「擋」已經擋不住了,只能採起「藏」的策略,經過提升核心代碼的隱蔽性來提升逆向工程在閱讀反彙編代碼階段的時間成本投入,間接起到軟件保護的效果。被動型軟件保護手段具體實現方式主要有亂序和混淆。
亂序是指在在程序執行流中添加跳轉指令,如jmp,經過這些跳轉指令將一個從上至下執行的完整代碼塊切分紅若干執行前後順序不一致的代碼片斷。亂序可以必定程度上增長反彙編代碼的閱讀難度,但若只是簡單地植入無條件跳轉很容易被識別和去除,所以工業級的保護產品每每經過採用條件跳轉的方式增長識別難度。
基於虛擬機的軟件保護技術基於虛擬機的軟件保護技術
混淆是指經過加入無心義代碼(又稱爲花指令或垃圾代碼)或者有意義代碼,增長反彙編碼的理解難度。俗話說要藏好一棵樹,最好的地點必定是森林,混淆技術就是經過代碼膨脹增長反彙編代碼的總量,爲隱藏核心代碼構造出一片代碼「森林」。早期增長的混淆代碼爲無心義代碼,實現類nop操做的執行效果,如push指令和pop指令搭配使用,但這類代碼無實際意義,去除後並不會對軟件運行產生影響,所以有經驗的逆向工程師每每會首先去除這些無心義的混淆代碼纔開始進行反彙編碼的閱讀工做,使混淆技術失去效果。爲了確保混淆代碼不被去除,工業級的保護產品更傾向於採用有意義的混淆代碼,核心思想是等價替換,經過多條指令實現核心代碼中一條指令的效果,如最簡單的賦值指令moveax,3能夠替換成xoreax,eax;inceax;inceax;inceax這四條指令,操做效果同樣,但指令數量翻了兩番。被動型軟件保護技術究竟可否對軟件安全起到實質性的做用,業界一直存在爭論。反對的觀點主要集中在認爲被動型軟件保護技術只是提升了閱讀反彙編代碼的難度和數量,讓人「眼花」而已,並無任何實質性的效果。本文認爲,軟件安全不應簡單理解成讓軟件絕對安全不可攻破,而實際該是攻方與防方、投入與產出的反覆博弈的過程,攻方人力的投入天然也是成本之一。一我的單位時間內閱讀代碼的數量是固定的,所以,提升了閱讀反彙編代碼的難度和數量,也就提升了閱讀反彙編代碼的時間,提升了攻方人力成本的投入,對軟件安全是有切實效果的。算法

虛擬機軟件保護技術安全

虛擬機軟件保護的思想jvm

虛擬機軟件保護技術是被動型軟件保護技術的分支,具體來講是添加有意義的混淆代碼的一種變型使用。
虛擬機技術目前在軟件領域應用普遍,根據應用層級不一樣,基本可分爲硬件抽象層虛擬機、操做系統層虛擬機和軟件應用層虛擬機。用於保護軟件安全的虛擬機屬於軟件應用層虛擬機,同層的虛擬機還包括高級語言虛擬機,如java程序語言運行環境jvm和.net程序語言運行環境CLR,後者採用虛擬機的緣由是便於移植,所以編譯器沒有直接生成可直接在機器上執行的nativecode,而改成生成中間代碼byte-code,再經過在不一樣機器環境下安裝對應版本的虛擬機對byte-code進行解釋執行,從而實現跨平臺運行。
用於保護軟件安全的虛擬機採用相似的流程。虛擬機保護軟件首先會對被保護的目標程序的核心代碼進行「編譯」——須要注意的是,這裏被編譯的不是源文件,而是二進制文件——並生成效果等價的byte-code,而後爲軟件添加虛擬機解釋引擎。用戶最終使用軟件時,虛擬機解釋引擎會讀取byte-code,並進行解釋執行,從而實現用戶體驗徹底一致的執行效果。編碼

虛擬機軟件保護的實現加密

編譯生成byte-code
要設計一套虛擬機保護軟件,首先要設計一套虛擬機指令,也便是byte-code的指令集表,生成byte-code的過程,實際是將原始機器指令流等價轉譯成虛擬機指令流的過程。spa

虛擬機指令集表應知足如下兩條設計原則:
第一條設計原則是虛擬機指令集表與原始機器指令集表越正交越好,安全係數越高。最壞的狀況是虛擬機指令集表與原始機器指令集表爲一一對應的關係,採用這種指令集的虛擬機保護程序安全係數趨近與零,對於逆向工程師而言只須要進行簡單的換算,便可還原出原始代碼。
另外一條設計原則是應儘量地具有圖靈完備性,可以完整地表達出原始機器指令的全部可能表達。圖靈完備性越好,則虛擬機保護引擎的保護的覆蓋範圍越廣,健壯性越高。理想狀態下,虛擬機指令集應完整地實現對原始機器指令集的等價替代,須要徹底知足圖靈完備性。但實際上完整替代的代價太高甚至不太可能實現,如x86指令集的FCLEX、FPTAN等指令,仿真難度較高,且核心代碼使用這類指令的可能性很小,綜合效費比考慮,虛擬機指令集一般並不涵蓋這些「生僻」指令。對於不能仿真的指令,能夠採起退出虛擬機執行,獲取執行結果再進入虛擬機的方法解決。操作系統

解釋執行byte-code
在軟件運行時,編譯產生的Byte-code由內嵌入軟件可執行文件中的虛擬機解釋引擎,採用讀取-分派的方式解釋執行。
虛擬機解釋引擎分爲兩大部分,分別爲Dispatcher和handle。.net

基於虛擬機的軟件保護技術基於虛擬機的軟件保護技術

Dispatcher的中文字面意思爲「分派器」,至關於虛擬機解釋引擎的CPU,負責讀取Byte-code,並指派對應的handle進行解釋執行。Handle的中文字面意思爲「處理」,實際做用爲虛擬機指令經過平臺nativecode(如PC平臺即爲x86指令)的實現。Handle的數量與虛擬機指令集的指令數量是一致的。
虛擬機的進入和退出問題
軟件保護虛擬機與高級語言虛擬機並不徹底同樣,主要體如今高級語言虛擬機由始至終均在虛擬機環境下執行,但軟件保護虛擬機必須經歷本地環境與虛擬機環境的切換,爲了保證執行結果的一致性,必需要求虛擬機環境可以正確獲取和還本來地環境的執行上下文。較爲便捷的方法是採用堆棧機模型,即虛擬機基於堆棧來進行數據操做。進入虛擬機前,先將本地環境壓棧,虛擬機直接以棧地址執行指令流操做,退出虛擬機後,再一一出棧,從而保證了上下文在不一樣執行環境的無縫切換。

結語

基於虛擬機的軟件保護技術能夠大大增長了逆向工程還原代碼的難度,一套設計良好的軟件保護虛擬機可以顯著增長代碼還原所需的時間,從而擡高了逆向工程的成本,達到軟件保護的效果。但採用虛擬機並不是有百利而無一害,和高級語言虛擬機同樣,軟件保護虛擬機一樣面臨會致使執行效率下降的問題,安全和效率老是處於相生相斥的關係,具體偏重只能根據生產環節的要求具體權衡。

 

免費提供最新Linux技術教程書籍,爲開源技術愛好者努力作得更多更好:http://www.linuxprobe.com/

相關文章
相關標籤/搜索