没腿的鸟 发表于 2023-11-30 02:38:48

从零开发基于ASM字节码的Java代码混淆插件XHood

项目背景

因在公司负责基础框架的开发设计,所以针对框架源代码的保护工作比较重视,之前也加入了一系列保护措施
例如自定义classloader加密保护,授权license保护等,但都是防君子不防小人,安全等级还比较低
经过调研各类加密混淆措施后,决定自研混淆插件,自主可控,能够贴合实际情况进行定制化,达到框架升级后使用零感知,零影响。
快速开始

项目地址:https://gitee.com/code2roc/xhood
在线文档:https://code2roc.gitee.io/xhood/#/

[*]下载最新发行版到本地,执行maven install
[*]工程项目配置maven plugin ,详细配置见在线文档
<build>
   <plugins>
      <plugin>
      <groupId>com.code2roc</groupId>
      <artifactId>xhood</artifactId>
      <version>1.0.0</version>
      <executions>
              <execution>
               <goals>
                  <goal>obscure</goal>
               </goals>
               <phase>compile</phase>
             </execution>
         </executions>
         <configuration>
            
             <packageName>com.xxx.xxx</packageName>
            
            <obscureIgnoreClasss>com.xxx.xxx.Application</obscureIgnoreClasss>
         </configuration>
       </plugin>
   </plugins>
</build>方案设计

我们首先要清除代码混淆要实现什么,就是将原代码名称结构和内容使用一系列的规则码替换
达到阅读困难,理解困难,恢复困难的作用
混淆的事项包括方法,成员变量,临时变量,方法参数,常量,类,包,枚举
这些事项的混淆还需要遵循固定的顺序,因为事项之间还存在相互引用的情况
在完成结构混淆(类文件,包名)后,需要删除对应的原class文件
混淆前后的效果如下图所示
https://code2roc-blog.oss-cn-beijing.aliyuncs.com/blogimage/%E4%BB%8E%E9%9B%B6%E5%BC%80%E5%8F%91Java%E6%B7%B7%E6%B7%86%E5%8A%A0%E5%AF%86Maven%E6%8F%92%E4%BB%B6XHood/code_ori.png
https://code2roc-blog.oss-cn-beijing.aliyuncs.com/blogimage/%E4%BB%8E%E9%9B%B6%E5%BC%80%E5%8F%91Java%E6%B7%B7%E6%B7%86%E5%8A%A0%E5%AF%86Maven%E6%8F%92%E4%BB%B6XHood/code_obscure.png
方案实现

pom引用

                <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm</artifactId>
            <version>9.0</version>
      </dependency>
      <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm-commons</artifactId>
            <version>9.0</version>
      </dependency>
      <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm-util</artifactId>
            <version>9.0</version>
      </dependency>
      <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm-tree</artifactId>
            <version>9.0</version>
      </dependency>
      <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm-analysis</artifactId>
            <version>9.0</version>
      </dependency>名称混淆

名称混淆指的是把类名,方法名,参数名,变量名等定义的名称进行规则码替换,以混淆方法名为例

[*]混淆方法定义
自定义ClassVisitor重写visit方法
过滤枚举类的方法
过滤main方法,过滤lambda表达式方法,过滤构造函数方法
过滤非混淆范围内接口的实现方法
过滤非混淆范围内父类的重写方法
[*]混淆方法调用
自定义MethodVisitor重写visitMethodInsn,visitInvokeDynamicInsn方法
visitMethodInsn修混淆方法定义中的方法
visitInvokeDynamicInsn修改接口的实现方法和父类的重写方法(混淆范围内且混淆方法定义中的方法)
结构混淆

结构混淆指的是修改类名,包名时对实体class文件和文件夹的重命名,以混淆类名为例

[*]混淆类定义
自定义ClassVisitor重写visit方法
过滤非混淆范围内的class
重写visitSource,visitField,visitMethod,visitInnerClass,visitOuterClass等方法
[*]混淆类定义调用
自定义MethodVisitor重写visitMethodInsn,visitFieldInsn,visitFrame,visitInvokeDynamicInsn等方法
[*]混淆类重命名
定义ClassWriter获取class文件byte数组重新写入文件
注解混淆

注解的混淆比较特殊,需要继承AnnotationVisitor类来重写visit方法实现
针对注解中有枚举需要重写visitEnum方法
针对嵌套注解需要重写visitAnnotation方法
针对注解有参数有数组的,需要重写visitArray方法
visitAnnotation和visitArray方法需要返回AnnotationVisitor对象,调用super方法后返回自定义AnnotationVisitor对象递归处理即可
混淆规则

无论混淆哪一部分,我们总是要根据一个名称例如abc混淆后得到一个固定的规则码例如123
这时候我们会想到md5这种固定输入对应固定输出的信息摘要算法
md5内容太长,我们需要截取某几位进行简化
简化后的规则码在待混淆内容越多时越容易碰撞,需要需要动态调整,简单递归即可,最坏结果就是完整的md5表示
    public static String getTakeName(String name, int takeLimit, HashMap typeMap) {      String obscureName = getObscureName(name);      if (takeLimit
页: [1]
查看完整版本: 从零开发基于ASM字节码的Java代码混淆插件XHood