999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

一種Java字節(jié)碼保護(hù)技術(shù)的研究和實(shí)現(xiàn)

2012-07-25 03:19:36
微處理機(jī) 2012年5期
關(guān)鍵詞:程序方法

吳 芳

(陜西省紡織科學(xué)研究所,西安710038)

1 引言

C/C++等編程語(yǔ)言開(kāi)發(fā)的程序被編譯成本機(jī)可執(zhí)行的二進(jìn)制代碼。編譯器用內(nèi)存地址代替了程序中的變量名稱、方法名稱等信息。因此對(duì)這些本地二進(jìn)制代碼進(jìn)行反編譯從而得到源代碼是非常困難,甚至是不可能的。

Java是一種跨平臺(tái)的解釋型語(yǔ)言。Java編譯工具將Java源代碼編譯成為class文件(即Java字節(jié)碼),由 Java 虛擬機(jī)(Java Virtual Machine,JVM)負(fù)責(zé)對(duì)class文件進(jìn)行解釋執(zhí)行。與本地目標(biāo)代碼不同,class文件中仍然保留了方法名稱、變量名稱,并且通過(guò)這些名稱來(lái)訪問(wèn)變量和方法,這些符號(hào)往往帶有許多語(yǔ)義信息。因此,對(duì)class文件進(jìn)行反編譯就顯得比較容易。目前,市場(chǎng)上有許多Java的反編譯工具,有免費(fèi)的,也有商用的,還有的是開(kāi)放源代碼的。這些工具都能夠從class文件生成高質(zhì)量源代碼。所以,如何保護(hù)Java程序就變成了一個(gè)非常重要的挑戰(zhàn)。

2 Java字節(jié)碼保護(hù)技術(shù)的現(xiàn)狀

目前主要有如下幾種Java字節(jié)碼保護(hù)技術(shù):隔離Java程序、字節(jié)碼混淆、轉(zhuǎn)換本地代碼、數(shù)字水印、自定義類加載器等。

隔離Java程序是指將關(guān)鍵的class文件放在服務(wù)器端,客戶端通過(guò)訪問(wèn)服務(wù)器的相關(guān)接口來(lái)獲得服務(wù),而不是直接訪問(wèn)class文件。這樣黑客就沒(méi)有辦法反編譯 class文件[1]。HTTP、Web Service、RPC等標(biāo)準(zhǔn)和協(xié)議都能夠支持通過(guò)接口提供服務(wù)。但是有很多應(yīng)用都不適合這種保護(hù)方式,例如對(duì)于單機(jī)運(yùn)行的程序就無(wú)法隔離Java程序。

字節(jié)碼混淆主要是通過(guò)將定義的類、變量、方法和包的名字改為無(wú)意義的字符串、使用非法的字符代替變量符號(hào)和在軟件中添加一些無(wú)關(guān)的指令或永遠(yuǎn)執(zhí)行不到的指令[2]等手段來(lái)增加反編譯和對(duì)反編譯后源代碼閱讀的難度。但這種方法并不能真正阻止反編譯,而且不論是開(kāi)源的或是商用的混淆工具都有一定的規(guī)律可循,如果掌握這些規(guī)律,在反編譯時(shí)仍然可以得到一定質(zhì)量的源代碼。

轉(zhuǎn)換本地代碼即將Java程序像C/C++程序一樣編譯成本機(jī)可執(zhí)行的二進(jìn)制代碼,目前TowerJ、jexegen、JET、JOVE、JToEXE 等工具都能做到這一點(diǎn)。但是這樣做使得Java程序失去其跨平臺(tái)的特性,而且這種技術(shù)目前并不十分成熟,因此不適用于大型應(yīng)用程序。

數(shù)字水印技術(shù)是在class文件中嵌入以數(shù)字水印形式存在的開(kāi)發(fā)者簽名[3]。數(shù)字水印技術(shù)并不能阻止反編譯,但是能在確認(rèn)某些程序是否屬于剽竊時(shí)提供有效的證據(jù)。

自定義類加載器是指首先將class文件進(jìn)行加密處理,然后自己編寫一個(gè)Java類裝載器(即繼承java.lang.ClassLoader并重載其 loadClass方法)在class文件裝載時(shí)再進(jìn)行解密處理。這種方法的缺點(diǎn)在于雖然經(jīng)過(guò)加密的class文件無(wú)法被反編譯,但自定義的類加載器本身卻不能防止被反編譯。因此,加密過(guò)的class文件仍然是不安全的。

