Java軟件如何加密

Java軟件由于Java語言面向?qū)ο蠛途幾g成中間碼執(zhí)行的特點(diǎn),其在抗反編譯和反盜版方面顯得尤其脆弱,為此,我們針對Java軟件的特點(diǎn),綜合運(yùn)用各種加密方法,探索設(shè)計(jì)出一個實(shí)用型Java軟件加密保護(hù)方法。

一、Java軟件加密基本思路

對于應(yīng)用軟件的保護(hù)筆者從兩個方面進(jìn)行考慮,第一是阻止盜版使用軟件,第二是阻止競爭對手對軟件反編譯,即阻止對軟件的逆向工程。

1、阻止盜版

在軟件運(yùn)行時對自身存在的合法性進(jìn)行判斷,如果認(rèn)為自身的存在和運(yùn)行是被授權(quán)的、合法的,就運(yùn)行;否則終止運(yùn)行。這樣即使軟件可以被隨意復(fù)制,只要盜版用戶沒有相應(yīng)的授權(quán)信息就無法使用軟件。

2、阻止反編譯

對編譯產(chǎn)生的Class文件加密處理,并在運(yùn)行時進(jìn)行解密,解密者無法對軟件進(jìn)行反編譯。

二、Java軟件加密的總體流程

為了保護(hù)用Java語言開發(fā)的軟件,我們設(shè)計(jì)并實(shí)現(xiàn)了一個實(shí)用、高強(qiáng)度的加密算法。以下稱需要保護(hù)的Java軟件為“受保護(hù)程序”,稱對“受保護(hù)程序”進(jìn)行加密保護(hù)的軟件為“加密程序”。對軟件加密保護(hù)的流程如圖1所示。

Java軟件如何加密

三、加密算法分析設(shè)計(jì)

1、用戶信息提取器設(shè)計(jì)

為了防止用戶發(fā)布序列號而導(dǎo)致“一次發(fā)行,到處都是”的盜版問題,提取用戶機(jī)器中硬件相關(guān)的、具有唯一性的信息——用戶計(jì)算機(jī)的硬盤分區(qū)C的序列號,并要求用戶將此信息與用戶名一起返回,之后用“序列號生成器”根據(jù)用戶返回信息生成一個唯一合法的軟件注冊序列號發(fā)回用戶,用戶即可使用此號碼注冊使用軟件。

這個信息提取器使用Winclows 32匯編以一個獨(dú)立的小程序方式實(shí)現(xiàn),程序代碼如圖2所示。

Java軟件如何加密

2、序列號生成器與序列號合法性判斷函數(shù)的設(shè)計(jì)

序列號生成器與序列號合法性判斷函數(shù)中運(yùn)用RSA加密算法。在序列號生成器中是使用私鑰將用戶返回的信息(硬盤序列號,用戶名)進(jìn)行加密得到相應(yīng)的注冊序列號;在序列號合法性判斷函數(shù)中使用私鑰將用戶輸入的注冊序列號解密,再與(硬盤序列號,用戶名)進(jìn)行比較,一致則調(diào)用程序裝載器將程序其他部分解密裝入內(nèi)存,初始化刪環(huán)境并運(yùn)行程序主體;否則退出。

RSA加密算法的實(shí)現(xiàn)需要使用大數(shù)運(yùn)算庫,我們使用MIRACL大數(shù)庫來實(shí)現(xiàn)RSA計(jì)算,序列號生成器的主要代碼如下:

char szlnputString[]="機(jī)器碼和用戶名組成的字符串";

char szSerial[256]=[0];//用于存放生成的注冊碼

bign,d,c,m; //MIRACL中的大數(shù)類型

mip→IBASE=16; //以16進(jìn)制模式

n= mlrvar(0); //初始化大數(shù)

d= mirvar(0);

c= mirvar(0); //C存放輸入的字符串大數(shù)

m= mlrva(o);

bytes to big( len, szlnputString,c);

//將輸入字符串轉(zhuǎn)換成大數(shù)形式并存入變量c中

cinstr(n,"以字符串形成表示的模數(shù)");//初始化模數(shù)

cinstr(d,"以字符串形成表示的公鑰")://初始化公鑰

powmod(c,d,n,m); //計(jì)算m=cdmod n

cotstr(m,szSerial);//m的16進(jìn)制字符串即為注冊碼

序列號合法性檢測函數(shù)的主要代碼如下:

char szlnputStringL]=”機(jī)器碼和用戶名組成的字符串";

char szSerial[ 256]="用戶輸入的序列號"

bign,e,c,m; //MIRACL中的大數(shù)類型

mip→IBASE=16; //以16進(jìn)制模式

cinstr(m,szSerial); //將序列號的16進(jìn)制轉(zhuǎn)成大數(shù)形式

cinstr(n,"模數(shù)n的字符串形式");//初始化模數(shù)n

cinstr(e,"字符串形式的公鑰");//初始化公鑰

if compare(m,n)==-1) //m<n時才進(jìn)行解密
{
powmod(m,e,n,c);//計(jì)算m=me mod n

big_to _bytes(0,c,szSerial,0); //轉(zhuǎn)為字符串

return lstrcmp( szlnputString,szSerial);

}

3、強(qiáng)耦合關(guān)系的設(shè)計(jì)

