使用jvmti实现class加密,防止反编译
来源:互联网 发布:河北大学网络拓扑图 编辑:程序博客网 时间:2024/05/09 07:46
如果想要保护自己的java代码不被别人反编译,则可以使用下面的jvmti对Class加密,然后在类加载器加载时再进行加密,逃避反编译。
jvmti是java自带的强大工具,我们可以通过jvmti做一些操作(例如:hook class加载,jvm启动前做什么事情,或者jvm初始化时做事情等等)
步骤如下:
1.对class进行加密
2.创建本地方法DLL,实现解密代码
(1)添加jvmti头文件
(2)监听jvm初始化完毕事件,并执行自己的方法
(3)在class类加载的时候实现解密
3.添加解密组件,其实也就是添加启动命令参数
1.对class进行加密,这里只是演示最简单的加密,将java魔数修改,就可以做到防止编译了,当然如果老手一看就知道怎么解密了,具体的加密可以再自己搞。
正常class文件(开头4字节为0xbebafeca):
加密后的class文件(开头文件为0xbfbafeca):
2.创建本地方法DLL,实现解密代码
(1)添加jvmti头文件,找到自己java的安装路径,然后引入
(2)监听jvm初始化完毕事件,并执行自己的方法,以下是具体代码
#include <jvmti.h>#include <string>#include <cstring>#include <iostream>#include <list>#include <map>#include <set>#include <stdlib.h>#include <jni_md.h>#include <string>typedef struct tagHeader{ int nSeqNum;//分割二进制 用来判断是否为0xbfbafeca int nHash;//这个应该是对象的hash值 char strPass[16];} Header; //这个是对象头std::string& replace_all(std::string& str, const std::string& old_value, const std::string& new_value){ while (true) { std::string::size_type pos(0); if ((pos = str.find(old_value)) != std::string::npos) str.replace(pos, old_value.length(), new_value); else break; } return str;}char * jstringTostring(JNIEnv* env, jstring jstr){ char* rtn = NULL; jclass clsstring = env->FindClass("java/lang/String"); jstring strencode = env->NewStringUTF("utf-8"); jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr = (jbyteArray)env->CallObjectMethod(jstr, mid, strencode); jsize alen = env->GetArrayLength(barr); jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE); if (alen > 0) { rtn = (char*)malloc(alen + 1); memcpy(rtn, ba, alen); rtn[alen] = 0; } env->ReleaseByteArrayElements(barr, ba, 0); return rtn;}//(Ljava/lang/String;[BIILjava/security/ProtectionDomain;Ljava/lang/String;)Ljava/lang/Class;//(String,byte[],int,int,ProtectionDomainm,string)class//返回值为class类型jclass MyDefine1Class(JNIEnv * env, jobject obj, jstring name, jbyteArray b, jint off, jint len, jobject protection_doamin, jstring source){ jbyte * buff = env->GetByteArrayElements(b, NULL); char* buff1 = (char*)env->GetByteArrayElements(b, NULL); Header header; jclass descClazz; memcpy(&header, buff, sizeof(header));//将对象头部单独放到header中 char * className = jstringTostring(env, name); // std::string realName(className); replace_all(realName, ".", "/"); //如果发现加载的class以0xbfbafeca开头的就认为这个class已经被加密了,然后进行解密 if (header.nSeqNum == 0xbfbafeca) { //解密,将0xbfbafeca变为0xbebafeca header.nSeqNum = header.nSeqNum & 0xFEFFFFFF; memcpy(buff, &header.nSeqNum, sizeof(header.nSeqNum)); } //class被解密后或者没有被加密的class,直接就正常可以加载class descClazz = env->DefineClass(realName.c_str(), obj, buff, len); free(className); env->ReleaseByteArrayElements(b, buff, 0); return descClazz;}//JVM初始化完毕后要进行操作的函数void JNICALL cbVminit(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread){ printf("cd VMinit\n"); jclass clazz = jni_env->FindClass("java/lang/ClassLoader"); if (clazz != NULL) { //通过JNI的RegisterNatives方法将ClassLoader的defineClass1重写以实现解密 //其实就是自己写一个defineClass方法,加到ClassLoader类中,这里是class格式的一些规则,具体可以看一些class格式 JNINativeMethod methods[] = { { "defineClass1", "(Ljava/lang/String;[BIILjava/security/ProtectionDomain;Ljava/lang/String;)Ljava/lang/Class;", (void*)MyDefine1Class }, }; jni_env->RegisterNatives(clazz, methods, 1); }}JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm) { // nothing to do}//代理加载时执行JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { // nothing to do jvmtiEnv *jvmti = NULL; jvmtiError error; // 获取JVM环境 jint result = jvm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1); if (result != JNI_OK) { printf("ERROR: Unable to access JVMTI!\n"); } jvmtiCapabilities capabilities;//方便判断SetEventNotificationMode是否要开启 (void)memset(&capabilities, 0, sizeof(capabilities)); //capabilities.can_generate_all_class_hook_events = -1; capabilities.can_tag_objects = 1; capabilities.can_generate_object_free_events = 1; capabilities.can_get_source_file_name = 1; capabilities.can_get_line_numbers = 1; capabilities.can_generate_vm_object_alloc_events = 1; error = jvmti->AddCapabilities(&capabilities); if (error != JVMTI_ERROR_NONE) { printf("ERROR: Unable to AddCapabilities JVMTI!\n"); return error; } //定义要监听的模块,这里定义了监听JVM初始化完毕模块 jvmtiEventCallbacks callbacks; (void)memset(&callbacks, 0, sizeof(callbacks)); callbacks.VMInit = &cbVminit;//赋值JVM初始化完毕以后进行操作函数 error = jvmti->SetEventCallbacks(&callbacks, (jint)sizeof(callbacks)); if (error != JVMTI_ERROR_NONE) { printf("ERROR: Unable to SetEventCallbacks JVMTI!\n"); return error; } //定义了监听模块以后,这里还需要开启你要监听的模块,是必须的 error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL); if (error != JVMTI_ERROR_NONE) { printf("ERROR: Unable to SetEventNotificationMode JVMTI!\n"); return error; } return JNI_OK;}
3.添加解密组件,其实也就是添加启动命令参数
将生成的DLL放到lib目录,然后添加启动命令参数,然后运行就大功告成啦!
阅读全文
0 0
- 使用jvmti实现class加密,防止反编译
- 防止Class类反编译的方法,对Class进行加密
- 基于jvmti和c++实现的class加密解密(一)
- 基于jvmti与C++实现Class的加密解密 (二)
- JAVA .class 文件防止反编译。
- JAVA .class 文件防止反编译
- JAVA .class 文件防止反编译。
- Java加密Jar包和Class文件防止反编译的方法
- Android防止反编译实现
- 防止.class被反编译 的方法
- JAVA防止反编译(JAVA加密锁)
- 针对java加密防止反编译的办法
- unity 加密、防止反编译、mono编译
- JVMTI使用方案-C++
- Android Studio 基于NDK加密,防止反编译获取加密key
- Java代码加密与反编译(二):用加密算法DES修改classLoader实现对.class文件加密
- Java代码加密与反编译(二):用加密算法DES修改classLoader实现对.class文件加密
- jvmti
- 数据机房建设常用材料有哪些?
- PDU是如何帮助机房安然度夏?如何选择PDU电源配套机柜?
- 数据中心新认证出现,UPTIME面临挑战
- 将Nodejs移植到Arm
- Java互联网架构-类的加载机制
- 使用jvmti实现class加密,防止反编译
- 基于Docker的Python Web Service
- linux下各种格式的压缩包的压缩、解压方法
- request.getContextPath
- 高级加密标准AES的加密模式
- 多重背包【简单到死啊】
- 选择计算机建议
- button绑定多个click的bug处理
- ios11适配 以及会有的坑