另外,一些商用的專業(yè)數(shù)據(jù)加密軟件也能提供對(duì)Java字節(jié)碼的保護(hù),如HASP、CodeMeter等,其原理是對(duì)Java程序和java.exe都進(jìn)行加殼處理,在Java程序運(yùn)行時(shí)需要連接加密狗進(jìn)行解密。這種方法雖然安全性較高但是對(duì)于不使用java.exe來(lái)運(yùn)行的Java程序(如Eclipse平臺(tái)使用的是javaw.exe)則無(wú)能為力。因此通用性較差。

3 利用JVMTI和JNI保護(hù)Java字節(jié)碼

通過(guò)第一節(jié)對(duì)Java字節(jié)碼保護(hù)現(xiàn)狀的分析可以得出結(jié)論:要找到一種更好的Java字節(jié)碼保護(hù)方法則必須滿足以下3個(gè)條件:

·能夠有效防止反編譯,使得Java程序的安全級(jí)別相當(dāng)于本地應(yīng)用程序。

·保持Java程序的跨平臺(tái)特性。

·不修改JVM。

將class文件作為數(shù)據(jù)文件進(jìn)行加密是比較容易的(關(guān)于數(shù)據(jù)加密的算法很多,在此不再贅述),實(shí)現(xiàn)了這一步即可阻止對(duì)class文件的直接反編譯。但問(wèn)題的關(guān)鍵在于何時(shí)以何種方式將加密過(guò)的class文件安全地解密?首先來(lái)分析一下JVM的類加載機(jī)制。

3.1 JVM的類加載機(jī)制

Java語(yǔ)言是一種動(dòng)態(tài)性的解釋型語(yǔ)言。Java編譯器將每個(gè)類和接口都編譯成一個(gè)單獨(dú)的class文件,這些文件對(duì)于JVM來(lái)說(shuō)就是一個(gè)個(gè)可以動(dòng)態(tài)加載的單元,這些文件只有在需要使用時(shí)才會(huì)被加載。當(dāng)指定程序運(yùn)行的時(shí)候,JVM就將class文件按照需求和一定的規(guī)則加載到JVM的內(nèi)存,并組織成為一個(gè)完整的Java應(yīng)用程序。

JVM初始化類加載器的過(guò)程如圖1所示。

圖1 JVM類加載器的初始化

JVM被激活后,會(huì)產(chǎn)生第一個(gè)類加載器BootstrapClassLoader,BootstrapClassLoader 是采用 C++語(yǔ)言編寫的本地代碼。BootstrapClassLoader首先加載Launcher.java之中的 ExtClassLoader,并設(shè)定其Parent為 null,代表其父加載器為 BootstrapClass-Loader。然后 BootstrapClassLoader再要求加載Launcher.java之中的AppClassLoader,并設(shè)定其Parent為之前產(chǎn)生的ExtClassLoader實(shí)例。在這三個(gè)類加載器中 BootstrapClassLoader和 ExtClassLoader用來(lái)加載JVM的系統(tǒng)類,AppClassLoader用來(lái)加載用戶自己的類。AppClassLoader首先通過(guò)其findclass方法查找需要加載的class文件,然后調(diào)用defineclass方法將class文件的內(nèi)容轉(zhuǎn)換成Class對(duì)象。AppClassLoader的defineclass方法最終調(diào)用的是其超類ClassLoader中的本地方法defineclass1。defineclass1方法的第二個(gè)參數(shù)就是class文件的內(nèi)容。

通過(guò)上述分析,如果有一種Hook機(jī)制能夠?qū)VM調(diào)用本地方法defineclass1的事件截獲,并在Hook函數(shù)中利用本地方法實(shí)現(xiàn)對(duì)class文件內(nèi)容的解密操作,然后將解密后的字節(jié)碼傳遞給JVM,這樣就能使解密過(guò)程僅在內(nèi)存中進(jìn)行,從而實(shí)現(xiàn)對(duì)加密后的class文件的安全解密。

3.2 JNI和JVMTI

JNI的全稱是 Java Native Interface[4](Java 本地接口)。JNI是JDK的一部分,用于為Java提供本地代碼接口。JNI使得運(yùn)行在JVM虛擬機(jī)上的Java代碼能夠操作使用其它語(yǔ)言編寫的應(yīng)用程序和庫(kù),如C/C++以及匯編語(yǔ)言等。JNI在Java程序和C/C++程序間的調(diào)用原理如圖2所示。

