上一篇文章我们讲述了Android减少安装包体积的一些tips,本文主要对前文提到的资源混淆做一个简单的分析。微信中的资源混淆工具主要为了混淆资源ID长度(例如将res/drawable/welcome.png混淆为r/s/a.png),同时利用7z深度压缩,大大减少了安装包体积,同时也增加了逼格,提升了反破解难度。
资源混淆工具大约是在2014年4月实现,并在微信5.4中使用,减少了大约1M的空间。然后在8月在公司内部开源,现以推广到QQ邮箱、QQ空间、手机管家等多个产品中使用。
具体源码与使用方法详细在github中:
https://github.com/shwenzhang/AndResGuard
资源混淆简单来说希望实现将res/drawable/icon,png变成res/drawable/a.png,或我们甚至可以将文件路径也同时混淆,改成r/s/a.png。
Proguard -> Resource Proguard R.string.name -> R.string.a res/drawable/icon -> res/drawable/a r/s/a
我们可以想到以下几种方案:
几种方案的对比如下:
毫无疑问,微信采用的是方案三。现在关键问题是我们如何直接修改resources.arsc文件来达到资源混淆的效果?
在回答上面的问题之前,我们首先需要对resources.arsc的文件格式有一定的了解。resources.arsc一共有五种chunk类型,分别为TYPETABLE,TYPEPACKAGE,TYPE_STRING ,TYPETYPE,TYPECONFIG。
--table,是整个reousces table的开始,它的chunksize即是整个文件的大小。 --package,指的是一个package的开始,其实在resources,arsc是可以有多个package的。而packageID即是资源resID的最高八位,一般来说系统android的是1(0x01),普通的例如com.tencent.mm会是127(0x7f),剩下的是从2开始起步。当然这个我们在aapt也是可以指定的(1-127即八位的合法空间,一些混合编译就是改这个packageID)。 --string, 代表stringblock,我们一共有三种类型的stringblock。分别是table stringblock,typename stringblock, specsname stringblock。 --type,这里讲的是typename stringblock里面我们用到的各种type(用到多少种类型的type,就有多少个type chunk),例如attr, drawable, layout, id, color, anim等,Type ID是紧跟着Package ID。 --config, 即是Android用来描述资源维度,例如横竖屏,屏幕密度,语言等。对于每一种type,它定义了多少种config,它后面就紧跟着多少个config chunk,例如我们定义了drawable-mdpi,drawable-hdpi,那后面就会有两个config。 --entry,尽管没有entry这个chunk,但是每个config里面都会有很多的entry,例如drawable-mdpi中有icon1.png,icon2.png两个drawable,那在mdpi这个config中就存在两个entry。
简单来说方案为:
修改方案 | |
---|---|
1. table stringblock | 我们需要把文件指向路径改变,例如res/layout/test.xml,改为res/layout/a.xml |
2. 资源的文件名 | 需要将资源的文件名改为对应1,即将test.xml重命名为a.xml |
3. specsname stringblock | 旧的specsname除了白名单部分全部废弃,替换成所有我们混淆方案中用到的字符。由于大家都重复使用[a-z0-9_],specsname的总数量会大大减少。 |
4. entry中指向的specsname 中的id | 例如原本test.xml它指向specsname中的第十项,我们需要用混淆后的a项的位置改写。 |
5. table chunk的大小 | 修改table chunk的最后大小 |
与7z极限压缩结合
根据上文安装包知识的文章,7z有着更好的压缩率,同时我们也可以强制压缩类似resources.arsc、png、jpg等Android默认不会打包压缩的文件。
最后把修改后的resources.arsc重打包即可,微信从解压,到混淆,到重打包耗费时间,不要799,也不要699,仅需35秒。具体效果如下图:
最后,整体的处理流程如下:
TODO,除了资源混淆,其实我们还可以实现资源加密等其他功能。