使用开源工具ProGuard实现Java代码混淆

参考文档:

  1. ProGuard官网
  2. ProGuardMaven插件文档
  3. ProGuard官方配置文档
  4. ProGuard配置中文文档
  5. CSDN-ProGuard使用演示
  6. 知乎-ProGuard使用演示

一、概述

代码混淆是将计算机程序的代码转换成一种功能上等价,但是难以阅读和理解的形式。

二、常见的混淆思路

  • 符号混淆

    将函数的符号,如函数名、变量名去除或混淆。

  • 控制流混淆

    混淆程序正常的控制流,使其在功能保持不变的情况下,使其不能清晰地反映原程序的正常逻辑。

  • 计算混淆

    混淆程序的计算流程,或计算流程中使用的数据,使分析者难以分辨某一段代码所执行的具体计算。

  • 虚拟机混淆

    将一组指令集合(如一组x86指令)转化为一组攻击者未知的自定义指令集,并用与程序绑定的解释器解释执行。

三、ProGuard工具

ProGuard是一个压缩、优化和混淆Java字节码文件的免费的工具,它可以删除无用的类、字段、方法和属性。可以删除没用的注释,最大限度地优化字节码文件。它还可以使用简短的无意义的名称来重命名已经存在的类、字段、方法和属性。常常用于Android/Java开发用于混淆最终的项目,增加项目被反编译的难度。

​ 处理流程:

  • 在这里插入图片描述

​ 1)压缩(shrink):检测并删除未使用的类,字段,方法和属性

​ 2)优化(Optimize):分析并优化方法的字节码

​ 3)混淆(obfuscate):使用简短无意义的名称如a,b等重命名类、方法和属性。

​ 4)预检(preverify):Java平台上对处理后的代码进行预检

四、引入项目

​ ProGuard官方默认提供Gradle插件,不提供Maven插件。但是官方推荐了两个Maven插件wvengen/proguarddingxin/proguard,我们使用第一个插件。

项目使用的框架及语言版本:

-版本
Spring2.7.* (2.0+版本都可以,1.5和3.0+未测试)
Java8
proguard2.6.0

1. 配置xml

<build>
  <plugins>
    <!--  代码混淆proguard maven插件  -->
    <plugin>
      <groupId>com.github.wvengen</groupId>
      <artifactId>proguard-maven-plugin</artifactId>
      <version>2.6.0</version>
      <executions>
        <!--   package时执行proguard   -->
        <execution>
          <phase>package</phase>
          <goals>
            <goal>proguard</goal>
          </goals>
        </execution>
      </executions>
      <configuration>
        <!--  输入的jar包  -->
        <injar>${project.build.finalName}.jar</injar>
        <!--  输出的jar包  -->
        <outjar>${project.build.finalName}.jar</outjar>
        <!--  是否进行混淆,默认为true  -->
        <obfuscate>true</obfuscate>
        <!--  配置文件,通常为proguard.cfg,主要对options选项进行配置,所有的options选项都可以进行配置  -->
        <proguardInclude>${project.basedir}/proguard.cfg</proguardInclude>
        <!--  额外的jar,项目编译所需的jar  -->
        <libs>
          <lib>${java.home}/lib/rt.jar</lib>
          <!--<lib>${java.home}/lib/jce.jar</lib>-->
          <lib>${java.home}/lib/jsse.jar</lib>
        </libs>
        <!--  对输入jar进行过滤,如对META-INFO文件不处理  -->
        <inLibsFilter>!META-INF/**,!META-INF/versions/**</inLibsFilter>
        <!--  输出路径配置,必须包含injar标签中填写的jar  -->
        <outputDirectory>${project.build.directory}</outputDirectory>
        <!--  上面使用了conf配置文件,options无需配置  -->
        <!--<options></options>-->
      </configuration>
    </plugin>
  </plugins>
</build>

2. proguard.cfg文件配置

​ 该文件主要是对项目代码混淆时的参数配置,这里放在项目根目录与pom文件同级

# 指定 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{<methods>;}

keep可以帮助我们保留我们不需要进行混淆的类、方法或属性,关于上述配置文件中的keep关系整理:

保留内容防止删除或重命名防止重命名
类和类成员-keep-keepnames
仅类成员-keepclassmembers-keepclassmembernames
如果类成员存在,保留类和类成员-keepclasswithmembers-keepclasswithmembernames

更多属性配置,请参照:ProGuard配置中文文档

3. 项目结构

├── 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)进行查看:

在这里插入图片描述

2. 混淆后代码反编译演示

将项目代码混淆后通过反编译工具查看

在这里插入图片描述

3. 使用命令启动混淆后的jar包

java -jar proguard-1.0.0-SNAPSHOT.jar

请求接口进行测试

在这里插入图片描述

六、源码

Gitee码云,免费下载及参考。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
ProGuard是一个开源Java字节码混淆器、压缩器、优化器和预验证器。它可以用于减小应用程序的大小,保护代码安全以及提高应用程序的性能。ProGuard支持Java SE和Java ME,并可以与其他Java开发工具(如Eclipse、Ant和Maven)一起使用ProGuard基于一些简单的规则来混淆Java代码。这些规则指定了哪些类、方法和字段应该被保留,哪些应该被混淆或删除。例如,ProGuard可以将类、方法和字段的名称替换为随机的字符串,使得反编译后的代码难以理解。 以下是一些常见的ProGuard规则: -keep public class com.example.MyClass -keepclassmembers public class com.example.MyClass { public void myPublicMethod(); protected void myProtectedMethod(); private void myPrivateMethod(); } 上述规则意味着保留com.example.MyClass类以及其公共方法,保留com.example.MyClass类的公共、受保护和私有方法。 ProGuard还支持其他规则,如keepnames、keepattributes和dontwarn。这些规则可以进一步定制混淆过程。 要使用ProGuard混淆Java代码,需要先将代码编译成字节码,然后使用ProGuard对字节码进行混淆。可以使用以下命令运行ProGuardjava -jar proguard.jar @proguard.cfg 其中,proguard.cfg是包含ProGuard规则的配置文件。运行ProGuard后,将产生一个混淆后的.jar文件,其中包含混淆后的字节码和ProGuard生成的映射文件,该文件可以用于调试和错误分析。 总之,使用ProGuard可以有效地保护Java代码的安全性和减小应用程序的大小,但需要注意在混淆过程中可能会引入一些问题,如混淆后的代码无法运行或某些类或方法被错误地删除。因此,需要谨慎地选择ProGuard规则并进行适当的测试和调试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值