由浅入深 Android 混淆实战

许久没有做混淆相关的工作, 以前存储的知识遗忘得差不多了。停留在很多人的记忆里面混淆还不简单吗?不就是 -keep。这样说也没错,但是要把混淆做得精细精准还是不简单的,今天就一文带你全而透。

混淆的作用

我们为什么要做这个工作,有什么好处?

  • 代码缩减(摇树优化):使用静态代码分析来查找和删除无法访问的代码和未实例化的类型,对规避 64k 引用限制非常有用;

  • 资源缩减:移除不使用的资源,包括应用库依赖项中不使用的资源。

  • 混淆代码:缩短类和成员的名称,从而减小 DEX 文件的大小,增加反编译成本。

  • 优化代码:检查并重写代码,选择性内联,移除未使用的参数和类合并来优化代码大小。

  • 减少调试信息 : 规范化调试信息并压缩行号信息。

混淆的情况

混淆的情况是指你接手混淆时候的状况,大致分两种。

  • 一种是项目刚刚立项,这个时候你跟进混淆,随着你的代码量增多,和引入的第三方库&SDK 增多逐渐增加混淆规则,这是一个应该有的良性的状态,做到精准混淆也容易。
  • 第二种情况是以前的维护者完全没有混淆,有海量的代码和第三方库,里面的反射注解和各种存在混淆风险的问题存在,这样想做到精准混淆并不容易

上文多次提到精准混淆,我理解的精准混淆是最细粒度的白名单,而不是如下反例:

-keep public class * extends java.lang.Object{*;}

混淆基础知识储备

开启和关闭混淆

开启混淆比较简单,一般来讲为了方便开发调试只混淆 release 版本:

buildTypes {
    release {
        shrinkResources true //开启资源压缩
        minifyEnabled true //开启混淆
        zipAlignEnabled true //k对齐
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}

minifyEnabled 和 proguardFiles 是必选项其他为可选,关闭混淆的话就比较容易了直接 minifyEnabled 修饰为 false 即可。

proguard-android.txt 和 proguard-android-optimize.txt

我们经常在代码里面看到这样的语句:

proguard-rules.pro 我们知道就在 app/ 目录下,但是这个 getDefaultProguardFile 是什么?在哪里?有什么用?

getDefaultProguardFile 是 Android SDK 为我们提供的一些 Android 内置的混淆规则,一般来将这些是通用的,你要做到精通混淆必选知道它的位置以及他里面包含的内容和含义。

位置:android/sdk/tools/proguard/

# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html
#
# This file is no longer maintained and is not used by new (2.2+) versions of the
# Android plugin for Gradle. Instead, the Android plugin for Gradle generates the
# default rules at build time and stores them in the build directory.

-dontusemixedcaseclassnames #混淆时不会产生形形色色的类名
-dontskipnonpubliclibraryclasses #指定不去忽略非公共类库
-verbose #输出生成信息

# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize and preverify steps (and performs some
# of these optimizations on its own).
#-dontoptimize #不优化指定文件
-dontpreverify #不预校验
# Note that if you want to enable optimization, you cannot just
# include optimization flags in your own project configuration file;
# instead you will need to point to the
# "proguard-android-optimize.txt" file instead of this one from your
# project.properties file.

-keepattributes *Annotation*
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {
    native <methods>;
}

# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
-keepclassmembers public class * extends android.view.View {
   void set*(***);
   *** get*();
}

# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-keepclassmembers class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator CREATOR;
}

-keepclassmembers class **.R$* {
    public static <fields>;
}

# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version.  We know about them, and they are safe.
-dontwarn android.support.**

# Understand the @Keep support annotation.
-keep class android.support.annotation.Keep

-keep @android.support.annotation.Keep class * {*;}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <methods>;
}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <fields>;
}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <init>(...);
}

mapping 文件

Mapping 非常重要,在 app/build/mapping 中生成的 mapping 文件是我们分析混淆是否生效,混淆后的崩溃寻因的重要依据,通过这个文件的映射我们能够在一堆杂乱无章的 a、 b、 c 中回溯到原始代码。例:

