• Spring Boot 2.x系列【27】应用篇之代码混淆


    有道无术,术尚可求,有术无道,止于术。

    本系列Spring Boot版本2.7.0

    概述

    代码混淆

    代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成难于阅读和理解的形式的行为。

    比如以下几种方式:

    • 将代码中的各种元素,如变量,函数,类的名字改写成无意义的名字。比如改写成单个字母,或是简短的无意义字母组合,甚至改写成“__”这样的符号,使得阅读的人无法根据名字猜测其用途。

    • 重写代码中的部分逻辑,将其变成功能上等价,但是更难理解的形式。比如将for循环改写成while循环,将循环改写成递归,精简中间变量。

    • 打乱代码的格式。比如删除空格,将多行代码挤到一行中,或者将一行代码断成多行等等。

    也会带来一些问题:

    • 被混淆的代码难于理解,因此调试以及除错也变得困难起来。开发人员通常需要保留原始的未混淆的代码用于调试。
    • 对于支持反射的语言,代码混淆有可能与反射发生冲突。
    • 代码混淆并不能真正阻止反向工程,只能增大其难度。
    • 对于对安全性要求很高的场合,仅仅使用代码混淆并不能保证源代码的安全。

    由于跨平台的需要,Java字节码中包括了很多源代码信息,如变量名、方法名,并且通过这些名称来访问变量和方法,这些符号带有许多语义信息,很容易被反编译成Java源代码。为了防止这种现象,我们可以使用Java混淆器Java字节码进行混淆。

    混淆作用不仅仅是保护代码,它也有精简编译后程序大小的作用。由于以上介绍的缩短变量和函数名以及丢失部分信息的原因, 编译后jar文件体积大约能减少25% 。

    ProGuard

    github地址
    官网地址

    ProGuard 是一个开源的Java类文件压缩、优化、混淆和预验证工具。ProGuard 可以将JAVA 程序变得更小、更快,并且可以增加代码被反编译的难度。

    主要功能有:

    • 检测并删除未使用的类、字段、方法和属性
    • 优化字节码并删除未使用的指令
    • 混淆使用无意义的短名称重命名的类、字段和方法
    • 预验证信息添加到类中

    在这里插入图片描述
    工作原理:

    • 首先读取输入的 jars(或 aars、wars、ears、zip、apks 或目录)
    • 进行压缩、优化、混淆和预验证
    • 将处理后的结果写入一个或多个输出 jar(或 aars、wars、ears、zip、apks 或目录)

    使用Maven 插件

    官方只提供了Gradle 插件,Maven只有开源的一些实现,还不保证起功能的完整性。。。
    在这里插入图片描述
    首先找一个Spring Boot 项目,在根目录添加directory.txt文件配置混淆字典,用于替换类名、变量名等,默认是单个字母,每行保持唯一性,内容如下:

    0000O000000o
    000O00000Oo
    000O00000o0
    000O00000o
    000O00000oO
    
    • 1
    • 2
    • 3
    • 4
    • 5

    添加配置项文件proguard.cfg放在项目根目录,也就是混淆的各种配置项:

    # 添加字典
    -obfuscationdictionary 'directory.txt'
    -classobfuscationdictionary 'directory.txt'
    -packageobfuscationdictionary 'directory.txt'
    
    # 文档 https://www.guardsquare.com/manual/home#entry-points
    
    #指定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 cn.herodotus.dante.gateway.GatewayApplication {
            public static void main(java.lang.String[]);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    添加Maven 混淆、打包插件:

      <build>
            <plugins>
                
                <plugin>
                    <groupId>com.github.wvengengroupId>
                    <artifactId>proguard-maven-pluginartifactId>
                    <version>2.6.0version>
                    <executions>
                        
                        <execution>
                            <phase>packagephase>
                            <goals>
                                <goal>proguardgoal>
                            goals>
                        execution>
                    executions>
                    <configuration>
                        
                        <injar>${project.build.finalName}.jarinjar>
                        
                        <outjar>${project.build.finalName}.jaroutjar>
                        
                        <obfuscate>trueobfuscate>
                        
                        <proguardInclude>${project.basedir}/proguard.cfgproguardInclude>
                        
                        <libs>
                            <lib>${java.home}/lib/rt.jarlib>
                            <lib>${java.home}/lib/jce.jarlib>
                            <lib>${java.home}/lib/jsse.jarlib>
                        libs>
                        
                        <inLibsFilter>!META-INF/**,!META-INF/versions/9/**.classinLibsFilter>
                        
                        <outputDirectory>${project.basedir}/targetoutputDirectory>
                        
                        <options>
                            
                        options>
                    configuration>
                plugin>
                
                <plugin>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-maven-pluginartifactId>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackagegoal>
                            goals>
                        execution>
                    executions>
                plugin>
            plugins>
        build>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    点击package进行打包,成功打包:
    在这里插入图片描述
    查看JAR 包,发现类名被混淆:
    在这里插入图片描述
    将Class 文件复制到target目录下查看,代码中也有不少混淆:
    在这里插入图片描述
    启动混淆后的JAR 包,能正常启动:
    在这里插入图片描述

    直接使用工具混淆

    下载
    在这里插入图片描述
    解压并启动:
    在这里插入图片描述
    可以在控制台对JAR 包进行混淆:
    在这里插入图片描述

    在混淆Spring Boot JAR 包时,发现ProGuard 要求 jar 文件中类文件的名称直接对应于类的名称,BOOT-INF/classes这样的前缀识别不了,无法混淆。。。所以就懒得再试了。

    需要解决办法的可以研究下stackoverflow

  • 相关阅读:
    SSM+网上订餐系统 毕业设计-附源码221558
    数字人的未来:数字人对话系统 Linly-Talker + 克隆语音 GPT-SoVITS
    Linux 安全 - LSM源码分析
    【每日一题Day346】LC1488避免洪水泛滥 | 贪心+哈希表
    【Spatial-Temporal Action Localization(五)】论文阅读2020年
    Java面向对象编程之封装
    【新书推荐】AI时代,当程序员遇到ChatGPT,开发效率飞起来!
    vim的配置及基础使用
    C++ STL & 标准库
    使用vue自定义实现Tree组件和拖拽功能
  • 原文地址:https://blog.csdn.net/qq_43437874/article/details/127964743