(轉)防止java反編譯的一些經常使用方法

經常使用的保護技術算法

因爲Java字節碼的抽象級別較高,所以它們較容易被反編譯。本節介紹了幾種經常使用的方法,用於保護Java字節碼不被反編譯。一般,這些方法不可以絕對防止程序被反編譯,而是加大反編譯的難度而已,由於這些方法都有本身的使用環境和弱點。數組

1. 隔離Java程序 安全

最簡單的方法就是讓用戶不可以訪問到Java Class程序,這種方法是最根本的方法,具體實現有多種方式。例如,開發人員能夠將關鍵的Java Class放在服務器端,客戶端經過訪問服務器的相關接口來得到服務,而不是直接訪問Class文件。這樣黑客就沒有辦法反編譯Class文件。目前,經過接口提供服務的標準和協議也愈來愈多,例如 HTTP、Web Service、RPC等。可是有不少應用都不適合這種保護方式,例如對於單機運行的程序就沒法隔離Java程序。這種保護方式見圖1所示。
 
                             圖1隔離Java程序示意圖

2. 對Class文件進行加密
      爲了防止Class文件被直接反編譯,許多開發人員將一些關鍵的Class文件進行加密,例如對註冊碼、序列號管理相關的類等。在使用這些被加密的類以前,程序首先須要對這些類進行解密,然後再將這些類裝載到JVM當中。這些類的解密能夠由硬件完成,也可使用軟件完成。
在實現時,開發人員每每經過自定義ClassLoader類來完成加密類的裝載(注意因爲安全性的緣由,Applet不可以支持自定義的 ClassLoader)。自定義的ClassLoader首先找到加密的類,然後進行解密,最後將解密後的類裝載到JVM當中。在這種保護方式中,自定義的ClassLoader是很是關鍵的類。因爲它自己不是被加密的,所以它可能成爲黑客最早攻擊的目標。若是相關的解密密鑰和算法被攻克,那麼被加密的類也很容易被解密。這種保護方式示意圖見圖2。
 
                                  圖2 對Class文件進行加密示意圖服務器


3. 轉換成本地代碼
將程序轉換成本地代碼也是一種防止反編譯的有效方法。由於本地代碼每每難以被反編譯。開發人員能夠選擇將整個應用程序轉換成本地代碼,也能夠選擇關鍵模塊轉換。若是僅僅轉換關鍵部分模塊,Java程序在使用這些模塊時,須要使用JNI技術進行調用。
固然,在使用這種技術保護Java程序的同時,也犧牲了Java的跨平臺特性。對於不一樣的平臺,咱們須要維護不一樣版本的本地代碼,這將加劇軟件支持和維護的工做。不過對於一些關鍵的模塊,有時這種方案每每是必要的。
爲了保證這些本地代碼不被修改和替代,一般須要對這些代碼進行數字簽名。在使用這些本地代碼以前,每每須要對這些本地代碼進行認證,確保這些代碼沒有被黑客更改。若是簽名檢查經過,則調用相關JNI方法。這種保護方式示意圖見圖3。
 
                           圖3 轉換成本地代碼示意圖 數據結構

4. 代碼混淆
代碼混淆是對Class文件進行從新組織和處理,使得處理後的代碼與處理前代碼完成相同的功能(語義)。可是混淆後的代碼很難被反編譯,即反編譯後得出的代碼是很是難懂、晦澀的,所以反編譯人員很可貴出程序的真正語義。從理論上來講,黑客若是有足夠的時間,被混淆的代碼仍然可能被破解,甚至目前有些人正在研製反混淆的工具。可是從實際狀況來看,因爲混淆技術的多元化發展,混淆理論的成熟,通過混淆的Java代碼仍是可以很好地防止反編譯。下面咱們會詳細介紹混淆技術,由於混淆是一種保護Java程序的重要技術。圖4是代碼混淆的示圖。  
                            圖4 代碼混淆示意圖

函數

幾種技術的總結 
以上幾種技術都有不一樣的應用環境,各自都有本身的弱點,表1是相關特色的比較。
混淆技術介紹
表1 不一樣保護技術比較表
工具

      到目前爲止,對於Java程序的保護,混淆技術仍是最基本的保護方法。Java混淆工具也很是多,包括商業的、免費的、開放源代碼的。Sun公司也提供了本身的混淆工具。它們大多都是對Class文件進行混淆處理,也有少許工具首先對源代碼進行處理,而後再對Class進行處理,這樣加大了混淆處理的力度。目前,商業上比較成功的混淆工具包括JProof公司的1stBarrier系列、Eastridge公司的JShrink和 4thpass.com的SourceGuard等。主要的混淆技術按照混淆目標能夠進行以下分類,它們分別爲符號混淆(Lexical Obfuscation)、數據混淆(Data Obfuscation)、控制混淆(Control Obfuscation)、預防性混淆(Prevent Transformation)。
符號混淆
在Class中存在許多與程序執行自己無關的信息,例如方法名稱、變量名稱,這些符號的名稱每每帶有必定的含義。例如某個方法名爲 getKeyLength(),那麼這個方法極可能就是用來返回Key的長度。符號混淆就是將這些信息打亂,把這些信息變成無任何意義的表示,例如將全部的變量從vairant_001開始編號;對於全部的方法從method_001開始編號。這將對反編譯帶來必定的困難。對於私有函數、局部變量,一般能夠改變它們的符號,而不影響程序的運行。可是對於一些接口名稱、公有函數、成員變量,若是有其它外部模塊須要引用這些符號,咱們每每須要保留這些名稱,不然外部模塊找不到這些名稱的方法和變量。所以,多數的混淆工具對於符號混淆,都提供了豐富的選項,讓用戶選擇是否、如何進行符號混淆。
數據混淆
 
