JAVA 類文件保護(hù)分析論文

時間:2022-09-10 09:06:00

導(dǎo)語:JAVA 類文件保護(hù)分析論文一文來源于網(wǎng)友上傳,不代表本站觀點(diǎn),若需要原創(chuàng)文章可咨詢客服老師,歡迎參考。

JAVA 類文件保護(hù)分析論文

【摘要】:由于Java語言面向?qū)ο蠛途幾g成中間代碼執(zhí)行的特點(diǎn),其在抗反編譯和反盜版方面顯得尤其脆弱。本文針對Java軟件的特點(diǎn),運(yùn)用多種方法,綜合設(shè)計出一個保護(hù)Java類文件的方法。

關(guān)鍵詞:Class;加密;密鑰;代碼混淆

1.引言

目前,Java編程語言的應(yīng)用在全世界范圍正流行,它廣泛的應(yīng)用在Internet的數(shù)據(jù)庫、多媒體、CGI及動態(tài)網(wǎng)頁的制作方面。1999年在美國對Java程序員的需求量首次超過C++。經(jīng)調(diào)查統(tǒng)計,Java語言應(yīng)用在軟件領(lǐng)域占領(lǐng)著舉足輕重的地位,為人類科技文明進(jìn)步奠定了重要基礎(chǔ)。然而,Java語言卻存在著巨大的安全隱患。Java是一種跨平臺的、解釋型語言。第一,Java源代碼編譯中間“字節(jié)碼”存儲于Class文件中。Class文件是一種字節(jié)碼形式的中間代碼,該字節(jié)碼中包括了很多源代碼的信息,例如變量名、方法名等;第二,由于跨平臺的需求,Java的指令集比較簡單通用,較容易得出程序的語義信息;第三,Java編譯器將每一個類編譯成一個單獨(dú)的文件,這也簡化了反編譯的工作;第四,Java的Class文件中,仍然保留所有的方法和變量的名稱,可以通過這些名稱來訪問變量和方法,這些符號往往帶有許多語義信息。因此,Java程序的這些特點(diǎn),很容易對不經(jīng)過處理的Java程序進(jìn)行反編譯。目前,市場上有許多優(yōu)秀的Java反編譯工具,能夠反編譯出非常接近源代碼的程序。所以,對開發(fā)人員來說,如何保護(hù)Java程序就變成一個非常重要的任務(wù)。

2.Java類文件的安全威脅

2.1Java的編譯

開發(fā)Java應(yīng)用程序首先是使用編輯工具編寫Java的源代碼,然后使用編譯器編譯成虛擬機(jī)可執(zhí)行的Class類文件。編譯后生成的類文件是一種有格式的中間代碼——字節(jié)碼文件,不能在本地機(jī)器上獨(dú)立運(yùn)行,只能在Java虛擬機(jī)里解釋執(zhí)行。Java編譯器不對變量和方法等符號的引用轉(zhuǎn)換為數(shù)值引用,也不確定程序執(zhí)行過程中的內(nèi)存布局,而是將這些符號的引用信息保留在類文件中,由解釋器在運(yùn)行過程中創(chuàng)建內(nèi)存布局,然后再通過查找表來確定一個變量或方法所在的地址。

從Java類文件的結(jié)構(gòu)及其實(shí)際數(shù)據(jù)可知Java類文件保留了源代碼文件的大部分信息,如所有的變量和方法等信息。正是由于這個特點(diǎn),只要在各個平臺上實(shí)現(xiàn)了各自的Java虛擬機(jī),不用修改Java應(yīng)用程序的源代碼就可以在各個平臺上運(yùn)行,真正做到跨平臺的特性,這也是Java能夠迅速流行起來的重要原因。

2.2Java的反編譯

反編譯是一個將目標(biāo)代碼轉(zhuǎn)換成源代碼的過程。而目標(biāo)代碼是一種用語言表示的代碼,這種語言能通過實(shí)機(jī)或虛擬機(jī)直接執(zhí)行。從本質(zhì)上說,他需要根據(jù)小規(guī)模、低層次的行為來推斷大規(guī)模、高層次的行為。因此,反編譯目標(biāo)代碼并不容易。

在JDK中,有一個反編譯器javap,利用該工具可以對Java類文件進(jìn)行反編譯。經(jīng)過

