聊聊如何进行代码混淆

前言

什么是代码混淆

代码混淆,是指将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为。

代码混淆常见手段

1、名称混淆

将有意义的类,字段、方法名称更改为无意义的字符串。生成的新名称越短,字节代码越小。在名称混淆的字节代码中,包,类,字段和方法名称已重命名,并且永远不能恢复原始名称。不幸的是,控制流程仍然清晰可见。故而需要流混淆

2、流混淆

用于if, switch, while,for等关键字,对字节码进行细微的修改,模糊控制流,而不改变代码在运行时的行为。通常情况下,选择和循环等逻辑构造会被更改,因此它们不再具有直接等效的Java源代码。流模糊的字节码通常强制反编译器将一系列标签和非法的goto语句插入到它们生成的源代码中。源代码有时会因为反编译错误而变得更加模糊

其他

异常混淆、字符串加密混淆、引用混淆等

代码混淆的作用

不仅仅是保护代码,它也有精简编译后程序大小的作用。由于缩短变量和函数名以及丢失部分信息的原因, 编译后jar文件体积大约能减少25% ,这对当前费用较贵的无线网络传输是有一定意义的

代码混淆可能带来的问题

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

常用的混淆工具

1、yGuard

yGuard是一款免费的Java混淆器(非开源),它有Java和.NET两个版本。yGuard 完全免费,基于 Ant 任务运行,提供高可配置的混淆规则。

官网地址:https://www.yworks.com/products/yguard

2、proguard

proguard是一个免费的 Java类文件的压缩,优化,混肴器。它删除没有用的类,字段,方法与属性。使字节码最大程度地优化,使用简短且无意义的名字来重命名类、字段和方法

官网地址:https://www.guardsquare.com/en/products/proguard

3、allatori

第二代Java混淆器。所谓第二代混淆器,不仅仅能进行字段混淆,还能实现流混淆。

Allatori具有以下几种保护方式:命名混淆,流混淆,调试信息混淆,字符串编码,以及水印技术。对于教育和非商业项目来说这个混淆器是免费的。支持war和jar格式,支持对需要混淆代码的应用程序添加有效日期。

官网地址:http://www.allatori.com/

本文主要介绍基于allatori如何进行混淆

allatori入门

因为allatori没有提供maven GAV坐标,因此需要去官网下载jar。

1、下载的jar可以放到项目可以读到的地方。比如项目根目录,形如下图

聊聊如何进行代码混淆_第1张图片

2、编写混淆配置allatori.xml

示例配置:





    
   
        
    
      
      
      
      
      

    
    
   

    
    
        
    

    
        
        
        
        
        
        
    

    
    

详细配置内容可以查看如下链接
http://www.allatori.com/doc.html

其实官网的文档中,有贴一个更全的示例,基本上参照官网配置即可。

官网示例配置


    
        
        

        
    

    
        
        
        
        
        
        
    

    
        
        
        
        
            
            
        
        
            
            
            
        
    

    

    

    
    
    
    

    
    
    
    
    

    
    
    

    
    
    

    
    
    
    
    

    
    

    
    
    
    
    
    
    
    
    
    
    
    

    
    
3、pom.xml加入拷贝和运行allatori需要的插件
 

        

            
            
                org.apache.maven.plugins
                maven-resources-plugin
                2.6
                
                    
                        copy-and-filter-allatori-config
                        package
                        
                            copy-resources
                        
                        
                            true
                            ${basedir}/target
                            
                                
                                    ${basedir}/allatori
                                    
                                        allatori.xml
                                        proguard.txt
                                    
                                    true
                                
                            
                        
                    
                
            

            
            
                org.codehaus.mojo
                exec-maven-plugin
                1.2.1
                
                    
                        run-allatori
                        package
                        
                            exec
                        
                    
                
                
                    java
                    
                        -Xms128m
                        -Xmx512m
                        -jar

                        
                        ${basedir}/allatori/lib/allatori.jar
                        ${basedir}/target/allatori.xml
                    
                
            

        

    

4、运行mvn clean package

因为我混淆前后的jar名称都一样,所以混淆的jar会覆盖未混淆的jar,我们可以通过idea看下混淆后的代码长啥样
聊聊如何进行代码混淆_第2张图片

@Aspect
public class 0o0o0o0o0o0o0o0o0o0o {
    @Autowired
    private LicenseProperties ALLATORIxDEMO;

    public _o0o0o0o0o0o0o0o0o0o/* $FF was: 0o0o0o0o0o0o0o0o0o0o*/() {
        if ((new Date()).after(new Date(1610726400305L))) {
            throw new Throwable("EXPIRED!");
        }
    }

    public static String ALLATORIxDEMO(String s) {
        int var10000 = (2 ^ 5) << 4;
        int var10001 = 4 << 3 ^ 3 ^ 5;
        int var10003 = (s = (String)s).length();
        char[] var10004 = new char[var10003];
        boolean var10006 = true;
        int var3;
        int var10002 = var3 = var10003 - 1;
        char[] var1 = var10004;
        byte var4 = 2;
        var10001 = var10000;
        var10000 = var10002;

        for(int var2 = var10001; var10000 >= 0; var10000 = var3) {
            var10001 = var3;
            char var5 = s.charAt(var3);
            --var3;
            var1[var10001] = (char)(var5 ^ var2);
            if (var3 < 0) {
                break;
            }

            var10002 = var3--;
            var1[var10002] = (char)(s.charAt(var10002) ^ var4);
        }

        return new String(var1);
    }

    @Around("@annotation(licenseCheck)")
    public Object ALLATORIxDEMO(ProceedingJoinPoint pjp, LicenseCheck licenseCheck) {
        try {
            com.github.lybgeek.0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o.0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o.0o0o0o0o0o0o0o0o0o0o.ALLATORIxDEMO(this.ALLATORIxDEMO.getCode());
            return pjp.proceed();
        } catch (Throwable var4) {
            throw var4;
        }
    }
}

从代码上看,估计连代码的亲妈都很难认出这个代码

总结

自从知道allatori后,我基本上都不用proguard。不过在用混淆工具也有一些细节点,比如用到的开源包,就不要对开源包进行混淆了,不然可能会导致项目报错,还有一些对外提供的API,最好也不要混淆。allatori是一个值得推荐的混淆工具,因为真的开箱即用。他提供了很多示例
聊聊如何进行代码混淆_第3张图片
因为allatori没有提供插件,其实我们在使用的时候,可以把他制作成一个maven插件。如何制作一个maven插件,可以参考我之前的文章
聊聊如何自定义实现maven插件

其实在springboot项目使用allatori,还遇到一点小坑。这个小坑是啥,留个悬念。下篇文章水一篇。如果上面的介绍的混淆工具,不能满足需求,可以查看如下链接
https://www.oschina.net/project/tag/167/code-confusion
。该链接提供了很多混淆工具介绍

demo链接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-proguard

你可能感兴趣的:(聊聊如何进行代码混淆)