jar包防反编译+加密方案

说明

由于程序需要部署至外部机器,直接上传打包的原生jar包有代码暴露风险,为解决此问题输出本方案。本文示例的改造加密程序为可信工业资产服务网络/密钥管理系统。

改动说明

目的:程序正常运行不出现改动导致的bug

需求:核心代码混淆,jar包加密

1、新增一个proguard.cfg文件

2、修改启动类模块的pom.xml文件

3、使用xjar工具加密

  1. ### 编写proguard.cfg文件

在启动类模块的pom.xml同级目录下新建文件,并命名为”proguard.cfg”

只需要修改文件中标注需要改动的地方,其他配置如果对proguard的kepp规则不熟悉的不要改动

#指定Java的版本
-target 1.8
#proguard会对代码进行优化压缩,他会删除从未使用的类或者类成员变量等
-dontshrink
#是否关闭字节码级别的优化,如果不开启则设置如下配置
-dontoptimize
#混淆时不生成大小写混合的类名,默认是可以大小写混合
-dontusemixedcaseclassnames
# 对于类成员的命名的混淆采取唯一策略
-useuniqueclassmembernames
#混淆时不生成大小写混合的类名,默认是可以大小写混合
-dontusemixedcaseclassnames
#混淆类名之后,对使用Class.forName('className')之类的地方进行相应替代
-adaptclassstrings
# 保留枚举成员及方法
-keepclassmembers enum * { *; }
# 此选项将保存接口中的所有原始名称(不混淆)-->
#-keepnames interface ** { *; }
# 此选项将保存所有软件包中的所有原始接口文件(不进行混淆)
#-keep interface * extends * { *; }
# 不混淆所有类,保存原始定义的注释-
-keep class * {
                        @org.springframework.context.annotation.Bean *;
                        @org.springframework.beans.factory.annotation.Autowired *;
                        @org.springframework.beans.factory.annotation.Value *;
                        @org.springframework.stereotype.Service *;
                        @org.springframework.stereotype.Component *;
                        @org.apache.dubbo.config.annotation.DubboReference *;
                        @org.apache.dubbo.config.annotation.DubboService *;
                        @javax.annotation.Resource *;
                    }
#忽略warn消息
-ignorewarnings
#忽略note消息
-dontnote **
#打印配置信息
-printconfiguration
#保持目录结构
-keepdirectories
#保持序列化的类成员
-keepclassmembers class * implements java.io.Serializable {*;}
#不混淆方法参数名、包名
-keepattributes MethodParameters , Packagenames
#对异常、注解信息予以保留
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod

###############################以上配置不需要修改####################################
####                                                                           ####
####                            proguard混淆配置文件                            ####
####                                                                           ####
###############################根据实际情况修改下方配置###############################

#不混淆该类内的所有名字,一般指包含切点的切面对象,项目中没有用到可以注释
-keepnames class com.plktech.gyhlw.component.LogAspect {*;}

#不混淆dao层的jpa接口,这个需要根据项目实际路径修改,要混淆的模块不包含的话可以注释
-keepnames interface com.plktech.gyhlw.dao.* { *; }

#不混淆mapper层的映射接口,这个需要根据项目实际路径修改,要混淆的模块不包含的话可以注释
-keepnames interface com.plktech.gyhlw.mapper.* { *; }

#不混淆启动类,根据实际情况修改路径例如:com.plktech.gyhlw.GyhlwEnterpriseApplication
-keep public class com.plktech.gyhlw.SecretKeyApplication {*;}
  1. ### 修改启动类模块的pom.xml

主要修改配置,其他配置不需要修改

  1. 单模块:service层和启动类在同一个模块中

未说明的配置项一般不需要修改,有说明解释的可根据项目实际情况修改,启动类路径一定要修改