圖2 JNI在Java程序和C/C++程序間的調(diào)用原理

通過(guò)JNI中提供的接口,本地代碼可以與JVM進(jìn)行交互,其中有一個(gè)名為RegisterNatives的接口,這個(gè)接口可以注冊(cè)與某個(gè)類的方法關(guān)聯(lián)的本地代碼。

JVMTI的全稱是Java Virtual Machine Tool Interface[5](Java 虛擬機(jī)工具接口),它提供了一種監(jiān)視JVM狀態(tài)及控制JVM執(zhí)行的方法:JVMTI客戶端(又稱為代理或Agent)。JVMTI客戶端能夠從JVM監(jiān)聽(tīng)到感興趣的事件。用戶可以通過(guò)JVM的-agentlib參數(shù)向JVM注冊(cè)JVMTI客戶端。下面對(duì)所要涉及的JVMTI函數(shù)和事件做簡(jiǎn)要說(shuō)明。

·Agent_OnLoad、Agent_OnUnload函數(shù):JVM 與代理交互的入口和出口函數(shù)。

·SetEventNotificationMode函數(shù):該函數(shù)可以向JVM注冊(cè)要監(jiān)聽(tīng)的事件。

·SetEventCallbacks函數(shù):該函數(shù)可以為用SetEventNotificationMode注冊(cè)過(guò)的監(jiān)聽(tīng)事件指定Hook函數(shù)。

·VMInit事件:JVM的初始化事件,這個(gè)事件的發(fā)生表示JVM初始化的完成。在該事件完成后,JVMTI客戶端就可以得到JNI和JVMTI環(huán)境。

通過(guò)對(duì) JNI和 JVMTI的分析可知只要采用JVMTI技術(shù)編寫合適的JVMTI客戶端就能夠監(jiān)聽(tīng)到class文件的加載事件;然后向該事件掛接一個(gè)采用JNI技術(shù)編寫事件的回調(diào)函數(shù),在回調(diào)函數(shù)中對(duì)字節(jié)碼進(jìn)行解密處理,這樣就可以在JVM加載字節(jié)碼的時(shí)候利用本地代碼將其解密。

由于JVMTI客戶端和JNI回調(diào)函數(shù)都是本地代碼,并且解密的動(dòng)作在JVM的內(nèi)存中完成,不在本地保留解密后的字節(jié)碼,因此解密動(dòng)作的安全級(jí)別與本地代碼相當(dāng)。

由于JNI和JVMTI都是JVM提供的機(jī)制,與平臺(tái)無(wú)關(guān),即JVMTI客戶端和 JNI回調(diào)函數(shù)在支持JVM的平臺(tái)上都可以實(shí)現(xiàn),所以這種方法能夠保持Java程序的跨平臺(tái)特性。

4 解密實(shí)現(xiàn)

當(dāng)JVM加載一個(gè)JVMTI客戶端時(shí)會(huì)自動(dòng)調(diào)用Agent_OnLoad函數(shù),如果在這個(gè)函數(shù)中向JVM注冊(cè)VMInit事件及回調(diào)函數(shù),那么JVM初始化后JVMTI客戶端就會(huì)監(jiān)聽(tīng)到VMInit事件并進(jìn)入該事件的回調(diào)函數(shù)。在回調(diào)函數(shù)中利用JNI提供的RegisterNatives函數(shù)將ClassLoader.defineclass1方法注冊(cè)為自定義的一個(gè)代理函數(shù),這樣就可以攔截 JVM對(duì)ClassLoader.defineclass1方法的調(diào)用。當(dāng)JVM在為了生成某個(gè)類的Class對(duì)象而調(diào)用ClassLoader.defineclass1方法時(shí),它會(huì)調(diào)用自定義的代理函數(shù),在代理函數(shù)中實(shí)現(xiàn)對(duì)字節(jié)碼的解密。

JVMTI客戶端和JNI回調(diào)函數(shù)在支持JVM的平臺(tái)上都可以實(shí)現(xiàn),這里僅以Windows平臺(tái)和Linux平臺(tái)為例說(shuō)明。

4.1 基于Windows平臺(tái)的實(shí)現(xiàn)

