欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]java外壳保护原理

[原创]java外壳保护原理

好长时间没有碰过java加解密了,今天拿出来翻翻
        先随便写一个可以运行的Java文件 编译成xxx.class文件,然后在文件尾部添加一段标志数据。现在的xxx.class文件再用Java xxx已经报错了,就理解成xxx.class文件已经被我们加密了吧
        如果想正确运行这个文件该怎么办呢?现在就提到了正题,使用JVMTI技术。
        这个JVMTI是java虚拟机调试接口,具体的大家网上搜索就行了。
        下面举个栗子:
        加密代码:


#include <stdio.h>  

#include <windows.h>  

BYTE EncryptFlag[10] = { 0x73, 0x75, 0x70, 0x65, 0x72, 0x5F, 0x6D, 0x69, 0x6D, 0x69 };  //随意加的加密标记

int main()  

{  

    HANDLE hFile = CreateFile("Jvmti.class", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING,NULL,NULL);  

    if (hFile == NULL)  

    {  

        CloseHandle(hFile);  

        return 0;  

    }  

    SetFilePointer(hFile, 0, 0, FILE_END);  

    DWORD dwnum = 0;  

    BOOL is_Write = WriteFile(hFile, EncryptFlag, 10, &dwnum, NULL);  

    if (!is_Write)  

    {  

        printf("写入失败!\n");  

        CloseHandle(hFile);  

        return 0;  

    }  

    printf("写入成功!\n");  

    getchar();  

    return 0;  

}  


解密代码:
这个解密代码写成动态库,然后随java进程启动的时候使用
需要将java src的include源码加入到附加包含目录中
jvmti  DLL导出接口为:
启动加载接口:Agent_OnLoad。
退出卸载接口:Agent_OnUnload。

// JvmtiTest.cpp : 定义 DLL 应用程序的导出函数。  

//  

#include "stdafx.h"  

int num = 0;  

//加密文件标志,用以识别我们加过密的CLASS文件  

BYTE EncryptFlag[10] = { 0x73, 0x75, 0x70, 0x65, 0x72, 0x5F, 0x6D, 0x69, 0x6D, 0x69 };  

JNIEXPORT void JNICALL MyCallBackFunc(jvmtiEnv *jvmti_env,  

    JNIEnv* jni_env,  

    jclass class_being_redefined,  

    jobject loader,  

    const char* name,  

    jobject protection_domain,  

    jint class_data_len,  

    const unsigned char* class_data,  

    jint* new_class_data_len,  

    unsigned char** new_class_data);  

JNIEXPORT jint JNICALL  

Agent_OnLoad(JavaVM *vm, char *options, void *reserved)  

{  

    cout << "Agent_OnLoad start!" << endl;  

    //获取jvmti  

    jvmtiEnv * jvmti;  

    jint result = vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_0);  

    if (result != JNI_OK)  

    {  

        return result;  

    }  

  /**************最重要的代码************************/

//使用jvmti给classload添加HOOK

    jvmtiCapabilities capabilities;  

    // Clear the capabilities structure and set the ones you need.  

    (void)memset(&capabilities, 0, sizeof(capabilities));  

    capabilities.can_generate_all_class_hook_events = 1;  

    result = jvmti->AddCapabilities(&capabilities);  

    if (result != JVMTI_ERROR_NONE) {  

        printf("ERROR: Unable to AddCapabilities JVMTI!\n");  

        return result;  

    }  

    //回调  

    jvmtiEventCallbacks callbackfunc;  

    memset(&callbackfunc, 0, sizeof(callbackfunc));  

    callbackfunc.ClassFileLoadHook = MyCallBackFunc;  

    result = jvmti->SetEventCallbacks(&callbackfunc,sizeof(callbackfunc));  

    result = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);  

    if (result != JVMTI_ERROR_NONE)  

    {  

//      printf("ERROR: Unable to SetEventNotificationMode JVMTI!\n");  

        return result;  

    }  

   /**************最重要的代码************************/

    return JNI_OK;  

}  

JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm)  

{  

    printf("Agent_OnUnload!");  

    printf("卸载\n");  

}  

//解密回调函数  

JNIEXPORT void JNICALL MyCallBackFunc(jvmtiEnv *jvmti_env,  

                    JNIEnv* jni_env,  

                    jclass class_being_redefined,  

                    jobject loader,  

                    const char* name,  

                    jobject protection_domain,  

                    jint class_data_len,  

                    const unsigned char* class_data,  

                    jint* new_class_data_len,  

                    unsigned char** new_class_data)  

{  

    unsigned char * buf;  

    //解密加密类  

    if (memcmp(class_data + 553 - 10, EncryptFlag, 10) == 0)  

    {  

        printf("累加了%d次\n", num);  

        //是加密过的  这里的553是我xxx.class未加密之前文件的大小

        jvmti_env->Allocate(553 - 10, &buf);  

        memcpy(buf, class_data, (553 - 10));  

        *new_class_data = buf;  

        *new_class_data_len = 543;  

        printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");  

    }  

    else  

    {  

        num++;  

    }  

}  


所有的代码都写完了,怎么使用呢
使用方法:java -agentlib:jiemi.dll xxx
还有扩展思路,如果不想每次使用一个dll来解密,可以将重要代码添加到java源码中,加密算法自选。
有一个文章写的很好:http://www.ibm.com/developerworks/cn/java/j-lo-jvmti/
不会排版,大家凑合着看吧

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功