工具集

工欲善其事必先利其器,两款对混淆有着很大帮助的工具介绍

Android Studio APK Analysis

AS自带简单好用,对比包体积的占比分析也是相当不错,并且随着 AS 的迭代有着官方的支持相信功能会越来越强大,我们只需要简单的将 apk 包拖拽到 AS 中就会自动触发 AS 的 apk 解析功能:

Jadx

Jadx 的强大之处在于相较于 AS 自带的分析器,它还能直接查看源代码,AS 只能看到类名和方法名,简直是逆向神器。

更多介绍请移步 github.com/skylot/jadx

混淆实战

通过 demo 样例的混淆实战深刻理解每个混淆规则的含义,我们要做到的不是仅仅开启 minifyEnabled 然后应用通过,而是需要知到得更细更透彻,理解每个混淆语句规则的作用范围。

先定义一下基准包以及子包,还有类、内部类、接口、注解、方法、成员,然后我们分部对其进行混淆和 -keep 保持,记住下图的 proguard 开始的包类目录关系,我们后面一直要使用它。

后续的文章都会以这几个类做样例,所以我们把它罗列出来再加深一下印象:

  • User.java
  • Animal.java
  • MethodLevel.java
  • Student.java
  • Teacher.java
  • Company.java
  • IBehaviour.java

部分样例类:

public class Teacher extends User implements IBehaviour {

  @Override
  public void doSomething() {
    System.out.println("teaching ...");
  }

  @MethodLevel(value = 1)
  private void waking(){

  }
}

混淆中代码调用关系

先开启混淆,不添加任何规则。我们通过 jadx 看下混淆情况

proguard 包和类一个都找不到应该都是被混淆了,进一步印证一下我们的想法,我们去 mapping 文件里面找下映射关系,结果出乎意料,我没有在 mapping 中找到映射关系,只在 usage.txt 中找到了对应的全路径名

是不是我们的类申明了没有引用导致的呢?我们去 activity 做一下调用

果然和我们的预想的一样,如果类创建了没有使用,mapping 不会生成映射关系,甚至可能在打包的过程中给优化掉,再看加上调用关系后我们查询 mapping 文件:


上图可以得知,我们的 proguard 包和下面的所有内容全部都混淆了。

keep 探寻

网络上的大部分文章都千篇一律,简单的给出了一个 Keep 语句,实际用的时候都是 copy 对其作用范围不是很明确,接下来我们就一个一个来探寻

keep *

-keep class com.zxmdly.proguard.*

我们先加上这句看看打包后的变化

对比之前的结果,我们看到的是 proguard 的包和下面的类名被保留下来了,注意仅仅是包合类名被保留,类中的字段和成员是没有找到的,这是为什么呢?难道是字段没有被使用

我们去印证下

好了,到现在我们已经能够透彻的知道了 -keep * 的作用,总结作用范围:

  • 能够保持该包和该包下的类、和静态内部类的类名保持,对字段和方法不额外起作用,子包不起作用,字段或者方法没有被调用则直接忽略。

keep **

-keep class com.zxmdly.proguard.**

通过查看上图和上面 keep * 的经验,我们可以得出结论:

  • keep ** 能够保持该包和其子包的子类的所有类名(含注解、枚举)不被混淆,但是方法和字段不在其作用范围,字段或者方法没有被调用则直接忽略。

值得注意的是, keep ** 对于 keep * 是包含关系,声明了 keep ** 混淆规则就无需再声明 keep * 了。

keep ** {*;}

-keep class com.zxmdly.proguard.* {}

有了之前的经验,我们可以得出结论:

  • keep ** {*;} 的作用范围特别大,能够保持该包及其子包、子类和其字段方法都不被混淆,相对来讲我们需要慎用这样的语句,因为可能导致混淆不够精准。

单个类名保持

-keep class com.zxmdly.proguard.Company

  • 仅保持类名,字段和成员被混淆

保持方法

-keep class com.zxmdly.proguard.Company{
  <methods>;
}

