安裝包立減1M--微信Android資源混淆打包工具

本文轉載自微信公衆號:WeMobileDev

原文鏈接:

https://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=208135658&idx=1&sn=ac9bd6b4927e9e82f9fa14e396183a8f&scene=1&srcid=1013pcRXMnnTemQFNW6eyW6E

看到好文,忍不住轉載,供需要的同學參考。

*********************************************************************

本文主要對Android的資源混淆做一個簡單的分析。微信中的資源混淆工具主要爲了混淆資源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

我們可以想到以下幾種方案:

  1. 最簡單的方法,我們按照Proguard的做法,直接在源碼級別修改,將代碼以及xml的R.string.name中替換到R.string.a,icon.png重命名爲a.png 然後再交給Android編譯。

  2. 根據Android的編譯流程,所有資源ID已經被編譯成32位int值。這說明我們並不需要去修改xml與java,因爲在編譯過程已經被R.java所替換,我們直接修改resources.arsc的二進制數據,不改變打包流程,只要在生成resources.arsc之後修改它,同時重命名資源文件。

  3. 但是方案二看起來不錯,但是它依然依賴了編譯流程,不利於使用。其實我們可以做到直接處理安裝包. 不依賴源碼,不依賴編譯過程,僅僅輸入一個安裝包,得到一個混淆包。

幾種方案的對比如下:


毫無疑問,微信採用的是方案三。現在關鍵問題是我們如何直接修改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秒。具體效果如下圖:


最後,整體的處理流程如下:


一些需要注意的問題

  1. compress參數對混淆效果的影響
    若指定compess 參數.png、.gif以及*.jpg,resources.arsc會大大減少安裝包體積。若要支持2.2,resources.arsc需保證壓縮前小於1M。

  2. 操作系統對7z的影響
    實驗證明,linux與mac的7z效果更好

  3. keepmapping方式對增量包大小的影響
    影響並不大,但使用keepmapping方式有利於保持所有版本混淆的一致性

  4. 渠道包的問題(**建議通過修改zip摘要的方式生產渠道包**)
    在出渠道包的時候,解壓重壓縮會破壞7zip的效果,通過repackage命令可用7zip重壓縮。

  5. 若想通過getIdentifier方式獲得資源,需要放置白名單中。

    部分手機桌面快捷圖標的實現有問題,務必將程序桌面icon加入白名單

TODO,除了資源混淆,其實我們還可以實現資源加密等其他功能。

發佈了41 篇原創文章 · 獲贊 1 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章