在Windows平臺(tái)上JVMTI客戶端以動(dòng)態(tài)鏈接庫(kù)的形式出現(xiàn)。支持創(chuàng)建動(dòng)態(tài)鏈接庫(kù)的開(kāi)發(fā)工具很多,這里以Microsoft Visual C++為例說(shuō)明。

首先創(chuàng)建一個(gè)動(dòng)態(tài)鏈接庫(kù)項(xiàng)目,并將JDK中JVMTI和 JNI相關(guān)的頭文件(jvmti.h、jni.h、jni_md.h)引入到項(xiàng)目中以建立支持JVMTI和JNI的編程環(huán)境;然后創(chuàng)建Agent_OnLoad函數(shù),在該函數(shù)中通過(guò)GetEnv獲取JVMTI環(huán)境并向JVM預(yù)定VMInit事件的通知并設(shè)置VMInit事件的回調(diào)函數(shù),在回調(diào)函數(shù)中利用RegisterNatives將自定義的本地代理方法注冊(cè)到ClassLoader.defineclass1上;最后完成自定義的本地代理方法,在該方法中實(shí)現(xiàn)對(duì)字節(jié)碼的解密。解密后的字節(jié)碼存儲(chǔ)在JVM的內(nèi)存中,此時(shí)再調(diào)用java.dll中的_Java_java_lang_ClassLoader_define-Class1@32方法將解密后的字節(jié)碼轉(zhuǎn)換為Class對(duì)象并將這個(gè)對(duì)象作為Agent_OnLoad的返回值返回給JVM。

在運(yùn)行加密過(guò)的class文件時(shí),必須在JVM的運(yùn)行參數(shù)中通過(guò)-agentlib參數(shù)指定JVMTI客戶端。

4.2 基于Linux平臺(tái)的實(shí)現(xiàn)

在windows平臺(tái)的源代碼基礎(chǔ)上做如下修改即可實(shí)現(xiàn)JVMTI客戶端向Linux平臺(tái)的移植:

(1)由于在Windows平臺(tái)從動(dòng)態(tài)鏈接庫(kù)中調(diào)用函數(shù)需要LoadLibrary、GetProcAddress和FreeLibrary三個(gè)庫(kù)函數(shù),而g++編譯器不支持這三個(gè)庫(kù)函數(shù),所以需要將windows.h頭文件改為dlfcn.h頭文件,然后分別使用dlopen、dlsym和dlclose這三個(gè)庫(kù)函數(shù),具體實(shí)現(xiàn)和Windows平臺(tái)類似。

(2)利用g++編譯代碼時(shí),需要使用shared參數(shù),這樣將代碼編譯成動(dòng)態(tài)鏈接庫(kù),利用-o libXXX.so輸出代理庫(kù),其中輸出名稱的后綴為lib和.so,XXX為自定義名稱。

(3)在程序運(yùn)行前,必須使用 set命令設(shè)置L-D_LIBRARY_PATH變量為代理庫(kù)的路徑。

和Windows平臺(tái)一樣,在運(yùn)行加密過(guò)的class文件時(shí),必須在JVM的運(yùn)行參數(shù)中通過(guò)-agentlib參數(shù)指定JVMTI客戶端。

5 結(jié)束語(yǔ)

基于JVMTI的Java字節(jié)碼保護(hù)技術(shù)及其實(shí)現(xiàn)方案在保持Java程序跨平臺(tái)特性和不修改JVM的前提下達(dá)到了有效防止反編譯的目標(biāo)。當(dāng)然這種技術(shù)并非無(wú)懈可擊,采用極端的方式仍然可以對(duì)JVMTI客戶端程序進(jìn)行破解,破解的難度取決于JVMTI客戶端采用的加密算法的強(qiáng)度。但正如Alex Kalinovsky所說(shuō)[6]:成功的保護(hù)機(jī)制的關(guān)鍵是讓它復(fù)雜到95%的典型用戶很難破解,并迫使其余5%有經(jīng)驗(yàn)的破解者花費(fèi)大量的時(shí)間來(lái)破譯。換句話來(lái)說(shuō),目標(biāo)是讓購(gòu)買許可比花費(fèi)在破解保護(hù)上的成本顯得更加劃算。

該方案在JVMTI客戶端程序?qū)VM類加載器執(zhí)行效率的影響方面沒(méi)有給出詳盡的分析或數(shù)據(jù),但可以肯定的是這種影響是存在的,其影響程度主要取決于解密算法的時(shí)間復(fù)雜度。這個(gè)問(wèn)題值得相關(guān)工程技術(shù)人員進(jìn)一步研究和探討。

