# ProGuard-Demo **Repository Path**: hikdah/proguard-demo ## Basic Information - **Project Name**: ProGuard-Demo - **Description**: 使用proguard开源工具对Java代码进行混淆的一个代码示例。 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 6 - **Created**: 2025-06-18 - **Last Updated**: 2025-06-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 使用开源工具ProGuard实现Java代码混淆 参考文档: 1. [ProGuard官网](https://www.guardsquare.com/proguard) 2. [ProGuardMaven插件文档](https://wvengen.github.io/proguard-maven-plugin/#proguard-mojo.htmloptions) 3. [ProGuard官方配置文档](https://www.guardsquare.com/manual/configuration/usage) 4. [ProGuard配置中文文档](https://www.jianshu.com/p/47ddf0a9d07e) 5. [CSDN-ProGuard使用演示](https://blog.csdn.net/liaomingwu/article/details/123680696) 6. [知乎-ProGuard使用演示](https://zhuanlan.zhihu.com/p/574137579) ## 一、概述 代码混淆是将计算机程序的代码转换成一种功能上等价,但是难以阅读和理解的形式。 ## 二、常见的混淆思路 - ### 符号混淆 将函数的符号,如函数名、变量名去除或混淆。 - ### 控制流混淆 混淆程序正常的控制流,使其在功能保持不变的情况下,使其不能清晰地反映原程序的正常逻辑。 - ### 计算混淆 混淆程序的计算流程,或计算流程中使用的数据,使分析者难以分辨某一段代码所执行的具体计算。 - ### 虚拟机混淆 将一组指令集合(如一组x86指令)转化为一组攻击者未知的自定义指令集,并用与程序绑定的解释器解释执行。 ## 三、ProGuard工具 ​ **ProGuard**是一个压缩、优化和混淆[Java字节码](https://baike.baidu.com/item/Java字节码/13025120?fromModule=lemma_inlink)文件的免费的工具,它可以删除无用的类、字段、方法和属性。可以删除没用的注释,最大限度地优化字节码文件。它还可以使用[简短](https://baike.baidu.com/item/简短/7933503?fromModule=lemma_inlink)的无意义的名称来重命名已经存在的类、字段、方法和属性。常常用于Android/Java开发用于混淆最终的项目,增加项目被反编译的难度。 ​ 处理流程: - ![输入图片说明](image/1200.jpeg) ​ 1)压缩(shrink):检测并删除未使用的类,字段,方法和属性 ​ 2)优化(Optimize):分析并优化方法的字节码 ​ 3)混淆(obfuscate):使用简短无意义的名称如a,b等重命名类、方法和属性。 ​ 4)预检(preverify):Java平台上对处理后的代码进行预检 ## 四、引入项目 ​ ProGuard官方默认提供Gradle插件,不提供Maven插件。但是官方推荐了两个Maven插件[wvengen/proguard](https://github.com/wvengen/proguard-maven-plugin)与[dingxin/proguard](https://github.com/dingxin/proguard-maven-plugin),我们使用第一个插件。 项目使用的框架及语言版本: | - | 版本 | | -------- | --------------------------------------- | | Spring | 2.7.* (2.0+版本都可以,1.5和3.0+未测试) | | Java | 8 | | proguard | 2.6.0 | ### 1. 配置xml ```xml com.github.wvengen proguard-maven-plugin 2.6.0 package proguard ${project.build.finalName}.jar ${project.build.finalName}.jar true ${project.basedir}/proguard.cfg ${java.home}/lib/rt.jar ${java.home}/lib/jsse.jar !META-INF/**,!META-INF/versions/** ${project.build.directory} ``` ### 2. proguard.cfg文件配置 ​ 该文件主要是对项目代码混淆时的参数配置,这里放在项目根目录与pom文件同级 ```yaml # 指定 java 版本 -target 1.8 # 关闭对代码进行优化压缩,开启会删除从未使用的类或者类成员变量等 -dontshrink # 列出未使用的代码,可打印到标准输出或写入指定文件 #-printusage # 关闭字节码级别的优化,如果不开启则设置如下配置,默认开启。 -dontoptimize # 关闭预检,预检主要针对JavaME,Java6以后都不用预检 -dontpreverify # 不生成大小写混写的类名 -dontusemixedcaseclassnames # 对类成员的命名混淆采取唯一策略 -useuniqueclassmembernames # 混淆类名之后,对使用Class.forName('className')之类的地方进行相应替代 -adaptclassstrings #对异常、注解信息予以保留 -keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod # 此选项将保存接口中的所有原始名称(不混淆)--> -keepnames interface ** { *; } # 此选项将保存所有软件包中的所有原始接口文件(不进行混淆) #-keep interface * extends * { *; } #保留参数名,因为控制器,或者Mybatis等接口的参数如果混淆会导致无法接受参数,xml文件找不到参数 -keepparameternames # 保留枚举成员及方法 -keepclassmembers enum * { *; } # 不混淆所有类,保存原始定义的注释- -keepclassmembers 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 *; } #忽略warn消息 -ignorewarnings #忽略note消息 #-dontnote #打印配置信息 #-printconfiguration # 排除混淆 指定的类名且类中的方法也不混淆 -keep class com.example.proguard.ProguardDemoApplication{;} ``` keep可以帮助我们保留我们不需要进行混淆的类、方法或属性,关于上述配置文件中的keep关系整理: | 保留内容 | 防止删除或重命名 | 防止重命名 | | :----------------------------- | --------------------- | ------------------------- | | 类和类成员 | -keep | -keepnames | | 仅类成员 | -keepclassmembers | -keepclassmembernames | | 如果类成员存在,保留类和类成员 | -keepclasswithmembers | -keepclasswithmembernames | 更多属性配置,请参照:[ProGuard配置中文文档](https://www.jianshu.com/p/47ddf0a9d07e) ### 3. 项目结构 ```basic ├── pom.xml ├── proguard.cfg └── src ├── main │   ├── java │   │   └── com │   │   └── example │   │   └── proguard │   │   ├── ProguardDemoApplication.java │   │   └── controller │   │   └── IndexController.java │   └── resources │   └── application.yml └── test ``` ### 4. 注意事项 - **不混淆反射代码。(class.forName("类名"))** - **不混淆需要bean注入的类。(因为我们没有给bean指定id,那么此时的bean的唯一标识的就是name。)** - **不混淆aop切面的类或方法。(原因与上述大致)** - **混淆之后可能会有很多奇怪的问题导致项目启动失败,需要根据实际情况进行放行(不混淆)。** - **对于混淆成功了的项目也需要多进行测试,保证其功能与接口完成与未混淆的源码功能一致。** ## 五、成功演示 ### 1. 未混淆代码反编译演示 将项目正常打包后通过反编译工具(JD)进行查看: ![输入图片说明](image/image-20230302141251364.png) ### 2. 混淆后代码反编译演示 将项目代码混淆后通过反编译工具查看 ![输入图片说明](image/image-20230302141814380.png) ### 3. 使用命令启动混淆后的jar包 ```java java -jar proguard-1.0.0-SNAPSHOT.jar ``` 请求接口进行测试 ![输入图片说明](image/image-20230302142846258.png)