Android高级混淆和代码保护技术

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介:
本文讲的是 Android高级混淆和代码保护技术, 这是一篇关于 Android 代码保护的文章,旨在介绍代码混淆、防止逆向工程的各种高级技巧。大家都很忙,我也赶着回去继续开发我的新应用,因此话不多说,越干(gan, 一声)越好。

开始之前,值得一说的是,本文超过五千字,完全由我开发的「纯纯写作」书写而成,纯纯写作主打安全、写作体验和永不丢失内容,于是本着珍爱生命,我用纯纯写作来写这篇文章。

本文有两部分内容,一部分讲混淆,一部分介绍一些混淆之下的安全手段。基准原则都是:在保证不麻烦到自身 以及 能够正常阅读异常日志的前提下,尽可能提高混淆强度和保护代码安全。

本文原文地址:http://drakeet.me/android-advanced-proguard-and-security/

混淆

Android 官方集成了 Proguard 以供我们进行代码混淆工作,关于 Proguard 你可以搜索到各种它的 rules 解释,这些文章千篇一律,因此我不再赘述,只说一些特别的有用的技巧:

一般情况下,Android 的 gradle 中都会默认写着:

 
  1. proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 

这一行代码很多人不了解。它的意思是,指定了两个 Proguard rules 文件,一个是通过getDefaultProguardFile() 方法获得官方自带的混淆规则文件路径,另一个是与当前 gradle 相同目录下的 proguard-rules.pro 文件路径。

后者就在我们项目中,由我们书写的,没什么好说的,我们要关注的是前者这个默认 Proguard 文件,它的内容是什么你有曾探究过吗?没有的话,你可以在你的系统文件里搜索proguard-android.txt 就应该能把它找出来,具体自己去看,我就说一些关键的,这个默认文件中帮我们声明了许多混淆规则内容,包括:keep 所有继承自 View 的类,keep 所有继承自 Activity 的类,keep 所有 JavascriptInterface、native 方法声明,以及 keep 一些注解了@Keep 的内容。

所以你知道为什么默认情况下,即使你自己一条规则都没有加入,你的自定义 View 和 Activity 都被保留下来了吧,至少类名都没有被混淆。

那么为什么官方默认会帮我们写下这些?为什么 View 和 Activity 默认情况下应该被保留呢?

简单来说,因为 Proguard 原本是为 Java 打造的,它无法搜索到我们 AndroidManifest、布局等文件中引用了哪些 Java 类,因此如果 Java 代码变了而 XML 文件中的引用没变,就会造成反射失败。所以这些被 XML 使用到的类需要 keep 住。

对于这个问题,饿了么 的团队提供了一个鲜为人知的 gradle 插件 用来无伤混淆 Activity 和 View,这个项目叫 Mess:https://github.com/eleme/Mess ,具体内容各位可以稍后自行去阅读其文档和教程,链接最后都还会附于末尾。简单来说,Mess 弥补了 Proguard 不能检索 XML 文件的缺点,帮 Proguard 完成了 Activity 和 View 的改名及 mapping。

