加固的意義
從安卓2.x版本起,加固技術就逐漸火了起來。最初,只有一些創業型公司涉及加固領域;隨着安卓應用的逐漸升溫,諸如阿里、騰訊、百度等大型互聯網公司逐漸涉及該領域。
那麼爲什麼要對APP進行加固呢?主要原因有三點:首先安卓的APP應用通常採用Java語言編寫的,開發門檻低,容易被反編譯(解釋性語言的弊端);其次安卓市場比較混亂且可自簽名,進而導致大量應用被二次打包,植入廣告、***;同時,手機Root後,***可利用Hook等技術手段可對應用進行動態***,獲取應用的核心邏輯。綜合這三點來看,安卓應用的安全係數是非常低的,因此APP加固就有了意義:應用加固之後可以有效減少反編譯、二次打包、植入廣告***等操作。
傳統加固
第一代加固技術採用的是Dex加密存儲,解密時落地;落地之後通過自定義的DexClassLoader將解密出的Dex加載到內存中,然後程序運行該文件(Dex是APK的Java代碼經過編譯後生成的文件,可以簡單理解爲Java的邏輯)。
其脫殼方式很簡單:因爲Dex加密是整體進行的,解密時還會落地。可以通過HOOK文件操作(Read、Write、Delete)將Dex文件脫殼出來,通過反編譯工具分析,從而得到APP的核心邏輯。
之後對第一代版本進行了升級,與未升級版相比:Dex加密存儲方式相同,但解密時不落地;解密之後在內存中通過自定義DexClassLoader進行加載。升級版本的脫殼方法也比較簡單,主要採用內存Dump方法,將文件寫到磁盤中,通過HOOK dvmDexFilePartial的方式達到脫殼目的。
第二代加固方式採用的是Dex Method方法抽離,Dex在內存中加載時不連續。其原理是:Method方法通過一些加固方法抽離,APK在運行時,整個Dex會一併修復,然後在內存中運行,也就說在內存中有着完整的Dex代碼。第三代方式與第二代相比同樣是採用Dex Method方法抽離,但Dex執行中動態解密。兩者的差異在於:後者在APK運行時,Dex文件是不進行修復的,而是等到Class被執行時才進行解密。
對第二代和第三代進行脫殼前,需要先了解Dex結構。Dex結構從dex_header開始,在頭部存在Dex的標誌位;然後逐步按結構指向Method結構體,Method結構中的code_off字段最終指向可執行代碼。因此在第二代和第三代的脫殼過程中,需要HOOK DVM虛擬機中很底層的函數,從而拿到需要執行的APK的類,進而得知Class object全部方法;然後在內存中對DEX進行重建,重建之後再將其Dump到本地,得到脫殼之後的Dex文件,便於後續採用工具分析。
除了上述的脫殼方式之外,通用的脫殼機(開源的Zjdroid、DexHunter)也可以輕鬆脫掉大部分殼;並且,由於傳統的加固方式容易被脫殼,導致目前脫殼類教程非常之多。因此,傳統的加固方式面臨着很大的挑戰。
全量混淆
針對層出不窮的脫殼方式。阿里內部經過多次討論後,認爲傳統的加固方式已過時,需要轉變思路:混淆。
ProGuard混淆
在APP發佈前,通常會對應用進行ProGuard混淆,類似上圖的配置。圖中的proguard-android.txt/proguard-rules.pro是ProGuard的混淆規則。在Java中,某些特性如反射調用以及可序列化類等是需要保留的,因此需要人工配置一些複雜的規則。當規則全部配置成功後,對APK進行反編譯,從上圖可以看到某些邏輯被混淆成了a、b、c等,進而大大增加了***逆向分析的難度。
通過混淆可以增加逆向分析的難度,但並不代表着不能分析。上圖是對金山隱私保險箱逆向分析的案例,通過反編譯工具分析,得知金山隱私保險箱對其核心代碼進行了混淆,例如它的類名是a、b、c等形式。由於ProGuard混淆時需要配置很多規則,很多開發人員爲了保障兼容性會保持很多類,導致APK內的邏輯並不全部混淆,進而導致安全性的降低,通常ProGuard混淆率在10%-30%。
爲了解決ProGuard混淆需要配置很多規則導致混淆效率低下的問題,阿里內部研發了全量混淆技術。上圖左側是手淘在未混淆之前的反編譯情況,其中的類、函數名都是一目瞭然的;經過全量混淆之後的效果圖如右側所示:類名全部變成了a、b、c的類型,並且全量混淆幾乎是不用任何配置的,大大降低了使用成本。目前,全量混淆已在線上對外發布。
優化瘦身
隨着APK功能的增加,其體積也在不斷地增大,例如手淘、支付寶等應用達到五十幾兆、遊戲類的APK達到幾百甚至上千兆,進而引發了手機資源存儲、用戶下載流量浪費等問題。因此APK優化瘦身勢在必行。
APK優化瘦身的實現邏輯主要包括:首先,清除Dex文件Debug信息,減少編譯器自動產生函數,優化性能,減少體積;其次,通過Java層攔截技術,對SO進行重新打包壓縮,減少體積;同時,修改Android應用資源名稱,通常資源名稱是帶有實際意義的,通過將帶有實際意義的長文件名修改成上文所示的a、b、c等形式既減少應用體積,又提高了資源保護強度;此外,通過自行開發的7z工具,對簽名後的APK包重新壓縮,達到進一步減少體積的目的。
上圖是阿里內部應用優化瘦身之後對比效果圖,從圖中可以看到手淘、支付寶、釘釘瘦身前後的對比,瘦身效果可以達到10%左右。
上圖是市場上常見應用瘦身前後的對照表,微博、百度地圖等應用優化後的減少百分比可達到百分之十幾;華爲賬號等應用優化瘦身減少率甚至達到40+%。通常應用優化瘦身減少率在15%-20%,具體數值和APK的開發質量有關。
總結
全量混淆和優化瘦身等阿里內部使用的加固方案都是在實際業務強需求下開發的,經歷了數以萬計的APP和用戶測試,其穩定性和可靠性絕對具有保障。
瘦身工具
指定打包某一些資源文件至APK中,清除沒有被引用的資源