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

打印 上一主题 下一主题

主题 883|帖子 883|积分 2649

项目背景

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

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

  • 下载最新发行版到本地,执行maven install
  • 工程项目配置maven plugin ,详细配置见在线文档
  1. <build>
  2.    <plugins>
  3.       <plugin>
  4.         <groupId>com.code2roc</groupId>
  5.         <artifactId>xhood</artifactId>
  6.         <version>1.0.0</version>
  7.         <executions>
  8.                 <execution>
  9.                <goals>
  10.                   <goal>obscure</goal>
  11.                </goals>
  12.                <phase>compile</phase>
  13.              </execution>
  14.          </executions>
  15.          <configuration>
  16.             
  17.              <packageName>com.xxx.xxx</packageName>
  18.             
  19.               <obscureIgnoreClasss>com.xxx.xxx.Application</obscureIgnoreClasss>
  20.          </configuration>
  21.        </plugin>
  22.    </plugins>
  23. </build>
复制代码
方案设计

我们首先要清除代码混淆要实现什么,就是将原代码名称结构和内容使用一系列的规则码替换
达到阅读困难,理解困难,恢复困难的作用
混淆的事项包括方法,成员变量,临时变量,方法参数,常量,类,包,枚举
这些事项的混淆还需要遵循固定的顺序,因为事项之间还存在相互引用的情况
在完成结构混淆(类文件,包名)后,需要删除对应的原class文件
混淆前后的效果如下图所示


方案实现

pom引用
  1.                   <dependency>
  2.             <groupId>org.ow2.asm</groupId>
  3.             <artifactId>asm</artifactId>
  4.             <version>9.0</version>
  5.         </dependency>
  6.         <dependency>
  7.             <groupId>org.ow2.asm</groupId>
  8.             <artifactId>asm-commons</artifactId>
  9.             <version>9.0</version>
  10.         </dependency>
  11.         <dependency>
  12.             <groupId>org.ow2.asm</groupId>
  13.             <artifactId>asm-util</artifactId>
  14.             <version>9.0</version>
  15.         </dependency>
  16.         <dependency>
  17.             <groupId>org.ow2.asm</groupId>
  18.             <artifactId>asm-tree</artifactId>
  19.             <version>9.0</version>
  20.         </dependency>
  21.         <dependency>
  22.             <groupId>org.ow2.asm</groupId>
  23.             <artifactId>asm-analysis</artifactId>
  24.             <version>9.0</version>
  25.         </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表示
[code]    public static String getTakeName(String name, int takeLimit, HashMap typeMap) {        String obscureName = getObscureName(name);        if (takeLimit

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

没腿的鸟

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表