前言
Proguard 能混淆Java代码,却是混淆不了资源文件,AndResGuard 弥补了这个空缺。一、AndResGuard是什么?
AndResGuard是混淆资源文件,破坏资源文件可读性,同时缩小APK大小的工具,微信提供,它的原理类似Java Proguard。 作用有两点:一是通过混淆资源ID长度同时利用7z深度压缩,减小了apk包大小;二是混淆后在安全性方面有一点提升,提高了逆向破解难度。二、混淆原理
1.生成新的资源文件目录,里面对资源文件路径进行混淆(其中涉及如何复用旧的mapping文件),例如将res/drawable/hello.png混淆为r/s/a.png,并将映射关系输出到mapping文件中。 2.对资源id进行混淆(其中涉及如何复用旧的mapping文件),并将映射关系输出到mapping文件中。 3.生成新的resources.arsc文件,里面对资源项值字符串池、资源项key字符串池、进行混淆替换,对资源项entry中引用的资源项字符串池位置进行修正、并更改相应大小,并打包生成新的apk。原文链接:https://blog.csdn.net/u011106915/article/details/107705862
资源混淆简单来说希望实现将res/drawable/icon.png
变成 res/drawable/a.png
,或我们甚至可以将文件路径也同时混淆,改成 r/s/a.png
。它通过修改resources.arsc文件,从而可以混淆Apk包的资源文件路径,达到减少Apk包体积的目的,而且还提升了反编译的难度。
二、使用步骤
project gradle: classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.18'
app.gradle:
apply from: 'and_res_guard.gradle'
and_res_guard.gradle:
apply plugin: 'AndResGuard'
andResGuard {
// keep住不混淆的资源原有的物理路径 mappingFile = file("./resource_mapping.txt");
//如果混淆全部的话,设置 mappingFile = null
mappingFile = null
// 打开这个开关,会keep住所有资源的原始路径,只混淆资源的名字
keepRoot = false
// 设置这个值,会把arsc name列混淆成相同的名字,减少string常量池的大小
// fixedResName = "arg"
// 启用7zip压缩。当你使用v2签名的时候,7zip压缩是无法生效的。
// use7zip 为true时,useSign必须为true
// 对于发布于 Google Play 的 APP,建议不要使用 7Zip 压缩,因为这个会导致 Google Play 的优化 Patch 算法失效
use7zip = true
// 启用签名,(需要配置signConfig)
useSign = true
// 保留不被混淆的资源文件,只作用于文件名,不会对路径有影响,支持通配符:? * +
// 【+】代表1个或多个,【?】代表0个或1个,【*】代表0个或多个。如 "R.id.*",//任意id
whiteList = [
// for your icon
"R.drawable.icon",
// for fabric
"R.string.com.crashlytics.*",
// for google-services
"R.string.google_app_id",
"R.string.gcm_defaultSenderId",
"R.string.default_web_client_id",
"R.string.ga_trackingId",
"R.string.firebase_database_url",
"R.string.google_api_key",
"R.string.google_crash_reporting_api_key"
]
// 打包时是否压缩这类文件,支持通配符:? * +
compressFilePattern = [
"*.png",
"*.jpg",
"*.jpeg",
"*.gif",
//如果不是对APK size有极致的需求,请不要把resources.arsc添加进compressFilePattern
//"resources.arsc"
]
//配置7Zip,只需设置 artifact 或 path;支持同时设置,但此时以 path 的值为优先
sevenzip {
artifact = 'com.tencent.mm:SevenZip:1.2.7'
//path = "/usr/local/bin/7za" //path指本地安装的7za(7zip命令行工具)
}
/**
* 可选: 如果不设置则会默认覆盖assemble输出的apk
**/
finalApkBackupPath = "${project.rootDir}/final.apk"
/**
* 可选: 指定v1签名时生成jar文件的摘要算法 默认值为“SHA-1”
**/
// digestalg = "SHA-256"
}
编译...
四、白名单
使用AndResGuard对资源文件进行混淆,可能会导致部分资源文件没有办法获取到的问题。对这部分获取不到的资源需要进行白名单设置。也就是避免混淆。 如下,白名单设置的位置: whiteList = [
// for your icon
"R.drawable.icon",
// for fabric
"R.string.com.crashlytics.*",
// for google-services
"R.string.google_app_id",
"R.string.gcm_defaultSenderId",
"R.string.default_web_client_id",
"R.string.ga_trackingId",
"R.string.firebase_database_url",
"R.string.google_api_key",
"R.string.google_crash_reporting_api_key"
]
这个问题,AndResGuard也专门提出部分白名单。
AndResGuard白名单:https://github.com/shwenzhang/AndResGuard/blob/master/doc/white_list.md
除此之外,我们也需要了解出现找不到资源文件的原因:使用 getIdentifier() 的形式去获取资源或者代码中写死资源文件。getResources().getIdentifier(“com.test.demo:drawable/icon”,null,null);//包名 : 资源文件夹名 / 资源名
getResources().getIdentifier(“icon”, “drawable”, “com.test.demo”);//ID名,资源属性,包名
所以,我们也可以通过在工程中修改这部分代码,达到获取资源文件的目的;
又因为部分我们的引用三方SDK是没有办法修改的,所以呢,还是通过白名单规避吧~
五、扩展
大神都研究源码,并修改定制。
程序性能优化之APK大小优化(六)下篇:https://zhuanlan.zhihu.com/p/91510597
参考和转载地址
shwenzhang AndResGuard:https://github.com/shwenzhang/AndResGuard
Android 资源混淆 AndResGuard MD:https://www.cnblogs.com/baiqiantao/p/9292266.html
AndResGuard简单使用教程:https://www.jianshu.com/p/7a0984d9b2c3