android反混淆,android 打包 混淆配置_玩转代码混淆工具:ProGuard

 2023-09-23 阅读 20 评论 0

摘要:维基百科对ProGuard的介绍是:ProGuard是一个压缩(shrink),优化(optimize)与混淆(Obfuscate)Java代码的开源命令行工具。也就是说混淆只是ProGuard的其中一个功能,本文也只介绍它的混淆功能。About ProGuardProGuard能通过重命名类名,字段名ÿ

维基百科对ProGuard的介绍是:ProGuard是一个压缩(shrink),优化(optimize)与混淆(Obfuscate)Java代码的开源命令行工具。也就是说混淆只是ProGuard的其中一个功能,本文也只介绍它的混淆功能。

1e46592ffe8a828839d5a66315bdba27.png
About ProGuard

ProGuard能通过重命名类名,字段名,方法名为一些没有意义的名字来混淆Java和Android程序,从而使逆向工程更难。并且ProGuard已经是Android SDK的一部分了,当然本文只讲如何混淆Java代码。

用法

本文介绍两种方式:使用UI工具 和 Maven集成。

  • android反混淆、UI工具

这个比较简单,先从https://sourceforge.net/projects/proguard/下载最新版的ProGuard,然后解压,到bin目录下找到proguardgui.bat双击即可,程序运行后的界面如下:

d10970cbee03bc948e3e7cee3c66496b.png
ProGuard