[1] 歐陽(yáng)辰.如何保護(hù)Java程序[EB/OL].2004-12-02.http://www.infosecurity.org.cn/article/websec/java/index.html.

[2] 陳剛.基于封裝包的Java源代碼安全保護(hù)[J].電子信息與對(duì)抗技術(shù),2006,21(3):45-48.

[3] 陳晗,趙軼群,繆亞波.Java字節(jié)碼的水印嵌入[J].微型電腦應(yīng)用,2004,20(20):56-58.

[4] Sun Microsystems.Java Native Interface Specification[EB/OL].http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/niTOC.html.2007-06-20.

[5] Sun Microsystems.JVM(TM)Tool Interface 1.1.102[EB/OL].2007-06-20.http://java.sun.com/javase/6/docs/platform/jvmti/jvmti.html.

[6] Alex Kalinovsky,著.透視 JAVA[M].劉凌,周哲海,譯.北京:清華大學(xué)出版社,2005.

猜你喜歡
程序方法
學(xué)習(xí)方法
試論我國(guó)未決羈押程序的立法完善
失能的信仰——走向衰亡的民事訴訟程序
“程序猿”的生活什么樣
英國(guó)與歐盟正式啟動(dòng)“離婚”程序程序
用對(duì)方法才能瘦
Coco薇(2016年2期)2016-03-22 02:42:52
創(chuàng)衛(wèi)暗訪程序有待改進(jìn)
四大方法 教你不再“坐以待病”!
Coco薇(2015年1期)2015-08-13 02:47:34
賺錢方法
捕魚
主站蜘蛛池模板: 直接黄91麻豆网站| 四虎在线高清无码| 久久美女精品| 中文字幕2区| 欧美区日韩区| 久久无码av一区二区三区| 国产在线98福利播放视频免费 | 久久天天躁狠狠躁夜夜躁| 中文字幕在线欧美| 亚洲福利视频一区二区| 国产亚洲高清视频| 国产亚洲男人的天堂在线观看| 尤物精品视频一区二区三区| 日韩欧美中文在线| www.亚洲天堂| 国产成人精品高清不卡在线| 夜夜爽免费视频| 久久亚洲国产最新网站| a色毛片免费视频| AⅤ色综合久久天堂AV色综合| m男亚洲一区中文字幕| 一级毛片在线播放| 囯产av无码片毛片一级| 国产欧美日韩综合一区在线播放| 中文字幕首页系列人妻| 韩日免费小视频| 中文字幕亚洲另类天堂| 久久99精品久久久大学生| 国产综合色在线视频播放线视| 国产亚洲欧美在线视频| 亚洲性视频网站| 69免费在线视频| 亚洲国产中文综合专区在| 69免费在线视频| 色婷婷综合激情视频免费看| 欧美啪啪精品| 九九热精品在线视频| 国产精品视频久| 成年免费在线观看| 欧美成人影院亚洲综合图| 国产香蕉一区二区在线网站| 无遮挡国产高潮视频免费观看| 国产97公开成人免费视频| 久久精品国产999大香线焦| 日本91视频| 日本欧美在线观看| 国产精品免费入口视频| AV不卡国产在线观看| 一边摸一边做爽的视频17国产| 亚洲人成在线精品| 在线亚洲天堂| 欧美色综合久久| 久久综合婷婷| 人妻无码中文字幕第一区| 精品国产成人a在线观看| 国产精品.com| 国产色婷婷视频在线观看| 欧美一区二区三区欧美日韩亚洲| 中文字幕亚洲无线码一区女同| 在线观看免费国产| 欧美国产日产一区二区| 日韩视频免费| 婷婷在线网站| 中文字幕乱妇无码AV在线| 亚洲综合二区| 欧美日本在线观看| 在线国产三级| 欧美福利在线观看| 免费国产无遮挡又黄又爽| 欧美综合一区二区三区| a国产精品| av一区二区三区高清久久| 2020最新国产精品视频| 成人在线综合| 国产色婷婷| 五月婷婷精品| 国产男人天堂| 97超爽成人免费视频在线播放| 最新国语自产精品视频在| 99中文字幕亚洲一区二区| 国内视频精品| 婷婷六月综合网|