1.使用程序对.class文件进行加密,之后使用jvm hook对加载的.class文件进行解密然后完成类加载的工作 2.注意事项 由于java解密代码调用非常的频繁 所以一定要注意申请的资源要及时释放 否则会导致内存泄漏以至程序崩溃 目前该程序只适用于java 1.6 java1.5实现未作测试 java1.7不能使用 由于底层实现有变java1.7的兼容性开发还未做 3.程序解释 1)加密程序 可采用对称加密如需要可以再修改成其它加密算法 并对加密的文件做上加密标记 2) 1>.Java agent程序 java虚拟机在运行是使用-agentpath或-agentlib参数加载该dll 如 java -agentpath:C:\temp\xxxagent.dll=C:\temp\key.dat HelloWorld 其中的HelloWorld.class为已经加密过的类 当然如果这个类未加密也可以正常运行 xxxagent.dll会识别哪些类加密了 2>.该dll向jvm注册了一些本地的方法最重要的一个是defineClass1 3>.注册之后在做了解密处理之后还要调用jvm本身的函数defineClass1(这个函数位于java.dll中) 4>.此程序设计时一定要注意性能 5>.与还可以利用类似的方法对jvm的性能做一个统计及优化等工作 3)xxxagent.dll开发的关键外在于取得相关的函数定义及签名等信息 取得函数名方法如下: 1>. 可以通过ClassLoader.java ClassLoader.c取得相关的方法 2>. 可以使用dumpbin.exe取得方法在java.dll中的导出名 dumpbin.exe /EXPORTS java.dll 3>. 通过javap -s -private ClassLoader取得相关类的签名信息 4>. 由于java语言及其实现是开源的所以可以取得相关的源代码 这样更易开发 伪代码如下: 1.注册虚拟机初始化结束事件 JVM_EVENT_VM_INIT JNIEXPORT jint JNICALL Agent_OnLoad( JavaVM *jvm, char *options, void *reserved ) { printf( "starting agent ......\n" ); error = gb_jvmti->SetEventNotificationMode(JVMTI_ENABLE,JVMTI_EVENT_VM_INIT, (jthread)NULL); return JNI_OK; } typedef jclass(JNICALL *lpDefineClass1_32) ( JNIEnv *env, jobject loader, jstring name, jbyteArray b, jint off, jint len, jobject pd, jstring source, jboolean bVerify ); //用于指向java.dll中的 _Java_java_lang_ClassLoader_defineClass1@36 //32位的函数指针 //64位的和这个不同 //可通过ClassLoader.java ClassLoader.c 及使用dumpbin.exe /EXPORTS java.dll查看即可得知参数及函数名 2. 响应虚拟机初始化结束事件 并注册要hook的函数 及取得要调用的函数指针 static void JNICALL jvmInitFinish( jvmtiEnv *jvmti_env, JNIEnv* env, jthread thr ) { printf( "jvm Init finish ......\n" ); int iLen = env->RegisterNatives( jcls, jni_methes1_6, iLen ); HMOUDLE hJavaDll = LoadLibrary( "java.dll" ); funcDefineClass1_32 = (lpDefineClass1_32)(GetProcAddress(hJavaDll, "_Java_java_lang_ClassLoader_defineClass1@36" )); funcDefineClass2_32 = (lpDefineClass2_32)(GetProcAddress(hJavaDll, "_Java_java_lang_ClassLoader_defineClass2@36" )); } 注意其中的函数指针要定义正确 可以ClassLoader中得到正常的定义 3. 要hook的函数 JNIEXPORT jclass JNICALL comdev_defineClass1_6( JNIEnv *env, jobject loader, jstring name, jbyteArray data, jint offset, jint length, jobject pd, jstring source, jboolean verify ) { if( !strncmp( (const char*)LABEL, (const char*)originByte, strlen((const char*)LABEL)) ) { //如果是已加密的类则执行解密操作 lPlainText = DES_DecryptByteArray( pCipher, pCharKey, LABEL, pPlainText, iCipherLen ); } if( pPlainText ) { cls = funcDefineClass1_32( env, loader, name, pByteArr, offset, lPlainText, pd, source, verify ); } else { //如果是非加密类则直接执行java.dll中的原函数 cls = funcDefineClass1_32( env, loader, name, data, offset, length, pd, source, verify ); } return cls; } fzq整理所得 欢迎转载
java字节码文件加密_Java字节码文件保护方法之字节码加密实现(方法及伪码)
最新推荐文章于 2024-04-08 16:48:28 发布