該工具反匯編后得到的結(jié)果并不是源代碼,但是使用javap進(jìn)行反編譯的Java類文件可以得到成員變量、方法、行號以及局部變量名等信息。在javap工具的基礎(chǔ)上,一些反編譯工具如Mocha,WinDis,DjDecompiler等工具可反編譯出和源代碼幾乎一摸一樣的代碼。

3.常用Java類文件保護(hù)方法

由于Java字節(jié)碼的抽象級別較高,容易被反編譯,所以就有了多種防止Java字節(jié)碼被反編譯的方法。

隔離Java程序:最簡單的方法就是讓用戶不能夠訪問到JavaClass程序,這種方法是最根本的方法,具體實(shí)現(xiàn)有多種方式。

代碼混淆:這種方法對Class文件進(jìn)行重新組織和處理,使得處理前后的代碼具有相同的語義,被混淆后的代碼很難被反編譯。

轉(zhuǎn)換成本地代碼:本地代碼難以被反編譯,開發(fā)人員可以選擇將整個應(yīng)用程序或關(guān)鍵模塊轉(zhuǎn)換成本地代碼。如果僅僅轉(zhuǎn)換關(guān)鍵模塊,在使用這些模塊時,需調(diào)用JNI技術(shù),這將犧

牲Java的跨平臺特性

加密Class文件:為了防止Class文件被直接反編譯,可以將一些關(guān)鍵的Class文件加密

,例如對密鑰、加密算法、注冊碼、序列號管理相關(guān)的類等。在使用這些被加密的類之前先解密,然后再將其裝載到JVM中。

對比上述幾種方法,都存在其自身的優(yōu)缺點(diǎn)。隔離Java程序只能適合網(wǎng)絡(luò)環(huán)境的客戶機(jī)/服務(wù)器結(jié)構(gòu)或者分布式的環(huán)境,對單機(jī)運(yùn)行的程序就無法隔離,而且Java程序需要使用安全機(jī)制保護(hù)服務(wù)器開放接口的使用,服務(wù)器的安全成了整個系統(tǒng)安全的焦點(diǎn)。代碼本地化,對于不同的平臺,需要維護(hù)不同版本的本地代碼,這將加重軟件支持和維護(hù)的工作。對Class文件進(jìn)行加密,在使用時再進(jìn)行解密,同時將關(guān)鍵加密代碼部分進(jìn)行代碼混淆,這樣經(jīng)過雙重處理后,代碼的安全性提高了很多,該方法也是本文研究的重點(diǎn)。

4.Class文件加密技術(shù)

Java生成的Class文件大量暴露在客戶端,利用現(xiàn)在的反編譯工具可輕易的獲取源代碼,下面將講敘如何有效的保護(hù)Class文件。

第一,讀取本工程的所有待加密Class文件,并保存到byte型數(shù)組中;

publicstaticbyte[]symmetricEncrypt(byte[]key,byte[]classData){…};方法對讀取到的所

有Class文件進(jìn)行加密,key為用來加密的密鑰,classData為所讀到的待加密Class文件,返回結(jié)果為加密后的Class文件,然后將其寫回原來的Class中,保證結(jié)構(gòu)的完整性。

第二,加密過的Class文件在使用之前需先對其進(jìn)行解密。

Java虛擬機(jī)有默認(rèn)的類加載器,但是若要它根據(jù)用戶提供的密碼解密代碼就難以做到,此時需要通過自定義ClassLoader類來完成加密類的裝載。自定義的ClassLoader首先找到被加密過的類,然后進(jìn)行解密,最后將解密后的類裝載到JVM中。這里我的自定義ClassLoader如下:

ClassLoaderappLoader=newEncryptedClassLoader(EncryptedClassLoader.class.getClassLoader(),newFile(args));

Thread.currentThread().setContextClassLoader(appLoader);

finalClassapp=appLoader.loadClass(args);

其中參數(shù)args傳入的是方法所在的工程名,args為主函數(shù)所在的類名。

在加載類后,系統(tǒng)的默認(rèn)findClass()并未對加載的類作任何處理,由于Class文件已被

加密過,此時若運(yùn)用系統(tǒng)方法findClass()則會拋出ClassNotFoundException()的異常,所以這里需要重構(gòu)我自己的findClass()方法:

protectedClassfindClass(finalStringname)throwsClassNotFoundException{

finalStringclassResource=name.replace(''''.'''',''''/'''')+".class";finalURLclassURL=getResource(classResource);InputStreamin=null;

Filefile=newFile(classURL.getPath());

byte[]classBytes=newbyte[(int)file.length()];FileInputStreamfin=newFileInputStream(file);fin.read(classBytes);

……

classBytes=decrypt(classBytes);//解密

……

returndefineClass(name,classBytes,0,classBytes.length);

}

在這個函數(shù)中,我運(yùn)用decrypt(classBytes);方法對所有的加密Class文件進(jìn)行解密,并在其中調(diào)用方法publicstaticbyte[]symmetricEncrypto(byte[]key,byte[]byteSource){}將解密后的Class文件保存直原文件處,保持文件目錄級別不變,key為解密密鑰,byteSource為待

解密的byte型文件。至此,已完成對類文件的加密和解密,經(jīng)過測試,功能已實(shí)現(xiàn),Class

文件無法被反編譯。但為進(jìn)一步加強(qiáng)程序的安全性,我做了如下的處理。

第三,對包含有關(guān)鍵信息的方法進(jìn)行代碼混淆處理。在上述內(nèi)容中,方法symmetricEncrypt(byte[]key,byte[]classData)包含有加密所用到的算法,自定義的ClassLoade

r包含有關(guān)鍵信息,findClass(finalStringname)以及decrypt(classBytes);中包含有解密信息,由于它們本身不是被加密的,因此它可能成為黑客最先攻擊的目標(biāo)。如果相關(guān)的解密密鑰和算法被攻克,那么被加密的類也很容易被解密。所以這里我對這些關(guān)鍵代碼進(jìn)行代碼混淆。代碼混淆是對代碼進(jìn)行重新組織和處理,使得處理后的代碼與處理前的代碼完成相同的功能,但是混淆后的代碼很難被反編譯。代碼混淆有符號混淆、數(shù)據(jù)混淆、控制混淆和預(yù)防性混淆。這里我采用數(shù)據(jù)混淆對關(guān)鍵代碼進(jìn)行處理。

publicstaticbyte[]symmetricEncrypt(byte[]key,byte[]classData){…};處理如下:

//rawKey,byteSource為symmetricEncrypt(byte[],byte[])的待傳入?yún)?shù)

byte[]tempkey=null;

tempkey[0]=0x00;

for(inti=0;i<key.length;i++)

tempkey[i+1]=key[i];

tempkey[key.length+1]=0x11;

byte[]source=null;

source[0]=0x00;

for(inti=0;i<classData.length;i++)source[i+1]=classData[i];source[classData.length+1]=0x11;

publicstaticbyte[]symmetricEncrypt(byte[]tempkey,byte[]source){

//取tempkey和source的除第一個和最后一個byte的值

......

}

對publicClassloadClass(finalStringtempname,finalbooleanresolve){}方法進(jìn)行處理:

Stringtempname="abcdefg"+name;//name:loadClass的第一個待傳入?yún)?shù)

publicClassloadClass(finalStringtempname,finalbooleanresolve){Stringname=tempname.substring(11,tempname.length());

......

}

對findClass(Stringname){}方法進(jìn)行處理:

//name為findClass(Stringname)待傳入?yún)?shù),先做如下處理

addname=name+"01357924680";

protectedClassfindClass(finalStringaddname){

name=addname.substring(0,addname.length()-11);

......//fingClass其他工作

}

intlen;//len=待傳文件file的長度:file.length()

byte[]classBytes=newbyte[(int)len];classBytes[len+1]=0x00;classBytes[len+2]=0x11;

//classBytes作為decrypt(byte[]classBytes)的傳入?yún)?shù)

privatestaticbyte[]decrypt(finalbyte[]classBytes){

byte[]data=newbyte[(int)classByte.lengt-2];

for(inti=0;i<data.length;i++)

data[i]=classBytes[i];

......//解密工作

}

5.結(jié)論

本文介紹了我針對Java類文件設(shè)計的保護(hù)方法,在眾多方法中,我選擇了對Class文件進(jìn)行加密這一思想,加密之后又對包含重要信息的方法進(jìn)行代碼混淆處理,這樣就對文件起到了雙重保護(hù)的作用。經(jīng)過在Windows平臺上測試,效果良好,難以反編譯,起到了很好的保護(hù)作用。