Input/Output中,Add input选择要混淆的JAR包(ProGuard不支持混淆单个class文件,但是我们可以通过命令把一个或多个class打成jar包:jar cvf Test.jar com/afei/test/*.class),Add output指定输出文件名。Obfuscation中有很多混淆自定义规则,根据需求自行调整,ShrinkingOptimization视情况而定是否需要勾选(如果只是混淆代码,则建议关闭)。最后选择Process,点击右下角的Process!即可。如下图所示,User.java混淆前后对比,我们发现类名,属性名都被重命名为一些毫无意义的命名了:

bad7db3901e4820b34742ce93201fbe9.png
image.png
  • Maven集成

jar包混淆。通过maven集成方式从而在maven打包阶段就达到了混淆的目。集成方式非常简单,只需修改POM,添加如下一些代码即可:

-- 添加依赖
<dependency>
    <groupId>net.sf.proguardgroupId>
    <artifactId>proguard-baseartifactId>
    <version>5.3.3version>
dependency>

-- 添加插件
<plugin>
    <groupId>com.github.wvengengroupId>
    <artifactId>proguard-maven-pluginartifactId>
    <version>2.0.15-SNAPSHOTversion>
    <executions>
        <execution>
            <phase>packagephase>
            <goals><goal>proguardgoal>goals>
        execution>
    executions>
    <configuration>
        <proguardVersion>5.3.3proguardVersion>
        <injar>${project.build.finalName}.jarinjar>
        <outjar>${project.build.finalName}.jaroutjar>
        <obfuscate>trueobfuscate>
        <libs>
            <lib>${java.home}/lib/rt.jarlib>
            <lib>${java.home}/lib/jce.jarlib>
        libs>
        <options>
            
            <option>-dontshrinkoption>
            
            <option>-dontoptimizeoption>
            <option>-keepnames interface **option>          
            <option>-keepparameternamesoption>
            <option>-keeppackagenamesoption>                    
        options>
    configuration>
plugin>

集成后执行maven package打包,就会看到target目录下会多出一些命名中带有proguard的文件,例如afei-demo-1.0.0-SNAPSHOT_proguard_base.jarproguard_map.txtproguard_seed.txt等,并且每个目录下的类名都被重命名为a, b, c等毫无意义的类名:

ef1f0bf5d427f35872f3c932682f93ed.png
confusion target

  • 配置说明

maven集成ProGuard后,可自定义的地方主要集中在options标签中,一些option说明如下:

-dontshrink
shrink是ProGuard几大核心功能之一,配置了dontshrink表示不需要压缩,即关闭shrink功能

-dontoptimize
optimize也是ProGuard几大核心功能之一,配置了dontoptimize表示不需要优化,即关闭soptimize功能

-keeppackagenames
是否不混淆包名,如果配置了该项,那么包名会完整保留。如果没有配置,那么除了根目录(com.afei.test),子目录(例如bean, controller, impl等)都会被混淆。

-keepattributes SourceFile,LineNumberTable
抛出异常时保留代码行号,在异常分析中可以方便定位

-dontusemixedcaseclassnames
这个是给Windows系统用户的,因为ProGuard假定使用的操作系统是能区分大小写名,但是Windows不是这样的操作系统,所以必须为ProGuard指定-dontusemixedcaseclassnames选项

-keep class com.afei.test.Application
Application这个类名不混淆,但是方法名,属性名,以及方法中的内容还是会混淆;

-keep class com.afei.test.Application { *; }
Application这个类的类名,方法名,属性名完全保留不做任何混淆,但是方法体内的内容还是会混淆。

-keepnames interface **
所有接口类命名不做任何混淆,但是接口里的属性和方法会还是会被混淆;

-keepnames enum **
枚举类名不做任何混淆,但是枚举的值会混淆;

-keep public class * implements java.io.Serializable{
    public *;
    protected *;
    private *;
}
保留实现了Serializable接口类中的公有的,友好的,私有的成员(属性和方法),这个配置主要是对应实体类的配置。

-keep class com.afei.test.dao.** { *; }
dao层的类名和方法都不混淆;

-keepnames
用法如下,保留Application的类名和main方法不混淆:
-keepnames public class com.afei.test.Application {public static void main(java.lang.String[]);
    }

用法如下,保留FtpConfigSaveJob的类名和execute方法不混淆:
-keepclasseswithmembers public class com.afei.test.job.FtpConfigSaveJob {
        com.xxl.job.core.biz.model.ReturnT execute(java.lang.String);
    }

c代码混淆、配置中符号的含义:

!:感叹号表示除这个以外,例如-keep class !com.afei.test.Application表示出了Application.java,其他的类名都不混淆

遇到的问题

通过使用ProGuard混淆springboot项目的过程,笔者遇到了下面这些问题:

  1. 工程目录要清晰,比如VO, DTO, PO存放目录要统一,自定义Exception子类存放目录等。因为这些类名,甚至属性名都不能混淆,VO属性名与接口定义有关,PO与Mapper.xml有关;

  2. 与序列化反序列相关的对象也不会混淆,与第三方约定的接口相关的模型也不能混淆等;

  3. 代码混淆专家,xxl-job相关类不能混淆,方法申明必须是execute(String),笔者相信还会有其他的框架也会有类似的约定和限制;

  4. springboot的Application.java也不能混淆,因为main方法不能被重命名,Application.java类名最好也不要被重命名,因为maven中有配;置com.afei.test.Application

  5. 很多注解不能混淆

  6. … …

android破解混淆。如下图所示,是默认配置混淆后的Application.java,很明显,这样的springboot工程是无法启动的,因为main主方法被混淆为a了:

8a562c648d0569860953fb70ae0eb186.png
混淆后的Application.java

另外,由于ProGuard默认会将每个子目录下的类都重命名为a, b, c。例如com.afei.test.a下的类会被重命名为a.class,b.class,c.class,而com.afei.test.b下的类也会被重命名为a.class,b.class,c.class。这样就会导致spring初始化加载bean时抛出下面的异常:

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'b' for bean class [com.afei.test.config.b] conflicts with existing, non-compatible bean definition of same name and class [com.afei.test.common.b]
        at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:345)
        at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:283)
        at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:135)
        at 

ProGuard总结

通过上面的分析可知,ProGuard或者类似原理的代码混淆工具的限制太多太多,对工程目录有严格的要求,而且很多地方需要明确配置不允许混淆,以后有新增的代码,还需要评估是否需要申明不需要混淆。这样分析下来后发现,如果想要使用ProGuard混淆服务端的代码,最后几乎只能混淆方法体内的内容。

XJar

针对ProGuard或者同原理方案的缺陷,笔者找到了另一种方案:XJar。

混淆js代码,官方介绍XJar是Spring Boot JAR 安全加密运行工具,同时支持的原生JAR。基于对JAR包内资源的加密以及拓展ClassLoader来构建的一套程序加密启动,动态解密运行的方案,避免源码泄露或反编译。功能特性如下:

  • 无需侵入代码,只需要把编译好的JAR包通过工具加密即可。

  • 完全内存解密,杜绝源码以及字节码泄露或反编译。

  • 支持所有JDK内置加解密算法。

  • c代码混淆技术。可选择需要加解密的字节码或其他资源文件,避免计算资源浪费。

详细的介绍和用法请参考XJar GitHub主页: https://github.com/core-lib/xjar,介绍的非常详细。

cbfe024eb5b5f12e7ab4bf9c1a185fbb.png

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/2/89182.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息