项目开发混淆从初识到理解

项目开发流程系列

  1. 项目开发混淆从初识到理解
  2. 项目开发代码分支管理

博客创建时间:2022.08.28
博客更新时间:2023.03.29

以Android studio build=7.0.0,SDKVersion 31来分析讲解。如图文和网上其他资料不一致,可能是别的资料版本较低而已。


前言

Java 是一种跨平台、解释型语言,Java 源代码编译成的class文件中有大量包含语义的变量名、方法名的信息,很容易被反编译为Java 源代码。

为了项目的软件安全,提高对手的逆向破解难度,应该对项目进行合理的代码混淆,尽量少的keep类,保持代码正常运行的情况下编译生成的代码是无序随机的。

混淆编译器

Android的代码混淆编译器有两种

  • ProGuard:一个通用的 Java 字节码优化工具
  • R8:ProGuard 的继承者,专为 Android 设计,编译性能和编译产物更优秀

在Android Gradle 4.0.0以后基本使用的是R8混淆编译器。

// 显式启用 R8
android.enableR8 = true
// 只对 Android Library module 停用 R8 编译器
android.enableR8.libraries = false
// 对所有 module 停用 R8 编译器
android.enableR8 = false

其他关键词:D8 & DEX


混淆功能

ProGuard 与 R8 都提供了混淆编辑的四大功能:

  • 压缩(shrinker):也称摇树优化,tree shaking,从「应用及依赖项」 中移除「未使用」 的类、方法和字段,有助于规避 64 方法数的瓶颈。

    zipAlignEnabled true
    // 移除无用的resource
    shrinkResources true
    
  • 优化(optimizer):通过代码 「分析」 移除更多未使用的代码,甚至重写代码

  • 混淆(obfuscator):使用无意义的简短名称 「重命名」 类/方法/字段,增加逆向难度

  • 预校验(preverifier):对于面向 Java 6 或者 Java 7 JVM 的 class 文件,编译时可以把 「预校验信息」 添加到类文件中(StackMap 和 StackMapTable属性),从而加快类加载效率。预校验对于 Java 7 JVM 来说是必须的,但是对于 Android 平台无效。


编译流程

1. ProGuard编译流程

  • Javac编译器将java编译成.class文件
  • ProGuard 对 .class 文件执行代码压缩、优化与混淆
  • D8 编译器执行脱糖,并将 .class 文件转换为 .dex文件
    在这里插入图片描述
    2. R8编译流程
  • R8 对 .class 文件执行代码压缩、优化与混淆
  • D8 编译器执行脱糖,并将 .class 文件转换为 .dex文件
    在这里插入图片描述
    R8 将脱糖(Desugar)、压缩、优化、混淆和 dex(D8 编译器)整合到一个步骤
    module编译流程
    App module与Library module的编译规则如下:
  • 编译时会从上到下依次对各层 Library Module进行编译,最底层的Module会最先被编译为aar。然后上一层编译时会将依赖Module输出的aar/ jar文件解压到模块的build 中相应的文件夹中
  • App Module 这一层汇总了全部的 aar 文件后,才真正开始编译操作
  • 后编译的 Module 会覆盖之前编译的 Module 中的同名资源
    在这里插入图片描述

R8与ProGuard 区别

  1. R8 支持所有现有 ProGuard 规则文件
  2. ProGuard 可用于 Java 项目,而 R8 专为 Android 项目设计
  3. R8 将脱糖(Desugar)、压缩、优化、混淆和 dex(D8 编译器)整合到「一个步骤」中,显著提高了编译性能

规则文件

规则文件也称混淆保留规则文件,文件中不仅可以定义绝大多数的混淆规则,也可以定义代码压缩、优化、预校验规则。R8延续了 ProGuard的规则,其混淆规则文件写法一致。

混淆规则文件有两种:consumer-rules.pro和proguard-rules.pro
consumer-rules.pro:给上层依赖使用的
proguard-rules.pro:自身打包aar时使用
在这里插入图片描述

  • consumerProguardFiles会将混淆规则输出为proguard.txt文件,并打包进 aar 文件
  • App Module 会使用 aar 文件中的proguard.txt汇总为最终的混淆规则,最后混淆规则打包apk