话说回来,前面我建议各位都去逐行了解下默认混淆配置文件,因为只有这样,你才知道整个混淆工具帮你做了什么,了解清楚之后,我建议的一个做法是,把这个默认文件拷贝到你的项目目录之下,删掉 getDefaultProguardFile('proguard-android.txt'),再引入现存于你目录之下的原默认文件。这么做的好处是,方便你修改这个默认文件,因为它有些内容是不必要或者可以更改的。不过基本上我们可以保留其原样。复制过来的另一个好处是,避免其被外方更新导致你引用过来后产生变数。总之,proguardFiles 这个配置项(其实是一个 gradle 方法)可以接受无限个 rules 文件路径,它的参数是一个可变字符串参数,不过为了避免代码横向发展,我更愿意使用另一个方法,叫 proguardFile,注意,少了一个 s 有没有,它接受单个参数,相当于 add 一个 rules。对此,提供我的配置以供参考:

 
  1. release { 
  2.     debuggable false 
  3.     minifyEnabled true 
  4.     zipAlignEnabled true 
  5.     shrinkResources true 
  6.     signingConfig signingConfigs.release 
  7.     proguardFile 'proguard-common.pro' 
  8.     proguardFile 'proguard-rules.pro' 
  9.     proguardFile 'proguard-rules-google-ads.pro'

其中 proguard-common.pro 这个文件就是上述我说的复制过来的官方默认配置文件,它被我放在当前 module 目录之下和 proguard-rules.pro 并列。这么写很清楚而且便于复用。

讲完基本内容之后,我决定再介绍两条特别实用的 Proguard rules:

-repackageclasses

-repackageclasses 这条规则配置特别强大,它可以把你的代码以及所使用到的各种第三方库代码统统移动到同一个包下,可能有人知道这条配置,但仅仅知道它还不能发挥它最大的作用,默认情况下,你只要在 rules 文件中写上 -repackageclasses 这一行代码就可以了,它会把上述的代码文件都移动到根包目录下,即在 / 包之下,这样当有人反编译了你的 APK,将会在根包之下看到 成千上万 的类文件并列着,除此之外,由于我们有时不得不 keep 一些类文件,于是你应用的包名层次仍然会存在,有一些没被完全混淆的类将继续存留在你的包名之下,这些类文件就相对得不到很好的保护。于是我要介绍一个小技巧,就是 -repackageclasses 后跟上一个你应用的包名,如:

-repackageclasses com.drakeet.purewriter.debug

这么做以后,最终 Proguard 会将包括第三方库的所有类文件都移动到你的包名之下,所谓藏叶于林,这时候那些你未能完全混淆的类也可以藏身在这类文件大海之中,而且这些类文件名都会被混淆成 abcd 字母组合的名字。

需要注意的是,-repackageclasses + 你的包名 这种做法存在混淆 bug,而默认 -repackageclasses 不加包名不会出现 bug,所以初次使用此法需要进行测试,否则请退而求其次,关于这个 bug 的具体内容不多说,很赘述。

第二个实用 rules 配置项:-obfuscationdictionary

-obfuscationdictionary 后面加一个纯文本文件路径,它的作用是指定一个字典文件作为混淆字典。默认情况下我们的代码命名会被混淆成 abcdefg... 字母组合的内容,需要修改可以使用这个配置项将字典修改成乱码或中文内容。乱码命名可以令反编译者怀疑人生。中文命名则能够破坏一些反编译软件的正常工作,而且有的中文命名还能起到乱花渐欲迷人眼的效果,比如 GitHub 上较为流行的某长者的话语作为字典,在此不便贴出(可能会有人身危险),各位可以自行搜索,找不到别怪我。这些话语作为代码命名,可以令反编译者沉浸其中,无心分析代码 :P。

最后,关于混淆的内容,我们还有一块软肋,就是资源文件,Proguard 完全不会管我们的资源文件,因此如果资源文件名没有做保护的话,很容易被顺藤摸瓜找到关联的 Java 代码,对此,微信团队提供了一个好用的资源混淆工具,它不仅能帮你全面混淆资源文件,还能帮你缩减资源文件的整体体积,这个工具叫 AndResGuard,开源地址:https://github.com/shwenzhang/AndResGuard

好了,终于简单讲完了一些关于混淆的要点,关于混淆其实还有许多小内容,比如可以使用consumerProguardFiles 为一个 library 或 SDK 项目配置混淆文件,这样当某个 app 引用了你这个库,无需再配置相关混淆内容,该 app 就会自动从 consumerProguardFiles 配置的文件中读取需要进行的 keep 动作,这对于库开发者是很有用的一个功能。更多就不细说了,文章末尾我会附上我的混淆配置文件片段。

安全

有了代码混淆还不够,我们需要更多技巧来保护我们的代码,特别是对于需要做混淆但又需要暴露许多 API 的 SDK 开发者来说。混淆是基础,代码安全是意识。

首先我们要知道我们混淆代码是如何被攻破的,其实对于反编译者来说,最简单的入手点就是字符串搜索,我们硬编码留在代码里的字符串值都会在反编译过程中被原样恢复,因此这是我们首要关注对象。避免被通过字符串攻破,我们应该做到以下几点:

一,不要硬编码写入字符串值,即使你不得不这么做,也至少应该另起一个类,比如叫做HardStrings,用于静态存放这些硬编码的字符串。这样反编译者只能搜索到你这个常量类,而较难以搜索到这些字符串常量被哪里引用。

二,在 release 混淆过程中删除 Log 代码,使用 -assumenosideeffects 这个配置项可以帮我们在编译成 APK 之前把日志代码全部删掉,这么做不仅有助于提升性能,而且日志代码往往会保留很多我们的意图和许多可被反编译的字符串:

 
  1. -assumenosideeffects class android.util.Log { 
  2.     public static boolean isLoggable(java.lang.String, int); 
  3.     public static int d(...); 
  4.     public static int w(...); 
  5.     public static int v(...); 
  6.     public static int i(...); 

三,对于你不得不留下的一些硬编码和日志内容,可以采用编码形式替换,如 你可以规定 "4001" 代表某种错误,而不是在你的代码里写入这个错误的具体描述字符串。这么做的话,你需要有个地方记下这些编码映射的内容,关于此有个技巧:你可以再创建一个常量类,其内容是一堆静态字符串对象,针对上面那个例子,你可以把真正的错误信息作为一个字符串变量的名字,而把它的值写成一个编码,如下:

 
  1. public static final String SHOULD_REGISTER_FIRST_ERROR = "ssrrffe"

这样当你在看没混淆的代码引用这个静态变量,你能够一目了然它的意思。而反编译者看到的则是:

 
  1. public static final String abc = "ssrrffe"

命名看不懂,值也看不懂。

四,把 AppKey 之类特别敏感的字符串内容藏在 native so 文件中。

关于字符串技巧的内容差不多就这样了,能做到这些就不错了,还有一些极端做法不多说,为了阻碍黑客阅读,自己也变得非常麻烦,双刃剑,这不是我们想要的结果。

然后我们讲另一个混淆后代码的软肋,就是一些我们不得不 keep 的内容,如果是闭源 SDK 开发者,需要 keep 的内容将会更多,几乎只要是 public 的类、变量,方法,全部要 keep,那么针对这个问题,我们该怎么办?介绍一个方法:

给这些需要 keep 的内容设置委托者,然后将委托者投入大海之中。

很玄乎吧?哈哈,这么讲有助于记忆。其实和我们在混淆章节说的藏叶于林的思想是一样的。如果一个类不得不 keep,那就把它所做的全部内容都转交给一个 private 或 internal 的类对象去完成,这个委托类对象代码可以完全混淆,然后你再把这个委托类通过混淆工具藏在大量的代码之中,这样就足够给反编译者带来了很大的麻烦,相比直接获取逻辑代码,这么做以后要找到实体的逻辑代码将费劲得多。

因此,如果你知道有这么一个方式,其实你完全可以不使用饿了么提供的那个 Activity 和 View 混淆工具,也能很好地保护你的 Activity 和 View。

不过一般情况我们无需所有内容都保护,只要把关键、核心内容委托出去就可以了。

最后的最后,我们还需要做的就是防止反编译者重新打包,全方位绝人之路呀,能做的就是在代码中加入签名验证,并做双向依赖。关于此我写过一个类似阿里黑匣子的东西,能够在 native 检查签名和加解密内容,后续也有计划整理开源,这里暂且就不多说了。

除此之外,我专门写过一篇叫作《Android 密钥保护和 C/S 网络传输安全理论指南》 的文章,感兴趣可以之后移步阅读。

总之,代码安全和混淆是一个意识加技巧的问题,但都不难,掌握以上内容就已经十分好了。分享到此结束,如有疑问或问题欢迎来信交流。


本文作者:佚名

来源:51CTO

原文标题:Android高级混淆和代码保护技术
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
28天前
|
安全 Android开发 iOS开发
安卓与iOS的较量:技术特性与用户体验的深度解析
在移动操作系统的战场上,安卓和iOS一直占据着主导地位。本文将深入探讨这两大平台的核心技术特性,以及它们如何影响用户的体验。我们将从系统架构、应用生态、安全性能和创新功能四个方面进行比较,帮助读者更好地理解这两个系统的异同。
50 3
|
2月前
|
物联网 区块链 vr&ar
未来已来:探索区块链、物联网与虚拟现实技术的融合与应用安卓与iOS开发中的跨平台框架选择
【8月更文挑战第30天】在科技的巨轮下,新技术不断涌现,引领着社会进步。本文将聚焦于当前最前沿的技术——区块链、物联网和虚拟现实,探讨它们各自的发展趋势及其在未来可能的应用场景。我们将从这些技术的基本定义出发,逐步深入到它们的相互作用和集成应用,最后展望它们如何共同塑造一个全新的数字生态系统。
|
7天前
|
安全 Android开发 数据安全/隐私保护
探索安卓与iOS的安全性差异:技术深度分析与实践建议
本文旨在深入探讨并比较Android和iOS两大移动操作系统在安全性方面的不同之处。通过详细的技术分析,揭示两者在架构设计、权限管理、应用生态及更新机制等方面的安全特性。同时,针对这些差异提出针对性的实践建议,旨在为开发者和用户提供增强移动设备安全性的参考。
|
10天前
|
监控 Android开发 iOS开发
深入探索安卓与iOS的系统架构差异:理解两大移动平台的技术根基在移动技术日新月异的今天,安卓和iOS作为市场上最为流行的两个操作系统,各自拥有独特的技术特性和庞大的用户基础。本文将深入探讨这两个平台的系统架构差异,揭示它们如何支撑起各自的生态系统,并影响着全球数亿用户的使用体验。
本文通过对比分析安卓和iOS的系统架构,揭示了这两个平台在设计理念、安全性、用户体验和技术生态上的根本区别。不同于常规的技术综述,本文以深入浅出的方式,带领读者理解这些差异是如何影响应用开发、用户选择和市场趋势的。通过梳理历史脉络和未来展望,本文旨在为开发者、用户以及行业分析师提供有价值的见解,帮助大家更好地把握移动技术发展的脉络。
|
14天前
|
开发工具 Android开发 iOS开发
掌握安卓与iOS应用开发:关键技术与未来展望
本文深入探讨了安卓和iOS平台下的应用开发技术,重点比较了两大平台的架构、开发工具和市场策略。通过分析最新的技术趋势和开发者社区的反馈,文章为读者提供了一个全面的对比视角,旨在帮助开发者做出更明智的平台选择和开发决策。
|
8天前
|
安全 Java Android开发
掌握安卓与iOS应用开发中的关键技术
本文深入探讨了安卓和iOS平台上应用开发的关键性技术,包括平台特性、开发工具选择、性能优化技巧及跨平台开发的可行性分析。通过对比两种平台的开发环境与实践案例,旨在为开发者提供全面的视角以理解和把握移动应用开发的核心技术。无论是安卓的Java与Kotlin之争,还是iOS的Swift语言革命,本文都将一一解析其优势与应用场景,帮助开发者在技术选型上有更明智的决策。此外,文章还将触及到当前流行的跨平台框架如React Native和Flutter,评估它们在项目实施中的实用性和限制,为有意进行多平台同步开发的团队提供参考。通过对这些关键技术的梳理,本文期望能够启发开发者深化对移动平台开发的理解,并
|
12天前
|
人工智能 vr&ar Android开发
探索安卓与iOS的无限可能:移动操作系统的技术革新与未来展望
本文旨在探讨安卓和iOS这两大主流移动操作系统在技术上的创新与突破,以及它们如何塑造我们的数字生活。通过深入分析两者的最新进展、面临的挑战以及未来的发展趋势,文章揭示了移动操作系统在推动科技进步和满足用户需求方面的关键作用。我们将从技术角度出发,解读安卓的开放性与iOS的封闭性如何影响应用生态和用户体验,并探讨这些差异背后的设计理念和商业考量。同时,我们还将关注两大系统在安全性、隐私保护、人工智能集成等方面的最新动态,以及它们如何应对日益增长的网络安全威胁和用户对隐私保护的需求。此外,文章还将展望未来移动操作系统的发展,分析5G、物联网等新兴技术如何为安卓和iOS带来新的机遇和挑战,以及这两大
33 6
|
13天前
|
存储 Java Android开发
🔥Android开发大神揭秘:从菜鸟到高手,你的代码为何总是慢人一步?💻
在Android开发中,每位开发者都渴望应用响应迅速、体验流畅。然而,代码执行缓慢却是常见问题。本文将跟随一位大神的脚步,剖析三大典型案例:主线程阻塞导致卡顿、内存泄漏引发性能下降及不合理布局引起的渲染问题,并提供优化方案。通过学习这些技巧,你将能够显著提升应用性能,从新手蜕变为高手。
16 2
|
14天前
|
安全 Linux Android开发
探索安卓与iOS的安全性差异:技术深度分析
本文深入探讨了安卓(Android)和iOS两个主流操作系统平台在安全性方面的不同之处。通过比较它们在架构设计、系统更新机制、应用程序生态和隐私保护策略等方面的差异,揭示了每个平台独特的安全优势及潜在风险。此外,文章还讨论了用户在使用这些设备时可以采取的一些最佳实践,以增强个人数据的安全。
|
19天前
|
API Android开发 iOS开发
掌握安卓与iOS应用开发中的依赖注入技术
本文探讨了在安卓和iOS应用开发中,如何有效利用依赖注入技术来提升代码的模块化、可测试性和可维护性。通过对比分析两种平台下依赖注入的实现方式与工具,本文旨在为开发者提供一套清晰、实用的依赖管理策略,助力打造高质量软件产品。
下一篇
无影云桌面