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

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

项目背景

因在公司负责基础框架的开发设计,所以针对框架源代码的保护工作比较重视,之前也加入了一系列保护措施

例如自定义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文件

混淆前后的效果如下图所示

方案实现

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<String, String> typeMap) {
   
   
        String obscureName = getObscureName(name);
        if (takeLimit <= 16) {
   
   
            obscureName = obscureName.substring(8, 24);
        }
        String takeName = obscureName.substring(0, takeLimit);
        if (typeMap.containsValue(takeName)) {
   
   
            takeName = getTakeName(name, takeLimit + 1, typeMap);
        }
        return takeName;
    }

注意事项

开发事项

在混淆过程中,需要针对不同的情况进行细节处理,举例如下

  • 混淆名称中有相同部分的优先排序替换长度最长的部分

例如方法名HandleMethod和Handle两部分,Handle对应的规则码为123,我先替换Handle部分变成了123Method和123,那么123Method这个方法混淆后就会定义错误

  • 临时变量和方法变量都会调用MethodVisitor的visitLocalVariable方法,需要区分

先定义ParamterAdapter继承MethodVisitor重写visitParameter记录方法变量

使用事项

在springboot项目中,我们需要进行一些配置避免导致项目无法运行或运行错误**

  • 所有需要通过接口返回的实体类需要忽略,例如数据库实体DO

  • 通过ConfigurationProperties映射的yml文件配置项类需要忽略

  • 通过类名/字段名反射调用的类需要忽略

  • 针对@Aspect注解切面进行了兼容,参照如下写法则混淆无影响

    PointCut注解/类需要指定全名,Around注解指定方法名

    @Aspect
    @Component
    public class RepeatSubmitAspect {
         
         
        /**
         * 切面点 指定注解
         */
        @Pointcut("@annotation(com.code2roc.fastboot.framework.submitlock.SubmitLock) " +
                "|| @within(com.code2roc.fastboot.framework.submitlock.SubmitLock)")
        public void repeatSubmitAspect() {
         
         
    
        }
    
        /**
         * 拦截方法指定为 repeatSubmitAspect
         */
        @Around("repeatSubmitAspect()")
        public Object around(ProceedingJoinPoint point) throws Throwable {
         
         
            return point.proceed();
        }
    }
    
目录
相关文章
|
1月前
|
监控 Java API
如何使用Java语言快速开发一套智慧工地系统
使用Java开发智慧工地系统,采用Spring Cloud微服务架构和前后端分离设计,结合MySQL、MongoDB数据库及RESTful API,集成人脸识别、视频监控、设备与环境监测等功能模块,运用Spark/Flink处理大数据,ECharts/AntV G2实现数据可视化,确保系统安全与性能,采用敏捷开发模式,提供详尽文档与用户培训,支持云部署与容器化管理,快速构建高效、灵活的智慧工地解决方案。
|
20天前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
38 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
8天前
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
55 13
|
13天前
|
算法 Java API
如何使用Java开发获得淘宝商品描述API接口?
本文详细介绍如何使用Java开发调用淘宝商品描述API接口,涵盖从注册淘宝开放平台账号、阅读平台规则、创建应用并申请接口权限,到安装开发工具、配置开发环境、获取访问令牌,以及具体的Java代码实现和注意事项。通过遵循这些步骤,开发者可以高效地获取商品详情、描述及图片等信息,为项目和业务增添价值。
46 10
|
24天前
|
Java
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
48 24
|
6天前
|
前端开发 Java 测试技术
java日常开发中如何写出优雅的好维护的代码
代码可读性太差,实际是给团队后续开发中埋坑,优化在平时,没有那个团队会说我专门给你一个月来优化之前的代码,所以在日常开发中就要多注意可读性问题,不要写出几天之后自己都看不懂的代码。
42 2
|
16天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
20天前
|
Java 编译器 数据库
Java 中的注解(Annotations):代码中的 “元数据” 魔法
Java注解是代码中的“元数据”标签,不直接参与业务逻辑,但在编译或运行时提供重要信息。本文介绍了注解的基础语法、内置注解的应用场景,以及如何自定义注解和结合AOP技术实现方法执行日志记录,展示了注解在提升代码质量、简化开发流程和增强程序功能方面的强大作用。
57 5
|
20天前
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
46 5
|
23天前
|
Java API 开发者
Java中的Lambda表达式:简洁代码的利器####
本文探讨了Java中Lambda表达式的概念、用途及其在简化代码和提高开发效率方面的显著作用。通过具体实例,展示了Lambda表达式如何在Java 8及更高版本中替代传统的匿名内部类,使代码更加简洁易读。文章还简要介绍了Lambda表达式的语法和常见用法,帮助开发者更好地理解和应用这一强大的工具。 ####
下一篇
DataWorks