在规则文档中添加以下配置,输出编译项目时应用的所有规则的完整报告:

-printconfiguration build/intermediates/proguard-files/full-config.txt

注意:

  1. 混淆的开启由混淆开启由 App Module 决定, 与Lib Module 无关。即使Lib Module开启了混淆,但是App未开启混淆,实际打包Apk并未混淆。
  2. 混淆规则以 App Module 中的混淆规则文件为准,对同一文件进行的混淆配置,App module 中的混淆规则会覆盖Lib Module中的混淆规则
  3. 不同的module 中的混淆文件应该写入到每个module的规则文档中,这样一旦移除某个Lib,不要去修改混淆规则文件,否则遗留下的规则文件虽然不会运行错误,却影响编译效率

混淆使用

    buildTypes {
        debug {
            signingConfig signingConfigs.release
            // 混淆
            minifyEnabled false
            // 混淆配置
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        
        release {
            signingConfig signingConfigs.release
            // 混淆
            minifyEnabled true
//            debuggable true
            // Zipalign优化
            zipAlignEnabled true
            // 移除无用的resource
            shrinkResources true
            // 混淆配置
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        ....
    }

注意:
R8 还是 ProGuard,默认不会启用压缩、优化和混淆功能。需要手动配置。这样做的目的是:编译时任务会增加编译时间。测试版本不需要进行,只需发布版本开启即可。

当关闭混淆 minifyEnabled false时,压缩和优化是不可以开启的即。

minifyEnabled false
zipAlignEnabled false
shrinkResources false

在混淆文件中也可以配置如下

-dontshrink//关闭压缩,默认是开启压缩的,Android中建议开启
-dontoptimize
//不进行优化,默认优化关闭。ProGuard混淆模式下建议关闭,因为Dex对ProGuard优化的代码兼容不太好
// R8不能关闭优化,也不允许修改优化的行为。R8会忽略修改默认优化行为的规则,设置关闭无效

// 关闭混淆,默认是开启的(建议在开发版本关闭混淆)
-dontobfuscate
// 关闭预校验(对 Android平台无效,建议关闭,提高编译效率)
-dontpreverify

混淆规则一般配置在Lib module中不生效,所以想要生效需要使用到consumer-rules.pro

android{
    defaultConfig{
        consumerProguardFiles 'consumer-rules.pro'
    }
}

规则整理

https://gitee.com/luofaxin/CodeAanalysis/tree/master 中已为大家总结了常见的混淆规则文件"通用规则.pro"和常见的第三方库混淆规则文件"第三方库规则.pro",需要的客官可以将两个文件合并在一起使用。
在这里插入图片描述

网络请求类保持keep
对于网络请求的request类和网络响应respond类应该保持混淆。网络请求类应该统一集中放在某一package中,例如:

@POST("XXXXX/login")
Observable<LogInRespond> mobileLogin(@Body MobileLoginRequestBody userBean);

请求类LogInRespond和MobileLoginRequestBody类应该保持keep,否则请求失败或者响应数据接收失败,特别是对于Retrofit对于网络相应类自动转Gson而言。应混淆配置

-keep class com.xxx.xxxxRespond.**{*;}
-keep class com.xxx.xxxxRequest.**{*;}

总结

  • 应用场景:ProGuard 是Java 字节码优化工具、R8 是专为 Android 设计、编译性能和编译产物更优秀;
  • 功能说明:ProGuard 与 R8 都提供了四大功能:压缩、优化、混淆和预校验
  • 编译流程:ProGuard主要是对 .class 文件执行代码压缩、优化与混淆,再由 D8 编译器执行脱糖并转换为 .dex 文件。R8 将压缩、优化、混淆、脱糖和 dex 整合为一个步骤。
  • 规则文件来源:Android Gradle 插件、AAPT2、Module;
  • 混淆规则:以 App Module 中的混淆规则文件为准,使用 consumer-rules.pro 文件可以设置 Lib Module 专属混淆规则。

相关链接

  1. 项目开发混淆从初识到理解
  2. 项目开发代码分支管理

扩展链接:

  1. Material Design UI方案使用讲解
  2. Material TextInputLayout使用详解

博客书写不易,您的点赞收藏是我前进的动力,千万别忘记点赞、 收藏 ^ _ ^ !

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值