jar包加密_maven 加密jar包 - CSDN
精华内容
参与话题
  • java对一个jar包加密

    千次阅读 2019-05-21 15:02:50
    软件无需任何代码开发,即可轻松加密Java应用程序、Jar包、War包,防止反编译逆向工程,真正实现 Java代码加密加密效果对比 加密加密加密方案 Virbox Protector 测试版工具:立即下载 使用Virbox...

    加密效果概述

    深思对 java 的源码保护方式是通过 Virbox Protector 与DS Protector 工具进行保护。软件无需任何代码开发,即可轻松加密Java应用程序、Jar包、War包,防止反编译逆向工程,真正实现 Java代码加密。

    加密效果对比

    加密前

    加密后

     

    加密方案

    Virbox Protector 测试版工具: https://shell.virbox.com/javaprotector.html

    使用Virbox Protector Standalone对 Jar 包加密有两种方式

    加密方式一

    加密流程

    1.准备工具

    将待加密的jar包放到一个文件夹中。

    2.添加目录

    将包含jar包的目录拖入工具中,设置加密选项中的密码

    加密选项-密码设置

    • 密码如果不设置,会随机默认密码。
    • 建议设置一个密码,并牢记,后续更新jar包时,重新加密时填写此密码,则无需更换配置sjt库。

    3.点击保护

    点击【保护选中项目】,保护成功后会重新生成一个目录:ssp.java程序 ,里面包含加密后的jar包和 sjt 文件。

     

    4.运行加密后jar

    两种方式运行加密后的jar包。1.将sjt库文件添加到系统环境变量;2.运行jar包时指定sjt文件目录。

    Windows系统

    添加到系统环境变量

    1)可以将 sjt 文件存放在一个固定的目录下,将sjt_windows_x64.dll或sjt_windows_x86.dll添加到系统环境变量中。

    设置环境变量流程:

    我的电脑-属性-高级系统设置-环境变量-系统变量,新建变量名JAVA_TOOL_OPTIONS,变量值

    -agentpath:C:\Users\test\Desktop\sjt\sjt_windows_x64.dll

    2)配置好环境后,直接运行jar包或直接调用jar包即可。

    备注:若Java版本是64位的,指定 sjt_windows_x64.dll ,若Java版本是32 位的,使用 sjt_windows_x86.dll。

    Linux系统

    添加到系统环境变量

    1)将JAVA_TOOL_OPTIONS=-agentpath:/home/sense/Desktop/sjt_so/sjt_linux_x86.so 添加到 /etc/profile环境变量

    JAVA_TOOL_OPTIONS=-agentpath:/home/sense/Desktop/sjt_so/sjt_linux_x86.so

    2)输入命令source /etc/profile使修改的文件生效。

    3)配置好环境后,直接运行jar包或直接调用jar包即可。

    注意

    若配置系统环境变量后,即使指定sjt库的位置,java运行也会先走系统环境变量里的配置。

    开始试用Virbox Protector Java !

    下载安装试用版后,点击【申请试用】注册VirboxProtector账号,登录即可开始加密。注意:试用版加密后的程序只能运行7天,请勿用于正式发布.

    试用地址:https://shell.virbox.com/javaprotector.html

    加密方式二-【DS工具加密】

    1.部署项目并启动服务

    项目放在 webapps 目录下,先启动 tomcat 服务确认能正常启动,启动过后该 War 包会自动解压出一个同名的文件夹

     

     

    启动 tomcat 服务

     

     

    找到依赖的解释器
    服务启动成功后,进入任务管理器-服务-找到目前运行项目所依赖的 jdk , 进入目录找到对应程序进行加密。 如下图

     

     

    2.对java.exe加密

    首先对安装环境 jdk 路径下的 java.exe 进行加密,将 java.exe 拖入到加壳工具Virbox Protector Standalone中。

     

    在加密选项页面将插件的ds按钮打开。

     

    点击“保护选中项目”,加壳后会额外生成图示两个文件。
    java.exe.ssp 是配置文件,在后面对 .class/.jar加密时会用到;java.ssp.exe 是加壳后的 java.exe 文件,将 java.exe 剪切到其他文件夹备份,java.ssp.exe 名字改为java.exe 即可。

     

     

    3.打开“DSProtector.exe”对 .class/.jar进行保护。

    添加上一步加密 java.exe 生成的 java.exe.ssp 文件。

     

    添加要加密的.class/.jar文件。

     

    点击“保护它”,加密成功。

    展开全文
  • 加密解密jar包

    2018-01-27 18:30:02
    包含对称加密、非对称加密所需要用到的核心jar包,一般jar包jdk里面有,这里列举需要自己下载的 参见博文: http://blog.csdn.net/qq_35255384/article/details/79179378
  • java jar包加密保护解决方案

    万次阅读 2017-03-03 19:28:20
    为什么需要保护? 我用java写了一个程序如下: 12345678910111213141516171819202122232425 ...// App.javapublic class App{ static public void main( String args[] ) throws Exception {


    为什么需要保护?

    我用java写了一个程序如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    package com.monkey.demo;
    // App.java
    public class App
    {
    static public void main( String args[] ) throws Exception {
    System.out.println( "This is your application." );
    System.out.print( "Args: " );
    for (int a=0; a<args.length; ++a)
    System.out.print( args[a]+" " );
    System.out.println( "" );
    new App().new AppChild().print();
    new Foo();
    new Bar();
    }
    public class AppChild{
    public void print(){
    System.out.println("haha ....");
    }
    }
    }

    然后编译生成.class文件后,我发布出去了,别人拿到我的.class文件拖到JD-GUI里面看到的是这样:

    image

    玩毛线,看源代码一样,当然你也可以使用ProGuard混淆,不过别人有点耐心还是能分析出来的。另外你还可以修改class文件里面的某些字段,这些字段对运行没有影响,但是能导致别人无法反编译。这里我们暂且不讨论这种方式,分别讨论下使用ClassLoaderjvmti对class文件加密解密的方案。

    ClassLoader

    Java运行时装入字节码的机制隐含地意味着可以对字节码进行修改。JVM每次装入类文件时都需要一个称为ClassLoader的对象,这个对象负责把新的类装入正在运行的JVM。JVM给ClassLoader一个包含了待装入类(比如java.lang.Object)名字的字符串,然后由ClassLoader负责找到类文件,装入原始数据,并把它转换成一个Class对象。

    所以我们可以通过自定义一个ClassLoader,然后先对class进行解密之后,再加载到JVM。大致流程如下:

    1
    2
    3
    4
    5
    6
    7
    // 首先创建一个ClassLoader对象
    ClassLoader myClassLoader = new myClassLoader();
    // 利用定制ClassLoader对象装入类文件
    // 并把它转换成Class对象
    Class myClass = myClassLoader.loadClass( "mypackage.MyClass" );
    // 最后,创建该类的一个实例
    Object newInstance = myClass.newInstance();

    loadClass

    在创建自定义的ClassLoader时,只需覆盖其中的一个,即loadClass,获取加密后的文件数据解密加载。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    public Class loadClass( String name, boolean resolve )
    throws ClassNotFoundException {
    try {
    // 我们要创建的Class对象
    Class clasz = null;
    // 如果类已经在系统缓冲之中,不必再次装入它
    clasz = findLoadedClass( name );
    if (clasz != null)
    return clasz;
    // 下面是定制部分
    byte classData[] = /* 解密加密后的字节数据 */;
    if (classData != null) {
    // 成功读取字节码数据,现在把它转换成一个Class对象
    clasz = defineClass( name, classData, 0, classData.length );
    }
    // 如果上面没有成功,尝试用默认的ClassLoader装入它
    if (clasz == null)
    clasz = findSystemClass( name );
    //如有必要,则装入相关的类
    if (resolve && clasz != null)
    resolveClass( clasz );
    // 把类返回给调用者
    return clasz;
    } catch( IOException ie ) {
    throw new ClassNotFoundException( ie.toString() );
    } catch( GeneralSecurityException gse ) {
    throw new ClassNotFoundException( gse.toString() );
    }
    }

    上面是一个简单的loadClass实现,其中涉及到如下几个方法:

    • findLoadedClass: 检查当前要加载的类是否已经加载。
    • defineClass: 获得原始类文件字节码数据后,调用defineClass转换成一个Class对象。
    • findSystemClass: 提供默认ClassLoader支持。
    • resolveClass: 当JVM想要装入的不仅包括指定的类,而且还包括该类引用的所有其他类时,它会把loadClass的resolve参数设置成true。这时,必须在返回刚刚装入的Class对象给调用者之前调用resolveClass。

    加密、解密

    直接使用java自带加密算法,比如DES。

    生成密钥

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //DES算法要求有一个可信任的随机数源
    SecureRandom sr = new SecureRandom();
    //为选择的DES算法生成一个KeyGenerator对象
    KeyGenerator kg = KeyGenerator.getInstance( "DES" );
    kg.init( sr );
    // 生成密匙
    SecretKey key = kg.generateKey();
    // 获取密匙数据
    byte rawKeyData[] = key.getEncoded();

    加密数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // DES算法要求有一个可信任的随机数源
    SecureRandom sr = new SecureRandom();
    byte rawKeyData[] = /* 用某种方法获得密匙数据 */;
    // 从原始密匙数据创建DESKeySpec对象
    DESKeySpec dks = new DESKeySpec( rawKeyData );
    // 创建一个密匙工厂,然后用它把DESKeySpec转换成一个SecretKey对象
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" );
    SecretKey key = keyFactory.generateSecret( dks );
    // Cipher对象实际完成加密操作
    Cipher cipher = Cipher.getInstance( "DES" );
    // 用密匙初始化Cipher对象
    cipher.init( Cipher.ENCRYPT_MODE, key, sr );
    // 现在,获取数据并加密
    byte data[] = /* 用某种方法获取数据 */
    // 正式执行加密操作
    byte encryptedData[] = cipher.doFinal( data );
    // 进一步处理加密后的数据
    doSomething( encryptedData );

    解密数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // DES算法要求有一个可信任的随机数源
    SecureRandom sr = new SecureRandom();
    byte rawKeyData[] = /* 用某种方法获取原始密匙数据 */;
    // 从原始密匙数据创建一个DESKeySpec对象
    DESKeySpec dks = new DESKeySpec( rawKeyData );
    // 创建一个密匙工厂,然后用它把DESKeySpec对象转换成
    // 一个SecretKey对象
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" );
    SecretKey key = keyFactory.generateSecret( dks );
    // Cipher对象实际完成解密操作
    Cipher cipher = Cipher.getInstance( "DES" );
    // 用密匙初始化Cipher对象
    cipher.init( Cipher.DECRYPT_MODE, key, sr );
    // 现在,获取数据并解密
    byte encryptedData[] = /* 获得经过加密的数据 */
    // 正式执行解密操作
    byte decryptedData[] = cipher.doFinal( encryptedData );
    // 进一步处理解密后的数据
    doSomething( decryptedData );

    实际案例

    这里写了一个简单的例子,代码在github

    首先生成密钥:

    1
    2
    3
    javac FileUtil.java
    javac GenerateKey.java
    java GenerateKey key.data

    然后加密class:

    1
    2
    javac EncryptClasses.java
    java EncryptClasses key.data App.class Foo.class Bar.class

    运行加密后的应用:

    1
    2
    javac MyClassLoader.java -Xlint:unchecked
    java MyClassLoader key.data App

    总的来说ClassLoader在类非常多的情况还是比较麻烦,而且这样一来自定义的ClassLoader本身就成为了突破口。下面介绍另外一种加密保护的方案。

    jvmti

    jvmti(JVMTM Tool Interface)是JDK提供的一套用于开发JVM监控,问题定位与性能调优工具的通用变成接口。通过JVMTI,我们可以开发各式各样的JVMTI Agent。这个Agent的表现形式是一个以c/c++语言编写的动态共享库。

    JVMTI Agent原理: java启动或运行时,动态加载一个外部基于JVM TI编写的dynamic module到Java进程内,然后触发JVM源生线程Attach Listener来执行这个dynamic module的回调函数。在函数体内,你可以获取各种各样的VM级信息,注册感兴趣的VM事件,甚至控制VM的行为。

    这里我们只需要监控class的加载信息,而jvmti也提供了这样的接口,通过下面的方式我们就能监控到class的加载:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    JNIEXPORT jint JNICALL
    Agent_OnLoad(
    JavaVM *vm,
    char *options,
    void *reserved
    )
    {
    ......
    //设置事件回调
    jvmtiEventCallbacks callbacks;
    (void)memset(&callbacks,0, sizeof(callbacks));
    callbacks.ClassFileLoadHook = &MyClassFileLoadHook;
    error = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
    ......
    }
    void JNICALL
    MyClassFileLoadHook(
    jvmtiEnv *jvmti_env,
    JNIEnv* jni_env,
    jclass class_being_redefined,
    jobject loader,
    const char* name, //class名字
    jobject protection_domain,
    jint class_data_len, //class文件数据长度
    const unsigned char* class_data, //class文件数据
    jint* new_class_data_len, //新的class文件数据长度
    unsigned char** new_class_data //新的class文件数据
    )
    {
    ......
    }

    通过这样的方式就能监控到class的加载然后再对其进行解密。

    加密、解密

    加密class文件

    这里简单的通过遍历class文件,然后对每个字节进行一个异或处理,具体的加密方法可以自己扩展:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    extern"C" JNIEXPORT jbyteArray JNICALL
    Java_Encrypt_encrypt(
    JNIEnv * _env,
    jobject _obj,
    jbyteArray _buf
    )
    {
    jsize len =_env->GetArrayLength(_buf);
    unsigned char* dst = (unsigned char*)_env->GetByteArrayElements(_buf, 0);
    for (int i = 0; i < len; ++i)
    {
    dst[i] = dst[i] ^ 0x07;
    }
    _env->SetByteArrayRegion(_buf, 0, len, (jbyte *)dst);
    return _buf;
    }

    解密class文件

    在运行jar文件的时候,加载我们的jvmti agent动态库进行动态解密:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    void JNICALL
    MyClassFileLoadHook(
    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
    )
    {
    *new_class_data_len = class_data_len;
    jvmti_env->Allocate(class_data_len, new_class_data);
    unsigned char* my_data = *new_class_data;
    if(name&&strncmp(name,"com/monkey/",11)==0){
    for (int i = 0; i < class_data_len; ++i)
    {
    my_data[i] = class_data[i] ^ 0x07;
    }
    }else{
    for (int i = 0; i < class_data_len; ++i)
    {
    my_data[i] = class_data[i];
    }
    }
    }

    实际案例

    这里写了一个简单的例子,代码在github

    首先加密jar包:

    1
    2
    javac Encrypt.java
    java -Djava.library.path=. -cp . Encrypt -src jardemo.jar

    image

    然后会得到一个jardemo_encrypt.jar文件,如果现在直接去运行该文件的话肯定是会出错的,所以要做解密。

    先编译生成一个解密的动态库libdecrypt.dylib。然后运行:

    1
    java -jar -agentlib:decrypt jardemo_encrypt.jar

    image

    总结

    总的来说,使用jvmti提供的监控api,方便了我们直接对class的操作,所以第二个方案更好一些,当然其中具体使用怎么样的加密,以及如何去保证加密不被破解就需要各位发挥自己的空间了。

    原文地址:http://www.alonemonkey.com/2016/05/25/encrypt-jar-class/

    参考:http://blog.csdn.net/yczz/article/details/39034223

    https://www.ibm.com/developerworks/cn/java/l-secureclass/


    展开全文
  • jar包加密保护解决方案[转发]

    千次阅读 2019-07-02 17:06:13
    为什么需要保护? 我用java写了一个程序如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package com.monkey.demo;... static public void main( Stri...

    为什么需要保护?

    我用java写了一个程序如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    package com.monkey.demo;
    
    // App.java
    
    public class App
    {
      static public void main( String args[] ) throws Exception {
        System.out.println( "This is your application." );
        System.out.print( "Args: " );
        for (int a=0; a<args.length; ++a)
          System.out.print( args[a]+" " );
        System.out.println( "" );
        
        new App().new AppChild().print();
        
        new Foo();
        new Bar();
      }
      
      public class AppChild{
    	  public void print(){
    		  System.out.println("haha ....");
    	  }
      }
    }
    

    然后编译生成.class文件后,我发布出去了,别人拿到我的.class文件拖到JD-GUI里面看到的是这样:

    image

    玩毛线,看源代码一样,当然你也可以使用ProGuard混淆,不过别人有点耐心还是能分析出来的。另外你还可以修改class文件里面的某些字段,这些字段对运行没有影响,但是能导致别人无法反编译。这里我们暂且不讨论这种方式,分别讨论下使用ClassLoaderjvmti对class文件加密解密的方案。

    ClassLoader

    Java运行时装入字节码的机制隐含地意味着可以对字节码进行修改。JVM每次装入类文件时都需要一个称为ClassLoader的对象,这个对象负责把新的类装入正在运行的JVM。JVM给ClassLoader一个包含了待装入类(比如java.lang.Object)名字的字符串,然后由ClassLoader负责找到类文件,装入原始数据,并把它转换成一个Class对象。

    所以我们可以通过自定义一个ClassLoader,然后先对class进行解密之后,再加载到JVM。大致流程如下:

    1
    2
    3
    4
    5
    6
    7
    
    // 首先创建一个ClassLoader对象
    ClassLoader myClassLoader = new myClassLoader();
    // 利用定制ClassLoader对象装入类文件
    // 并把它转换成Class对象
    Class myClass = myClassLoader.loadClass( "mypackage.MyClass" );
    // 最后,创建该类的一个实例
    Object newInstance = myClass.newInstance();
    

    loadClass

    在创建自定义的ClassLoader时,只需覆盖其中的一个,即loadClass,获取加密后的文件数据解密加载。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    
    public Class loadClass( String name, boolean resolve )
          throws ClassNotFoundException {
    	try {
    	  // 我们要创建的Class对象
    	   Class clasz = null;
    	  // 如果类已经在系统缓冲之中,不必再次装入它
    	  clasz = findLoadedClass( name );
    	  if (clasz != null)
    	    return clasz;
    	  // 下面是定制部分
    	  byte classData[] = /* 解密加密后的字节数据 */;
    	  if (classData != null) {
    	    // 成功读取字节码数据,现在把它转换成一个Class对象
    	    clasz = defineClass( name, classData, 0, classData.length );
    	  }
    	  // 如果上面没有成功,尝试用默认的ClassLoader装入它
    	  if (clasz == null)
    	    clasz = findSystemClass( name );
    	  //如有必要,则装入相关的类
    	  if (resolve && clasz != null)
    	    resolveClass( clasz );
    	  // 把类返回给调用者
    	  return clasz;
    	} catch( IOException ie ) {
    	  throw new ClassNotFoundException( ie.toString() );
    	} catch( GeneralSecurityException gse ) {
    	  throw new ClassNotFoundException( gse.toString() );
    	}
    }
    

    上面是一个简单的loadClass实现,其中涉及到如下几个方法:

    • findLoadedClass: 检查当前要加载的类是否已经加载。
    • defineClass: 获得原始类文件字节码数据后,调用defineClass转换成一个Class对象。
    • findSystemClass: 提供默认ClassLoader支持。
    • resolveClass: 当JVM想要装入的不仅包括指定的类,而且还包括该类引用的所有其他类时,它会把loadClass的resolve参数设置成true。这时,必须在返回刚刚装入的Class对象给调用者之前调用resolveClass。

    加密、解密

    直接使用java自带加密算法,比如DES。

    生成密钥

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    //DES算法要求有一个可信任的随机数源
    SecureRandom sr = new SecureRandom();
    //为选择的DES算法生成一个KeyGenerator对象
    KeyGenerator kg = KeyGenerator.getInstance( "DES" );
    kg.init( sr );
    // 生成密匙
    SecretKey key = kg.generateKey();
    // 获取密匙数据
    byte rawKeyData[] = key.getEncoded();
    

    加密数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    // DES算法要求有一个可信任的随机数源
    SecureRandom sr = new SecureRandom();
    byte rawKeyData[] = /* 用某种方法获得密匙数据 */;
    // 从原始密匙数据创建DESKeySpec对象
    DESKeySpec dks = new DESKeySpec( rawKeyData );
    // 创建一个密匙工厂,然后用它把DESKeySpec转换成一个SecretKey对象
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" );
    SecretKey key = keyFactory.generateSecret( dks );
    // Cipher对象实际完成加密操作
    Cipher cipher = Cipher.getInstance( "DES" );
    // 用密匙初始化Cipher对象
    cipher.init( Cipher.ENCRYPT_MODE, key, sr );
    // 现在,获取数据并加密
    byte data[] = /* 用某种方法获取数据 */
    // 正式执行加密操作
    byte encryptedData[] = cipher.doFinal( data );
    // 进一步处理加密后的数据
    doSomething( encryptedData );
    

    解密数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    // DES算法要求有一个可信任的随机数源
    SecureRandom sr = new SecureRandom();
    byte rawKeyData[] = /* 用某种方法获取原始密匙数据 */;
    // 从原始密匙数据创建一个DESKeySpec对象
    DESKeySpec dks = new DESKeySpec( rawKeyData );
    // 创建一个密匙工厂,然后用它把DESKeySpec对象转换成
    // 一个SecretKey对象
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" );
    SecretKey key = keyFactory.generateSecret( dks );
    // Cipher对象实际完成解密操作
    Cipher cipher = Cipher.getInstance( "DES" );
    // 用密匙初始化Cipher对象
    cipher.init( Cipher.DECRYPT_MODE, key, sr );
    // 现在,获取数据并解密
    byte encryptedData[] = /* 获得经过加密的数据 */
    // 正式执行解密操作
    byte decryptedData[] = cipher.doFinal( encryptedData );
    // 进一步处理解密后的数据
    doSomething( decryptedData );
    

    实际案例

    这里写了一个简单的例子,代码在github

    首先生成密钥:

    1
    2
    3
    
    javac FileUtil.java 
    javac GenerateKey.java
    java GenerateKey key.data
    

    然后加密class:

    1
    2
    
    javac EncryptClasses.java
    java EncryptClasses key.data App.class Foo.class Bar.class
    

    运行加密后的应用:

    1
    2
    
    javac MyClassLoader.java -Xlint:unchecked 
    java MyClassLoader key.data App
    

    总的来说ClassLoader在类非常多的情况还是比较麻烦,而且这样一来自定义的ClassLoader本身就成为了突破口。下面介绍另外一种加密保护的方案。

    jvmti

    jvmti(JVMTM Tool Interface)是JDK提供的一套用于开发JVM监控,问题定位与性能调优工具的通用变成接口。通过JVMTI,我们可以开发各式各样的JVMTI Agent。这个Agent的表现形式是一个以c/c++语言编写的动态共享库。

    JVMTI Agent原理: java启动或运行时,动态加载一个外部基于JVM TI编写的dynamic module到Java进程内,然后触发JVM源生线程Attach Listener来执行这个dynamic module的回调函数。在函数体内,你可以获取各种各样的VM级信息,注册感兴趣的VM事件,甚至控制VM的行为。

    这里我们只需要监控class的加载信息,而jvmti也提供了这样的接口,通过下面的方式我们就能监控到class的加载:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    
    JNIEXPORT jint JNICALL
    Agent_OnLoad(
        JavaVM *vm,
        char *options,
        void *reserved
    )
    {
    	......
    	//设置事件回调
        jvmtiEventCallbacks callbacks;
        (void)memset(&callbacks,0, sizeof(callbacks));
     
        callbacks.ClassFileLoadHook = &MyClassFileLoadHook;
        error = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
        ......
    }
    
    void JNICALL
    MyClassFileLoadHook(
        jvmtiEnv *jvmti_env,
        JNIEnv* jni_env,
        jclass class_being_redefined,
        jobject loader,
        const char* name,   //class名字
        jobject protection_domain,
        jint class_data_len,  //class文件数据长度
        const unsigned char* class_data,   //class文件数据
        jint* new_class_data_len,   //新的class文件数据长度
        unsigned char** new_class_data   //新的class文件数据
    )
    {
    	......
    }
    

    通过这样的方式就能监控到class的加载然后再对其进行解密。

    加密、解密

    加密class文件

    这里简单的通过遍历class文件,然后对每个字节进行一个异或处理,具体的加密方法可以自己扩展:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    extern"C" JNIEXPORT jbyteArray JNICALL 
    Java_Encrypt_encrypt(
        JNIEnv * _env, 
        jobject _obj,
        jbyteArray _buf
    )
    {
        jsize len =_env->GetArrayLength(_buf);   
    
        unsigned char* dst = (unsigned char*)_env->GetByteArrayElements(_buf, 0);
     	
     	for (int i = 0; i < len; ++i)
     	{
     		dst[i] = dst[i] ^ 0x07;
     	}
     
        _env->SetByteArrayRegion(_buf, 0, len, (jbyte *)dst);
        return _buf;
    }
    

    解密class文件

    在运行jar文件的时候,加载我们的jvmti agent动态库进行动态解密:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    
    void JNICALL
    MyClassFileLoadHook(
        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
    )
    {
        *new_class_data_len = class_data_len;
        jvmti_env->Allocate(class_data_len, new_class_data);
     
        unsigned char* my_data = *new_class_data;
    
        if(name&&strncmp(name,"com/monkey/",11)==0){
            for (int i = 0; i < class_data_len; ++i)
            {
                my_data[i] = class_data[i] ^ 0x07;
            }
        }else{
            for (int i = 0; i < class_data_len; ++i)
            {
                my_data[i] = class_data[i];
            }
        }
    }
    

    实际案例

    这里写了一个简单的例子,代码在github

    首先加密jar包:

    1
    2
    
    javac Encrypt.java
    java -Djava.library.path=. -cp . Encrypt -src jardemo.jar
    

    image

    然后会得到一个jardemo_encrypt.jar文件,如果现在直接去运行该文件的话肯定是会出错的,所以要做解密。

    先编译生成一个解密的动态库libdecrypt.dylib。然后运行:

    1
    
    java -jar -agentlib:decrypt jardemo_encrypt.jar
    

    image

    总结

    总的来说,使用jvmti提供的监控api,方便了我们直接对class的操作,所以第二个方案更好一些,当然其中具体使用怎么样的加密,以及如何去保证加密不被破解就需要各位发挥自己的空间了。

    原链接容易打不开

    http://www.alonemonkey.com/2016/05/25/encrypt-jar-class/

    展开全文
  • java jar包加密

    千次阅读 2019-04-16 23:38:04
    方案一:xjar - Spring Boot JAR 安全加密运行工具 GitHub: ... 基于对JAR包内资源的加密以及拓展ClassLoader来构建的一套程序加密启动,动态解密运行的方案,避免源码泄露或反编译。 ...

    方案一:xjar - Spring Boot JAR 安全加密运行工具

    GitHub: https://github.com/core-lib/xjar

    基于对JAR包内资源的加密以及拓展ClassLoader来构建的一套程序加密启动,动态解密运行的方案,避免源码泄露或反编译。
    这里只是最最简单场景下的使用步骤,进阶用法请参考官网

    1. 添加依赖

    在pom中project节点下添加jitpack仓库

    <!-- 设置 jitpack.io 仓库 -->
    <repositories>
    	<repository>
    		<id>jitpack.io</id>
    		<url>https://www.jitpack.io</url>
    	</repository>
    </repositories>
    

    添加xjar依赖

    <!-- 添加 XJar 依赖 -->
    <dependency>
    	<groupId>com.github.core-lib</groupId>
    	<artifactId>xjar</artifactId>
    	<version>v1.1.4</version>
    </dependency>
    

    2. Springboot Jar包加密

    @Test
    public void test() throws Exception {
    	String password = "io.xjar";
        XBoot.encrypt("D:/test/test.jar", "D:/test/encryptedTest.jar", password,
        		new XJarRegexEntryFilter("BOOT-INF/classes/com/.+?"));//只加密classes/com下的文件
        System.out.println("done");
    }
    
    // 危险加密模式,即不需要输入密码即可启动的加密方式,这种方式META-INF/MANIFEST.MF中会保留密钥,请谨慎使用!
    String password = "io.xjar";
    XKey xKey = XKit.key(password);
    XBoot.encrypt("/path/to/read/plaintext.jar", "/path/to/save/encrypted.jar", xKey, XConstants.MODE_DANGER);
    

    3. 运行jar

    java -jar encryptedTest.jar --xjar.password=io.xjar
    

    方案二:ProGuard - 代码混淆

    官网:https://www.guardsquare.com/en/products/proguard
    参考:https://blog.csdn.net/u010142437/article/details/72819771

    方案三:Allatori- 代码混淆

    官网:http://www.allatori.com/
    参考:https://github.com/Lovnx/confusion

    展开全文
  • java的jar包加密及使用

    万次阅读 2017-08-30 11:41:31
    由于项目要求(虽然我觉得代码没什么机密可言...),写好的jar包需要做一定加密处理 这里提供两种办法,一种奇葩,一种通用 1. 直接修改jar文件: 具体步骤:  在代码中插入一段不会运行的到的代码 1 ...
  • java项目的jar包加密(防止反编译)

    万次阅读 2018-01-11 16:30:18
    最近给公司写了一个项目,需要给其他公司用,为了不让别人看到源码,将项目打成了jar包,但是jar包用反编译工具... 其实jar包加密只是增加了反编译时间,理论上还是能破解的,但是有总比没有好。废话少说,开始吧。
  • Java jar包加密

    2020-08-31 16:24:55
    Java项目中jar包在window以及Linux环境下的加密 公司项目需要交付时对项目源码进行加密,本文针对Java spring boot项目的jar包运行方式进行加密加密工具:xjar,地址:https://gitee.com/core-lib/xjar 前提...
  • Springboot项目中jar包加密

    千次阅读 2019-10-22 19:29:14
    使用异或加密的形式,加密jar包 异或加密的原理: 一个整数 a 和任意一个整数 b 异或两次,得到的结果是整数 a 本身,即: a == a ^ b ^ b。 这里的 a 就是需要加密的原数据,b 则是密钥。a ^ b 就是加密过程,...
  • java项目的jar包加密(用abc混淆)

    千次阅读 2020-03-09 11:02:20
    最近给公司写了一个项目,需要给其他公司用,为了不让别人看到源码,将项目打成了jar包,但是jar包...其实jar包加密只是增加了反编译时间,理论上还是能破解的,但是有总比没有好。废话少说,开始吧。 软件下载解压...
  • Java项目对jar包加密流程

    千次阅读 2018-10-10 14:33:06
    Java 开发语言以其安全性高、代码优化、跨平台等特性,迅速取代了很多传统高级语言,占据了企业级网络应用开发等诸多领域的霸主地位。特别是近年来大数据、互联网+、云计算技术的不断发展,Java 开发语言更具有不可...
  • Jar包 加密混淆

    2020-08-27 17:38:04
    转发:https://www.cnblogs.com/zqzdong/p/9923472.html
  • 基于对JAR包内资源的加密以及拓展ClassLoader来构建的一套程序加密启动,动态解密运行的方案,避免源码泄露或反编译。 功能特性 无需侵入代码,只需要把编译好的JAR包通过工具加密即可。 完全内存解密,杜绝源码...
  • 最近公司有个项目涉及到,部署到待签约合作的客户服务器上,因为考虑到demo的代码保护,所以对springboot打包生成的jar包进行加密。从网上找了很多资料,有些是利用 ProGuard进行代码混淆,但这个方法我尝试过很多次...
  • 基于对JAR包内资源的加密以及拓展ClassLoader来构建的一套程序加密启动,动态解密运行的方案,避免源码泄露或反编译。 功能特性 无需侵入代码,只需要把编译好的JAR包通过工具加密即可。 完全内存解密,杜绝源码以及...
  • Java Jar 包加密 -- XJar

    2020-09-23 14:43:03
    Java Jar 包加密 一、缘由  Java的 Jar包中的.class文件可以通过反汇编得到源码。这样一款应用的安全性就很难得到保证,别人只要得到你的应用,不需花费什么力气,就可以得到源码。  这时候就需要对jar进行加密...
  • jar包加密

    千次阅读 2019-04-30 10:15:35
    不小心把公司的jar包给解密了。。。很尴尬,研究一下。。...对jar包进行加密,然后在Java层重写类加载器对其进行解密,以达到对jar包加密保护。包括用对称加密算法和非对称加密算法。不管用什...
  • Jar包加密,防止反编译方法XJar加密工具XJar功能特性使用方法(手动执行方式)使用方法(Maven插件方式)exe4j加密工具使用方法jvmti加密工具使用方法参考 XJar加密工具 XJar功能特性 基于对JAR包内资源的加密以及...
  • 基于对JAR包内资源的加密以及拓展ClassLoader来构建的一套程序加密启动,动态解密运行的方案,避免源码泄露或反编译。 功能特性 无需侵入代码,只需要把编译好的JAR包通过工具加密即可。 完全内存解密,杜绝源码...
1 2 3 4 5 ... 20
收藏数 42,529
精华内容 17,011
关键字:

jar包加密