保持字段

-keep class com.zxmdly.proguard.Company{
  <fields>;
}

实现关系保持

-keep public class * implements com.zxmdly.proguard.IBehaviour

-keep public class * implements com.zxmdly.proguard.IBehaviour {*;}

继承关系保持

-keep public class * extends com.zxmdly.proguard.base.User {*;}

指定保持具体方法或者字段

-keep class com.zxmdly.proguard.Company{
      public java.lang.String address;
      public void printlnAddress();
}

Tips 小技巧

在 gralde 中,我们可以通过下面配置将我们的混淆规则分门别类,指定多个混淆配置文件。

例如给第三方的 SDK 专门放到一个 Third 混淆配置文件,使用了这个小技巧加上注释,我们的混淆规则是不是更清晰了呢

结语

通过本文由浅入深的带大家进行混淆实战,相信 99% 的精准混淆工作已经难不倒你,当然混淆还有更深入和更细节的用法,篇幅关系我们下次再探。

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
在这里插入图片描述
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

一、架构师筑基必备技能

1、深入理解Java泛型
2、注解深入浅出
3、并发编程
4、数据传输与序列化
5、Java虚拟机原理
6、高效IO
……

在这里插入图片描述

二、Android百大框架源码解析

1.Retrofit 2.0源码解析
2.Okhttp3源码解析
3.ButterKnife源码解析
4.MPAndroidChart 源码解析
5.Glide源码解析
6.Leakcanary 源码解析
7.Universal-lmage-Loader源码解析
8.EventBus 3.0源码解析
9.zxing源码分析
10.Picasso源码解析
11.LottieAndroid使用详解及源码解析
12.Fresco 源码分析——图片加载流程

在这里插入图片描述

三、Android性能优化实战解析

  • 腾讯Bugly:对字符串匹配算法的一点理解
  • 爱奇艺:安卓APP崩溃捕获方案——xCrash
  • 字节跳动:深入理解Gradle框架之一:Plugin, Extension, buildSrc
  • 百度APP技术:Android H5首屏优化实践
  • 支付宝客户端架构解析:Android 客户端启动速度优化之「垃圾回收」
  • 携程:从智行 Android 项目看组件化架构实践
  • 网易新闻构建优化:如何让你的构建速度“势如闪电”?

在这里插入图片描述

四、高级kotlin强化实战

1、Kotlin入门教程
2、Kotlin 实战避坑指南
3、项目实战《Kotlin Jetpack 实战》

  • 从一个膜拜大神的 Demo 开始

  • Kotlin 写 Gradle 脚本是一种什么体验?

  • Kotlin 编程的三重境界

  • Kotlin 高阶函数

  • Kotlin 泛型

  • Kotlin 扩展

  • Kotlin 委托

  • 协程“不为人知”的调试技巧

  • 图解协程:suspend

在这里插入图片描述

五、Android高级UI开源框架进阶解密

1.SmartRefreshLayout的使用
2.Android之PullToRefresh控件源码解析
3.Android-PullToRefresh下拉刷新库基本用法
4.LoadSir-高效易用的加载反馈页管理框架
5.Android通用LoadingView加载框架详解
6.MPAndroidChart实现LineChart(折线图)
7.hellocharts-android使用指南
8.SmartTable使用指南
9.开源项目android-uitableview介绍
10.ExcelPanel 使用指南
11.Android开源项目SlidingMenu深切解析
12.MaterialDrawer使用指南
在这里插入图片描述

六、NDK模块开发

1、NDK 模块开发
2、JNI 模块
3、Native 开发工具
4、Linux 编程
5、底层图片处理
6、音视频开发
7、机器学习

在这里插入图片描述

七、Flutter技术进阶

1、Flutter跨平台开发概述
2、Windows中Flutter开发环境搭建
3、编写你的第一个Flutter APP
4、Flutter开发环境搭建和调试
5、Dart语法篇之基础语法(一)
6、Dart语法篇之集合的使用与源码解析(二)
7、Dart语法篇之集合操作符函数与源码分析(三)