圖5 改變數據訪問
數據混淆是對程序使用的數據進行混淆。混淆的方法也有多種,主要能夠分爲改變數據存儲及編碼(Store and Encode Transform)、改變數據訪問(Access Transform)。
改變數據存儲和編碼能夠打亂程序使用的數據存儲方式。例如將一個有10個成員的數組,拆開爲10個變量,而且打亂這些變量的名字;將一個兩維數組轉化爲一個一維數組等。對於一些複雜的數據結構,咱們將打亂它的數據結構,例如用多個類代替一個複雜的類等。
另一種方式是改變數據訪問。例如訪問數組的下標時,咱們能夠進行必定的計算,圖5就是一個例子。
在實踐混淆處理中,這兩種方法一般是綜合使用的,在打亂數據存儲的同時,也打亂數據訪問的方式。通過對數據混淆,程序的語義變得複雜了,這樣增大了反編譯的難度。

控制混淆
控制混淆就是對程序的控制流進行混淆,使得程序的控制流更加難以反編譯,一般控制流的改變須要增長一些額外的計算和控制流,所以在性能上會給程序帶來必定的負面影響。有時,須要在程序的性能和混淆程度之間進行權衡。控制混淆的技術最爲複雜,技巧也最多。這些技術能夠分爲以下幾類:
增長混淆控制經過增長額外的、複雜的控制流,能夠將程序原來的語義隱藏起來。例如,對於按次序執行的兩個語句A、B,咱們能夠增長一個控制條件,以決定B的執行。經過這種方式加大反彙編的難度。可是全部的干擾控制都不該該影響B的執行。圖6就給出三種方式,爲這個例子增長混淆控制。
 
圖6 增長混淆控制的三種方式
控制流重組重組控制流也是重要的混淆方法。例如,程序調用一個方法,在混淆後,能夠將該方法代碼嵌入到調用程序當中。反過來,程序中的一段代碼也能夠轉變爲一個函數調用。另外,對於一個循環的控制流,爲能夠拆分多個循環的控制流,或者將循環轉化成一個遞歸過程。這種方法最爲複雜,研究的人員也很是多。
預防性混淆
這種混淆一般是針對一些專用的反編譯器而設計的,通常來講,這些技術利用反編譯器的弱點或者Bug來設計混淆方案。例如,有些反編譯器對於 Return後面的指令不進行反編譯,而有些混淆方案偏偏將代碼放在Return語句後面。這種混淆的有效性對於不一樣反編譯器的做用也不太相同的。一個好的混淆工具,一般會綜合使用這些混淆技術。性能

案例分析
在實踐當中,保護一個大型Java程序常常須要綜合使用這些方法,而不是單一使用某一種方法。這是由於每種方法都有其弱點和應用環境。綜合使用這些方法使得Java程序的保護更加有效。另外,咱們常常還須要使用其它的相關安全技術,例如安全認證、數字簽名、PKI等。
本文給出的例子是一個Java應用程序,它是一個SCJP(Sun Certificate Java Programmer)的模擬考試軟件。該應用程序帶有大量的模擬題目,全部的題目都被加密後存儲在文件中。因爲它所帶的題庫是該軟件的核心部分,因此關於題庫的存取和訪問就成爲很是核心的類。一旦這些相關的類被反編譯,則全部的題庫將被破解。如今,咱們來考慮如何保護這些題庫及相關的類。
在這個例子中,咱們考慮使用綜合保護技術,其中包括本地代碼和混淆技術。由於該軟件主要發佈在Windows上,所以轉換成本地代碼後,僅僅須要維護一個版本的本地代碼。另外,混淆對Java程序也是很是有效的,適用於這種獨立發佈的應用系統。
在具體的方案中,咱們將程序分爲兩個部分,一個是由本地代碼編寫的題庫訪問的模塊,另一個是由Java開發的其它模塊。這樣能夠更高程度地保護題目管理模塊不被反編譯。對於Java開發的模塊,咱們仍然要使用混淆技術。該方案的示意圖參見圖7。
 
圖7 SCJP保護技術方案圖
對於題目管理模塊,因爲程序主要在Windows下使用,因此使用C++開發題庫訪問模塊,而且提供了必定的訪問接口。爲了保護題庫訪問的接口,咱們還增長了一個初始化接口,用於每次使用題庫訪問接口以前的初始化工做。它的接口主要分爲兩類:
1. 初始化接口
在使用題庫模塊以前,咱們必須先調用初始化接口。在調用該接口時,客戶端須要提供一個隨機數做爲參數。題庫管理模塊和客戶端經過這個隨機數,按必定的算法同時生成相同的SessionKey,用於加密之後輸入和輸出的全部數據。經過這種方式,只有受權(有效)的客戶端纔可以鏈接正確的鏈接,生成正確的 SessionKey,用於訪問題庫信息。非法的客戶很難生成正確的SessionKey,所以沒法得到題庫的信息。若是須要創建更高的保密級別,也能夠採用雙向認證技術。
2. 數據訪問接口
認證完成以後,客戶端就能夠正常的訪問題庫數據。可是,輸入和輸出的數據都是由SessionKey所加密的數據。所以,只有正確的題庫管理模塊纔可以使用題庫管理模塊。圖8時序圖表示了題庫管理模塊和其它部分的交互過程。
  編碼

相關文章
相關標籤/搜索