乐趣区

java混淆了吗

前言

最近在项目中碰到个一个场景,我们需要把自己的 java 项目 jar 包部署到一个第三方的服务器上,虽然双方互相信任,但是综合考虑,避免别人拿到 jar 包后可以很快的编译出源码,我们决定给代码加一层混淆,虽然此方法不能从根源上解决问题,但是做了一层混淆,也可以增加阅读源码的难度,总结了一下,写下这篇文章。

如何反编译 java 代码

我用的是 mac 电脑,从官网:http://java-decompiler.github… 下载 JD-GUI,官网有很多版本,下载后安装打开即可,导入你想反编译的 jar,我这里随便找了个 jar 包做演示

何为 java 混淆

细心的小伙伴肯定发现了,上面的截图有的包名是 a,b,c 这样命名的,但凡有点节操的程序员都不会这样命名的,这就是被混淆后的代码,让人不会一眼看出来代码里面的逻辑,效果会像下面这样

可以看到类名,包名都被修改了

进行 java 混淆

我们以之前 springboot 项目为例,进行 service 层的代码的混淆,混淆前效果如下:



接下来我们只需要在 pom 里面加入如下插件

              <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>com.github.wvengen</groupId>
                <artifactId>proguard-maven-plugin</artifactId>
                <version>2.0.14</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>proguard</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <proguardVersion>6.1.0beta2</proguardVersion>
                    <injar>${project.build.finalName}.jar</injar>
                    <outjar>${project.build.finalName}.jar</outjar>
                    <obfuscate>true</obfuscate>
                    <options>
                        <option>-dontshrink</option>
                        <option>-dontoptimize</option>
                        <!-- This option will replace all strings in reflections method invocations with new class names.
                             For example, invokes Class.forName('className')-->
                        <option>-adaptclassstrings</option>
                        <option>-keepdirectories</option>
                        <!-- This option will save all original annotations and etc. Otherwise all we be removed from files.-->
                        <option>-keepattributes
                            Exceptions,
                            InnerClasses,
                            Signature,
                            Deprecated,
                            SourceFile,
                            LineNumberTable,
                            *Annotation*,
                            EnclosingMethod
                        </option>
                        <!-- This option will save all original names in interfaces (without obfuscate).-->
                        <option>-keepnames interface **</option>
                        <!-- This option will save all original methods parameters in files defined in -keep sections,
                             otherwise all parameter names will be obfuscate.-->
                        <option>-keepparameternames</option>
                        <!-- 不使用大小写字母进行混淆,保持类唯一性 -->
                        <option>-dontusemixedcaseclassnames</option>
                        <!-- This option will save all original class files (without obfuscate) but obfuscate all
                             in domain and service packages.-->
                        <option>-keep
                            class com.stone.zplxjj.Application {public static void main(java.lang.String[]);
                            }
                        </option>
                        <!-- 指明哪些类可以不被混淆 -->
                        <option>-keep class com.stone.zplxjj.autoconfiguration.** {*;}</option>
                        <option>-keep class com.stone.zplxjj.config.** {*;}</option>
                        <option>-keep class com.stone.zplxjj.controller.** {*;}</option>
                        <option>-keep class com.stone.zplxjj.dao.** {*;}</option>
                        <option>-keep class com.stone.zplxjj.entity.** {*;}</option>
                        <option>-keep class com.stone.zplxjj.event.** {*;}</option>
                        <option>-keep class com.stone.zplxjj.interceptor.** {*;}</option>
                        <option>-keep class com.stone.zplxjj.listener.** {*;}</option>
                        <option>-keep class com.stone.zplxjj.properties.** {*;}</option>
                        <option>-keep class com.stone.zplxjj.filter.** {*;}</option>
                        <!-- This option ignore warnings such as duplicate class definitions and classes in incorrectly
                            named files-->
                        <option>-ignorewarnings</option>
                        <!-- This option will save all original class files (without obfuscate) in service package-->
                        <!--<option>-keep class com.slm.proguard.example.spring.boot.service {*;}</option>-->
                        <!-- This option will save all original interfaces files (without obfuscate) in all packages.-->
                        <option>-keep interface * extends * {*;}</option>
                        <!-- This option will save all original defined annotations in all class in all packages.-->
                        <option>-keepclassmembers class * {
                            @org.springframework.beans.factory.annotation.Autowired *;
                            @org.springframework.beans.factory.annotation.Value *;
                            }
                        </option>
                    </options>
                    <injarNotExistsSkip>true</injarNotExistsSkip>
                    <libs>
                        <!--Put here your libraries if required-->
                        <lib>${java.home}/lib/rt.jar</lib>
                    </libs>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>net.sf.proguard</groupId>
                        <artifactId>proguard-base</artifactId>
                        <version>6.1.0beta2</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

执行打包命令:mvn package,会看到生成如下

我们看到了生成了不只一个 jar 包,还有一些别的文件,这个我们放后面介绍,我们先看下划红线的 jar 反编译后的效果


可以看到我们针对 service 包下面的类混淆成功了

注意点

  1. zplxjj_proguard_base.jar 是没有经过混淆的 jar
  2. 两个.txt 文件说明了混淆前和混淆后的对应关系
  3. 如果项目中引入了 spring 框架,类的注入 id 要保持唯一性,否则就要重写生成 bean 的 id 规则的方法
  4. 更多 pom 文件细节可以参考:https://www.guardsquare.com/e…

更多文章可关注个人博客:https://www.zplxjj.com 和公众号

退出移动版