在这里插入图片描述

八、微信小程序开发

1、小程序概述及入门
2、小程序UI开发
3、API操作
4、购物商场项目实战……

在这里插入图片描述

全套视频资料:

一、面试合集
在这里插入图片描述
二、源码解析合集

在这里插入图片描述
三、开源框架合集

在这里插入图片描述
欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取↓↓↓

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《Android驱动开发与移植实战详解》是一本系统讲解在Android平台上驱动开发与移植的书籍。本书主要内容包括Android系统架构、驱动框架、Linux驱动开发方法、Android下驱动开发与移植等方面。本书由易到难、由浅入深,从讲解Android系统架构和驱动框架开始,通过对Linux内核驱动开发方法的讲解来引入读者进入Android下驱动开发与移植的实践。 本书从Android平台的体系结构开始,系统介绍了Android平台的各个组成部分,包括Java层、Native层和Linux内核层。在介绍完整个Android系统架构的同时,本书也详细讲解了Android内核的驱动框架,包括Linux内核驱动框架和Android内核驱动框架,并详细介绍了驱动的编写方法、调试方法和性能优化技巧。 本书还介绍了Android系统下常用硬件的驱动开发方法,包括USB驱动、SPI驱动、I2C驱动、MMC/SD卡驱动、LCD驱动、触摸屏驱动、按键驱动等。而且本书还详细介绍了Android系统的设备树,以及如何进行驱动的移植和调试。 总体来说,本书内容丰富,对Android驱动开发及移植有一定的基础和经验的读者可以通过本书进一步提高自己的技术水平。该书能帮助读者深入理解Android系统的内在机制,掌握Android驱动开发与移植的实际应用技能,是一本实用性强的专业书籍。 ### 回答2: 《Android驱动开发与移植实战详解pdf》是一本关于Android系统驱动开发与移植的专业性教材,主要介绍了如何进行Android系统驱动的开发、调试和移植,帮助读者掌握Android系统底层驱动的知识和技术。 本书首先介绍了Android系统的架构和驱动模型,深入分析了Android设备驱动的实现方式和工作流程。然后详细讲解了如何编写和调试Android驱动程序,包括内核模块、字符设备驱动、块设备驱动等多种类型的驱动开发。 此外,本书还解释了Android驱动程序的移植方法和技巧,包括从其他Linux系统移植Android驱动程序、自定义Android驱动程序以及如何把一个驱动程序移植到不同的设备上等重要内容。这样的话,读者可以在实际项目开发中更加容易地完成Android驱动程序的实现和移植。 总之,《Android驱动开发与移植实战详解pdf》是一本涵盖了Android系统驱动开发和移植等方面内容,对于想进一步了解Android系统底层工作原理的读者有着重要的指导意义。无论是初学者还是有经验的开发人员,在阅读本书后都可以获得很多关于Android驱动开发和移植的实用技巧和工具。 ### 回答3: 《android驱动开发与移植实战详解》是一本介绍Android驱动程序开发和移植的实用指南。本书包含了许多基础概念、应用场景和实例,可以帮助读者快速学习Android驱动程序开发和移植的实际应用。 本书的内容涉及很多主题,例如Android系统的架构和驱动模型、设备驱动程序的编写、驱动程序的调试和测试、不同类型设备的驱动程序移植等。其中,编写设备驱动程序需要掌握C语言的基础知识,而调试和测试则需要熟悉一些工具和技术。 本书的每一章节都配有大量的实例代码和案例分析,可以帮助读者深入理解Android驱动程序的开发和移植流程。同时,作者也提供了一些实用的技巧和建议,例如如何选择最合适的驱动程序类型、如何调试设备驱动程序、如何在移植设备驱动程序时避免常见问题等。 总之,《android驱动开发与移植实战详解》是一本非常实用的书籍,可以帮助Android开发者更加深入地了解驱动程序开发和移植的实际应用。对于那些刚开始从事Android开发的读者来说,这本书也是一个非常不错的入门指南。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值