如果在序列號合法性檢測函數(shù)中簡單地使用圖3所示流程:

Java軟件如何加密

解密者可以使用以下幾種手段進(jìn)行攻擊:

(1)修改“判斷合法性子函數(shù)”的返回指令,讓它永遠(yuǎn)返回正確值,這樣可以使用任意的序列號,安裝/使用軟件。

(2)修改判斷后的跳轉(zhuǎn)指令,使程序永遠(yuǎn)跳到正確的分支運(yùn)行,效果和上一種一樣。

(3)在“判斷合法性子函數(shù)”之前執(zhí)行一條跳轉(zhuǎn)指令,繞過判斷,直接跳轉(zhuǎn)到“正常執(zhí)行”分支運(yùn)行,這樣可以不用輸入序列號安裝/使用軟件。

為阻止以上攻擊手段,筆者在程序中增加了“序列號合法性檢測函數(shù)”與程序其他部分“強(qiáng)耦合”(即增強(qiáng)其與程序其他部分的關(guān)聯(lián)度,成為程序整體密不可分的一部分,一旦被修改程序?qū)o法正常工作)的要求(見圖1),并且設(shè)置一個“完整性檢測函數(shù)”用于判斷相關(guān)的代碼是否被修改過。當(dāng)然,基于同樣的原因,“完整性檢測函數(shù)”也必須與程序其他部分存在“強(qiáng)耦合”關(guān)系。

強(qiáng)耦合關(guān)系通過以下方式建立:

在程序其他部分的函數(shù)(例如函數(shù)A)中隨機(jī)的訪問需要強(qiáng)耦合的“序列號合法性檢測函數(shù)”和“完整性檢測函數(shù)”,在調(diào)用時隨機(jī)的選擇使用一個錯誤的序列號或是用戶輸入的序列號,并根據(jù)返回結(jié)果選擇執(zhí)行A中正常的功能代碼還是錯誤退出的功能代碼,流程如圖4所示。

Java軟件如何加密

經(jīng)過這種改進(jìn),如果破解者通過修改代碼的方式破解將因“完整性檢測”失敗導(dǎo)致程序退出;如果使用SMC等技術(shù)繞過“序列號合法性判斷函數(shù)”而直接跳至序列號正確時的執(zhí)行入口,在后續(xù)的運(yùn)行中,將因?yàn)殡S機(jī)的耦合調(diào)用失敗導(dǎo)致程序退出。破解者要破解軟件將不得不跟蹤所有進(jìn)行了耦合調(diào)用的函數(shù),這顯然是一個艱巨的任務(wù)。

4、完整性檢測函數(shù)的設(shè)計(jì)

我們使用CRC算法算出需進(jìn)行完整性檢測的文件的校驗(yàn)碼,并用RSA加密算法的公鑰(不同于序列號合法性檢測中的公鑰/私鑰對)將其加密存放在特定的文件中,在檢測時先用CRC算法重新生成需進(jìn)行完
整性檢測的文件的校驗(yàn)碼,并用私鑰將保存的校驗(yàn)碼解密,兩者相比較,相等則正常運(yùn)行;否則退出。

5、程序加載器的設(shè)計(jì)

與編譯成機(jī)器碼執(zhí)行的程序不同,Java程序只能由Java虛擬機(jī)解釋執(zhí)行,因此程序加載器的工作包括:初始化Java虛擬機(jī);在內(nèi)存中解密當(dāng)前要運(yùn)行的class文件;使解密后的c:lass文件在虛擬機(jī)中運(yùn)行,在
需要時解密另一個class文件。圖5是用于初始化JVM的代碼:

Java軟件如何加密

以上介紹了我們設(shè)計(jì)的針對Java軟件的加密保護(hù)方法,其中綜合運(yùn)用了多種加密技術(shù),抗破解強(qiáng)度高;使用純軟件保護(hù)技術(shù),成本低。經(jīng)筆者在Windows系列平臺上進(jìn)行測試,運(yùn)行穩(wěn)定,效果良好。

在研宄開發(fā)過程中,我們還總結(jié)出加密保護(hù)軟件的一些經(jīng)驗(yàn):

1、對關(guān)鍵代碼和數(shù)據(jù)要靜態(tài)加密,再動態(tài)解密執(zhí)行;要結(jié)合具體的工作平臺使用反跟蹤/調(diào)試技術(shù);

2、要充分利用系統(tǒng)的功能,如在Windows下使用DLL文件或驅(qū)動程序形式能得到最大的豐又限,可以充分利用系統(tǒng)具有的各種功能;

3、如果可能應(yīng)該將關(guān)鍵代碼存放在不可禚復(fù)制的地方;

4、序列號要與機(jī)器碼等用戶信息相關(guān)以阻止鹽復(fù)布序列號;

5、加密流程的合理性比加密算法本身的強(qiáng)度更重要。

小知識之DLL文件

DLL是Dynamic Link Library的縮寫,意為動態(tài)鏈接庫。在Windows系統(tǒng)中,從Windows3.x的后續(xù)版本起,大部分的系統(tǒng)DLL文件被存放在%SystemPath%Windows\System32文件夾中(systempath為系統(tǒng)安裝根路徑)目錄下。DLL是一個包含可由多個程序同時使用的代碼和數(shù)據(jù)的庫。