Java code obfuscation-proguard

The recently developed project needs to prevent decompilation, so the research on code obfuscation was carried out, and the project was developed using the spring boot framework. After the information found on the Internet and my own experiments, the code was finally confused to the greatest extent. Record it here and share it with you.

I use the proguard-maven-plugin plugin to confuse the code, and all proguard instructions can be implemented in the pom. The first thing to say is that this method of obfuscation is to remove unused code, and then rename the classes, variables, and methods in the code to short names that are not very readable, such as a, b, c, etc., so If this level of obfuscation cannot meet your needs, look for other obfuscation methods, such as encryption.

How to confuse will be carried out next. First of all, the whole obfuscation is to introduce the proguard-maven-plugin plug-in in the pom file, and perform the specific configuration of the confusion in the pom file. The pom configuration example is as follows:

<plugin>
               <groupId>com.github.wvengen</groupId>
               <artifactId>proguard-maven-plugin</artifactId>
               <version>2.0.11</version>
               <executions>
                   <execution>
                       <!-- 混淆时刻,这里是打包的时候混淆 -->
                       <phase>package</phase>
                       <goals>
                           <!-- 使用插件的什么功能,当然是混淆 -->
                           <goal>proguard</goal>
                       </goals>
                   </execution>
               </executions>
               <configuration>
                   <!-- 是否将生成的PG文件安装部署 -->
                   <attach>true</attach>
                   <!-- 是否混淆 -->
                   <obfuscate>true</obfuscate>
                   <!-- 指定生成文件分类 -->
                   <attachArtifactClassifier>pg</attachArtifactClassifier>
                   <options>
                       <!-- 不做收缩(删除注释、未被引用代码) -->
                       <option>-dontshrink</option>
                       <!-- 不做优化(变更代码实现逻辑) -->
                       <option>-dontoptimize</option>
                       <!-- 不路过非公用类文件及成员 -->
                       <option>-dontskipnonpubliclibraryclasses</option>
                       <option>-dontskipnonpubliclibraryclassmembers</option>
                       <!-- 优化时允许访问并修改有修饰符的类和类的成员 -->
                       <option>-allowaccessmodification</option>
                       <!-- 确定统一的混淆类的成员名称来增加混淆 -->
                       <option>-useuniqueclassmembernames</option>
                       <!-- 不混淆所有包名,本人测试混淆后WEB项目问题实在太多,毕竟Spring配置中有
                       大量固定写法的包名 -->
                       <option>-keeppackagenames</option>
                       <option>-adaptclassstrings</option>
                       <!-- <option>-keepdirectories</option> -->
                       <!-- 不混淆所有特殊的类 -->
                       <option>-keepattributes
                           Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod</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>-keepclassmembers class * {
                           @org.springframework.beans.factory.annotation.Autowired *;
                           @javax.annotation.Resource *;
                           @org.springframework.beans.factory.annotation.Value *;
                           }
                       </option>

                       <option>-keep class !com.xh.okdz.** { *; }</option>
                       <!-- 不混淆main方法 -->
                       <option>-keep class com.xh.okdz.OkdzApplication { *; }</option>

                       <!-- 不混淆所有的set/get方法 -->
                       <option>-keepclassmembers public class * {void set*(***);***
                           get*();}</option>
                       <!-- 不混淆包中的所有类以及类的属性及方法,实体包,混淆了会导致ORM框架及前端无法识别 -->

                       <!-- 不对包类的类名进行混淆,但对类中的属性和方法混淆 -->
                       <option>-keep class com.java.controller.** </option>
                       <option>-keep class com.java.service.** </option>
                       <option>-keep class com.java.exception.** </option>
                       <option>-keep class com.java.tasks.** </option>
                       <option>-keep class com.java.utils.** </option>

                       <!-- 不混淆包下的所有类名,且类中的方法也不混淆 -->
                       <option>-keep class com.java.config.**{*;}</option>
                       <option>-keep class com.java.entity.** {*;}</option>
                       <option>-keep class com.java.vo.** {*;}</option>
                       <option>-keep class com.java.annotation.**{*;}</option>
                       <option>-keep class com.java.dao.** {*;}</option>

                   </options>
                   <outjar>${project.build.finalName}-pg.jar</outjar>
                   <!-- 添加依赖,这里你可以按你的需要修改,这里测试只需要一个JRE的Runtime包就行了 -->
                   <libs>
                       <lib>${java.home}/lib/rt.jar</lib>
                       <lib>${java.home}/lib/jce.jar</lib>
                   </libs>
                   <!-- 对什么东西进行加载,这里加载classes就行,配置文件或者其他的三方文件应该不会混淆吧 -->
                   <injar>classes</injar>
                   <!-- 输出目录 -->
                   <outputDirectory>${project.build.directory}</outputDirectory>
               </configuration>
               <dependencies>
                   <dependency>
                       <groupId>net.sf.proguard</groupId>
                       <artifactId>proguard-base</artifactId>
                       <version>6.2.2</version>
                   </dependency>
               </dependencies>
           </plugin>

When using it, import the contents of the plugin tag in the above pom file into your own pom file, and replace the specific package name with your own. There are specific configuration notes. The main difficulty in the use process is the degree to which each package can be confused. It is best to conduct experiments to verify it when the specific situation requires it. Let me explain my confusion configuration:

-keep class !com.example.** { *; } is to confuse the classes under this package For the three packages of controller, service and scheduled task, the degree of obfuscation I use is not to confuse the class name, but to attribute and method To confuse dao, pojo, dto, and configuration packages, I don't confuse them. The above configuration is the maximum degree of confusion that I can find after trying again and again, otherwise an error will be reported. Note that in the proguard-maven-plugin, the class name, attributes, and methods are all confused by default, so if they are all confused, you don't need to configure this package. My personal perception is that the degree of confusion is mainly due to the fact that many classes are managed by spring, so it is best not to confuse the class names of these spring beans and the injected objects (managed by spring), otherwise spring cannot recognize and manage them. The other is the DAO class. If it is a type of MySQL that is mapped through Mapper's XML file, it is best not to confuse it, otherwise DAO cannot find the corresponding SQL statement. Others such as Hbase can be queried through code, and readers can try to confuse it. Some toolkits can also be obfuscated, and readers can try to obfuscate to that extent.

After completing the above configuration, you can execute the maven command to package. Finally, a jar package of your own project and a jar package of classes-pg.jar will be generated in the target directory. The jar package of your project is a jar package without obfuscated code. The content in the classes-pg.jar package is the real obfuscated code. Open the jar package of the project with winrar (remember not to decompress it if you are hungry, otherwise the jar package cannot run), enter the classes directory, and put the classes-pg The content in .jar (excluding the META-INF folder) can be copied to the classes directory of the jar package of the project, so that the jar package of the final project is the jar package after code obfuscation, and readers can decompile and observe by themselves Take a look at the effect of code obfuscation. If an error is reported after startup, the reader can modify the obfuscated class according to the error message. In addition, there is a blog here that is written in great detail, and readers can also take a look at the address of the blog post . If the content of the error is a class name conflict, you can try adding the following code to the startup class:


public static class CustomGenerator implements BeanNameGenerator {
    
    
		 
        @Override
        public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
    
    
            return definition.getBeanClassName();
        }

Add the package name before each class name, so that there will be basically no conflicts. At this point, the code obfuscation is complete, and we can communicate with each other if there are problems.

Guess you like

Origin blog.csdn.net/qq_45699784/article/details/125764225