Spring Boot 代码混淆

什么是代码混淆?

就是将代码的通过工具使其可读性变差(越差越好😄)

Proguard是什么?

官网地址:www.guardsquare.com/proguard 该工具主要是为了实现Java以及Android App的代码混淆工作。 从官网的说明可以地址,该公司主要做手机应用保护的。proguard的使用手册是www.guardsquare.com/manual/home… guard官方其实并没有提供maven的插件依赖,官网默认的是gradle,不过官方推荐了两个maven插件 [github.com/wvengen/pro…]https://github.com/wvengen/proguard-maven-plugingithub.com/dingxin/pro…

本文目标

本文并不是介绍proguard如何使用(proguard有standalone模式,可以直接使用proguard.sh命令行进行混淆代码),而是使用wvengen的proguard-maven-plugin插件实现将一个spring boot项目进行混淆。

准备项目

我这里使用的是Spring Boot 2.7.x,JDK使用的是8.

混淆前

首先打包看下未混淆前打包,查看反编译后的文件,这里需要使用反编译工具,可以去github.com/java-decomp… 打包:使用mvn clean package -DskipTests 或者直接使用IDEA的Build工具都可以。

#非必须选项,因为我电脑上安装多个版本的JDK。而环境变量中配置的不是jdk1.8,所有需要执行如下命令。 ➜  Spring-Boot-Proguard git:(main) ✗ export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_333.jdk/Contents/Home #我这里使用的是./mvnw,用mvn也可(只要你的电脑配置了环境变量,如果没配置,就可以使用spring boot项目下的mvnw) ➜  Spring-Boot-Proguard git:(main) ✗ ./mvnw clean package -DskipTestclears
[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------< com.itlab1024:Spring-Boot-Proguard >-----------------
[INFO] Building Spring-Boot-Proguard 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:3.2.0:clean (default-clean) @ Spring-Boot-Proguard ---
^C%                                                                                                                ➜  Spring-Boot-Proguard git:(main) ✗ 
➜  Spring-Boot-Proguard git:(main) ✗ ./mvnw clean package -DskipTests     
[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------< com.itlab1024:Spring-Boot-Proguard >-----------------
[INFO] Building Spring-Boot-Proguard 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:3.2.0:clean (default-clean) @ Spring-Boot-Proguard ---
[INFO] Deleting /Users/itlab/workspace/github/Spring-Boot-Proguard/target
[INFO] 
[INFO] --- maven-resources-plugin:3.2.0:resources (default-resources) @ Spring-Boot-Proguard ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Using 'UTF-8' encoding to copy filtered properties files.
[INFO] Copying 1 resource
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.10.1:compile (default-compile) @ Spring-Boot-Proguard ---
[INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to /Users/itlab/workspace/github/Spring-Boot-Proguard/target/classes
[INFO] 
[INFO] --- maven-resources-plugin:3.2.0:testResources (default-testResources) @ Spring-Boot-Proguard ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Using 'UTF-8' encoding to copy filtered properties files.
[INFO] skip non existing resourceDirectory /Users/itlab/workspace/github/Spring-Boot-Proguard/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.10.1:testCompile (default-testCompile) @ Spring-Boot-Proguard ---
[INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to /Users/itlab/workspace/github/Spring-Boot-Proguard/target/test-classes
[INFO] 
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ Spring-Boot-Proguard ---
[INFO] Tests are skipped.
[INFO] 
[INFO] --- maven-jar-plugin:3.2.2:jar (default-jar) @ Spring-Boot-Proguard ---
[INFO] Building jar: /Users/itlab/workspace/github/Spring-Boot-Proguard/target/Spring-Boot-Proguard-0.0.1-SNAPSHOT.jar
[INFO] 
[INFO] --- spring-boot-maven-plugin:2.7.4:repackage (repackage) @ Spring-Boot-Proguard ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.584 s
[INFO] Finished at: 2022-10-15T17:31:08+08:00 [INFO] ------------------------------------------------------------------------
完成后,我们target下就能看到打好的jar文件。使用jd-gui打开查看。

可以看到,代码没有被混淆。

代码混淆

接下来我使用proguard实现代码混淆。主要是在pom中使用插件来实现。

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.4</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.itlab1024</groupId> <artifactId>Spring-Boot-Proguard</artifactId> <version>0.0.1-SNAPSHOT</version> <name>Spring-Boot-Proguard</name> <description>Spring-Boot-Proguard</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>com.github.wvengen</groupId> <artifactId>proguard-maven-plugin</artifactId> <version>2.6.0</version> <executions> <!-- 以下配置说明执行mvn的package命令时候,会执行proguard--> <execution> <phase>package</phase> <goals> <goal>proguard</goal> </goals> </execution> </executions> <configuration> <!-- 就是输入Jar的名称,我们要知道,代码混淆其实是将一个原始的jar,生成一个混淆后的jar,那么就会有输入输出。 --> <injar>${project.build.finalName}.jar</injar> <!-- 输出jar名称,输入输出jar同名的时候就是覆盖,也是比较常用的配置。 --> <outjar>${project.build.finalName}.jar</outjar> <!-- 是否混淆 默认是true --> <obfuscate>true</obfuscate> <!-- 配置一个文件,通常叫做proguard.cfg,该文件主要是配置options选项,也就是说使用proguard.cfg那么options下的所有内容都可以移到proguard.cfg中 --> <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/9/**.class</inLibsFilter> <!-- 这是输出路径配置,但是要注意这个路径必须要包括injar标签填写的jar --> <outputDirectory>${project.basedir}/target</outputDirectory> <!--这里特别重要,此处主要是配置混淆的一些细节选项,比如哪些类不需要混淆,哪些需要混淆--> <options> <!-- 可以在此处写option标签配置,不过我上面使用了proguardInclude,故而我更喜欢在proguard.cfg中配置 --> </options> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> <configuration> <mainClass>com.itlab1024.proguard.SpringBootProguardApplication</mainClass> </configuration> </execution> </executions> </plugin> </plugins> </build> </project> 

再新建个mvc的controller。

package com.itlab1024.proguard.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;

@RestController public class IndexController { /**
     * 主页Mapping
     * @return
     */ @GetMapping public String index() { return "这是主页";
    }
}

proguard.cfg配置

#指定Java的版本 -target 1.8 #proguard会对代码进行优化压缩,他会删除从未使用的类或者类成员变量等 -dontshrink #是否关闭字节码级别的优化,如果不开启则设置如下配置 -dontoptimize #混淆时不生成大小写混合的类名,默认是可以大小写混合 -dontusemixedcaseclassnames # 对于类成员的命名的混淆采取唯一策略 -useuniqueclassmembernames #混淆时不生成大小写混合的类名,默认是可以大小写混合 -dontusemixedcaseclassnames #混淆类名之后,对使用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 public class com.itlab1024.proguard.SpringBootProguardApplication { public static void main(java.lang.String[]);
    }

混淆后反编译结果如下:



可以看到IndexController被混淆了,Spring Boot的启动类SpringBootProguardApplication未被混淆。

对混淆的jar进行启动

➜  target git:(main) ✗ java -jar Spring-Boot-Proguard-0.0.1-SNAPSHOT.jar 

  .   ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.4)

2022-10-16 16:44:23.132  INFO 12416 --- [           main] c.i.p.SpringBootProguardApplication      : Starting SpringBootProguardApplication v0.0.1-SNAPSHOT using Java 17.0.3.1 on 192.168.0.100 with PID 12416 (/Users/itlab/workspace/github/Spring-Boot-Proguard/target/Spring-Boot-Proguard-0.0.1-SNAPSHOT.jar started by itlab in /Users/itlab/workspace/github/Spring-Boot-Proguard/target)
2022-10-16 16:44:23.138  INFO 12416 --- [           main] c.i.p.SpringBootProguardApplication      : No active profile set, falling back to 1 default profile: "default"
2022-10-16 16:44:24.406  INFO 12416 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-10-16 16:44:24.420  INFO 12416 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-10-16 16:44:24.420  INFO 12416 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.65]
2022-10-16 16:44:24.528  INFO 12416 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-10-16 16:44:24.528  INFO 12416 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1266 ms
2022-10-16 16:44:24.996  INFO 12416 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-10-16 16:44:25.007  INFO 12416 --- [           main] c.i.p.SpringBootProguardApplication      : Started SpringBootProguardApplication in 2.538 seconds (JVM running for 3.108) 

访问主页:



备注

  1. 上面知识简单的介绍了插件的使用,其实有很多选项,并未一一介绍,但是基本够用。
  2. 如果配置文件中一个-keep都没有设置,打包会报错的,要注意下。
  3. 对于Java项目,哪些class需要混淆,哪些不需要混淆,自己一定要清楚。比如AOP或者读取路径等的地方肯定是不能够混淆的。另外一般接口也不建议混淆。因为有些第三方工具接口的名称是有意义的,就比如Mybatis的接口以及参数名字,在xml(也可能没有xml)的sql中都是一一对应的,如果混淆就找不到了。
  4. 另外混淆后,强烈建议多测试,笔者就是在实际过程中混淆的时候发现了很多问题。
#Java##程序员#
全部评论

相关推荐

造车新势力 自动驾驶规控 29k * 13
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务