通過JVMTI和JNI對JAVA加密

cher7.com發表於2014-09-03

通用JAVA加密或者是混淆更貼切技術是將class、方法及包,以隨機命名方式進行混淆,雖然這種方式增加了閱讀難度,但還不足以將位元組碼檔案進行完整保護。本文介紹一種以JVMTI和JNI方式對位元組碼進行加密的辦法,並提供測試原始碼下載(請讀完)。

為了幫助 Java 開發人員診斷和跟蹤 Java 執行緒狀態的切換,Sun 公司在 Java 開發工具包(Java2 Software Development Kit, JDK)1.5.0 版本中引進了 Java 虛擬機器工具介面(Java Virtual Machine Toolkit Interface,JVMTI),用於替代在先前的 JDK 版本中作為試驗功能存在的 Java 虛擬機器剖析介面(Java Virtual Machine Profiling Interface,JVMPI)和 Java 虛擬機器除錯介面(Java Virtual Machine Debugging Interface,JVMDI)。通過 JVMTI 介面可以建立代理程式(Agent)以監視和控制 Java 應用程式,包括剖析、除錯、監控、分析執行緒等等,其架構模型如圖 1 所示。引用自:http://www.ibm.com/developerworks/cn/java/j-lo-jvmti/

圖 1. JVMTI 架構模型

函式講解:JVMTI中包含了很多函式和事件,這裡只列出我們加密需要用的幾個函式

一、Agent_OnLoad可以理解為和JVM進行互動的入口函式;

二、SetEventNotificationMode 和SetEventCallbacks函式,這兩個函式一個是用來設定通知JVM需要攔截的事件和設定回撥方法的;

三、VmInit ,虛擬機器初始化事件,該事件發生時則說明虛擬機器已經初始化完成,即已經可以使用JNI環境了。

四、 Agent_UnLoad 代理解除安裝函式,可以將動態物件在此釋放.。

加密原理即對位元組碼檔案通過可逆演算法進行加密,比如3DES,然後重新打成JAR包或直接使用。解密原理:當JVM載入代理時虛擬機器呼叫Agent_OnLoad函式,在Agent_OnLoad函式中我們對VmInit事件進行註冊,在VmInit回撥方法我們可以獲取JNI環境,通過JNI的RegisterNatives方法將ClassLoader的defineClass1重寫以實現解密,通過以上幾個函式和事件來完成的,通過編寫動態連結庫的方式實現以上功能,再由JAVA虛擬機器的 –agentlib 或-agentpath引數呼叫實現的動態連結庫。

這裡以VS2010為開發環境,簡單介紹一下開發流程:

一、新建VC++  DLL專案 ,將JVM提供的標頭檔案引入專案中

 

二、作為DEMO,簡單起見,直接新建Main.cpp,在Cpp檔案中加入jvmti.h jni.h jni_md.h的引

三、實現代理入口函式Agent_OnLoad 

四、實現虛擬機器初始化函式VmInit 

五、通過JNI的RegisterNatives方法重寫ClassLoader的defineClass1函式

六、實現Agent_UnLoad方法釋放資源。

通過以上步驟可實現基於JVMTI的代理動態連線庫。

下面講解一下使用方法:

一、Eclipse中使用,在VM設定中加入-agentlib 或 –agentpath引數,設定動態連線庫的位置

二、Tomcat中使用,只需在Catalina.sh或Catalina.bat中的JAVA_OPTS引數中加入-agentlib或-agentpath引數,比如-agentlib:Jvmti

注:Linux使用時,需將動態連結庫所在目錄設定到LD_LIBRARY_PATH中或直接將動態連結庫放到Linux的/usr/lib下 且命令為xxxlib.so,使用-agentlib:xxx即可。

通過本文方法可對位元組碼進行很好的保護。DEMO下載地址:點我下載

相關文章