<build>
    <finalName>{project.artifactId}</finalName>
    <plugins>
        <plugin>
            <groupId>com.github.wvengen</groupId>
            <artifactId>proguard-maven-plugin</artifactId>
            <version>2.6.0</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>proguard</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <putLibraryJarsInTempDir>true</putLibraryJarsInTempDir>
                <injar>{project.build.finalName}.jar</injar>
                <outjar>{project.build.finalName}.jar</outjar>
                <obfuscate>true</obfuscate>
                <!-- 配置一个文件,通常叫做proguard.cfg,放在pom同级目录-->
                <proguardInclude>{basedir}/proguard.cfg</proguardInclude>
                <libs>
                    <lib>{java.home}/lib/rt.jar</lib>
                    <lib>{java.home}/lib/jce.jar</lib>
                    <lib>{java.home}/lib/jsse.jar</lib>
                </libs>
                <inLibsFilter>!META-INF/**,!META-INF/versions/9/**.class</inLibsFilter>
                <outputDirectory>{project.basedir}/target</outputDirectory>
                <options>
                </options>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
            <!--启动类路径,改成项目的启动类路径(全限定性类名)-->
                <mainClass>com.plktech.gyhlw.SecretKeyApplication</mainClass>
                <excludes>
                    <exclude>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                    </exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>

</build>
  1. 多模块:启动类所在模块需要依赖service层所在模块

正常来说service层会打包成一个jar包在启动类模块的lib下,混淆的话我们需要直接将service层的class文件直接打包进启动类的模块里面,所以pom.xml的配置跟单模块有区别,此处以企业平台为例

 <build>
        <finalName>{project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>com.github.wvengen</groupId>
                <artifactId>proguard-maven-plugin</artifactId>
                <version>2.6.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>proguard</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <putLibraryJarsInTempDir>true</putLibraryJarsInTempDir>
                    <injar>{project.build.finalName}.jar</injar>
                    <outjar>{project.build.finalName}.jar</outjar>
                    <obfuscate>true</obfuscate>
                     <!-- 配置一个文件,通常叫做proguard.cfg,放在pom同级目录-->
                    <proguardInclude>{basedir}/proguard.cfg</proguardInclude>
                    <injarNotExistsSkip>true</injarNotExistsSkip>
                     <!-- 此处与单模块不同,需要将server层模块的坐标配置进来-->
                    <assembly>
                        <inclusions>
                            <inclusion>
                                <groupId>com.plktech</groupId>
                                <artifactId>enterprise</artifactId>
                            </inclusion>
                        </inclusions>
                    </assembly>
                    <options>
                    </options>
                    <libs>
                        <lib>{java.home}/lib/rt.jar</lib>
                        <lib>{java.home}/lib/jce.jar</lib>
                    </libs>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>com.guardsquare</groupId>
                        <artifactId>proguard-base</artifactId>
                        <version>7.0.0</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork> 
                    <!-- 启动类所在路径,(全限定性类名) -->
                    <mainClass>com.plktech.gyhlw.GyhlwEnterpriseApplication</mainClass>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                    <!--需要修改,此处与单模块不同,上面将哪个jar包混淆了,这里就排除哪个-->
                    <excludeGroupIds>
                        com.plktech.gyhlw.enterprise
                    </excludeGroupIds>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

混淆后的方法名和变量名与编写时不同,可增加代码阅读难度

img

  1. 加密jar包

xjar加密工具包下载

  1. 工具包下载到本地后,建议放在打包好的jar同级目录

  1. 在资源路径上输入cmd回车或者键盘win+r打开命令窗口cd到jar包路径

image-20250208181427261

  1. 运行加密工具 java -jar xjar-demo.jar

image-20250208181437388

  1. 选择要加密的jar包以及加密后保存的路径,输入密码加密

image-20250208181445951

  1. 加密成功后得到三个文件加密后的jar包encrypt-server-enterprise-execute.jar,两个go源文件xjar.go、xjar_agentable.go。

image-20250208181456186

加密后的jar包,代码已不可见

image-20250208181504942

由于我们的程序需要在liunx上运行,所以需要在liunx上编译加密后的jar,得到一个可执行脚本xjar,将上述得到的三个文件上传至liunx服务器,以(192.168.2.188)为例,服务器需要安装go运行环境

image-20250208181515320

  1. 编译go源文件

    cd 到jar包所在目录

执行 go build xjar.go 执行完得到一个 xjar的可执行脚本

image-20250208181523560

  1. 运行程序 ./xjar java -jar encrypt-server-enterprise-execute.jar

如果是 sudo 命令需要加上java的绝对路径

sudo ./xjar /usr/local/java/bin/java -jar encrypt-server-enterprise-execute.jar

程序启动成功

image-20250208181536725

  1. 上传至服务器运行,只需要上传 xjar脚本以及加密的jar包即可,且运行的服务器不需要安装go环境

运行命令同上

参考文章

proguard官方文档

https://www.guardsquare.com/manual/home

插件文档

https://wvengen.github.io/proguard-maven-plugin/

xjar加密

https://blog.csdn.net/seashouwang/article/details/115728095?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-1-115728095-blog-129407415.235

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注