歡迎通路網易雲社群,了解更多網易技術産品營運經驗。
網易資深安全工程師鐘亞平在今年的安卓巴士全球開發者論壇上做了《安卓APP逆向與保護》的演講(完整演講内容請見這裡:一文了解安卓APP逆向分析與保護機制),其中就談到了關于代碼混淆的問題。
Java代碼是非常容易反編譯的,為了很好地保護Java源代碼,開發者往往會對編譯好的class檔案進行混淆處理。
混淆就是對釋出出去的程式進行重新組織和處理,使得處理後的代碼與處理前代碼完成相同的功能,而混淆後的代碼很難被反編譯,即使反編譯成功也很難得出程式的真正語義。ProGuard就是一個混淆代碼的開源項目,能夠對位元組碼進行混淆、縮減體積、優化等處理。
Proguard處理流程圖如下所示,包含壓縮、優化、混淆、預檢四個主要環節:
<
1. 壓縮(Shrink):檢測并移除代碼中無用的類、字段、方法和特性(Attribute);
2. 優化(Optimize):對位元組碼進行優化,移除無用的指令。優化代碼,非入口節點類會加上private/static/final,沒有用到的參數會被删除,一些方法可能會變成内聯代碼;
3. 混淆(Obfuscate):使用a、b、c、d這樣簡短而無意義的名稱,對類、字段和方法進行重命名;
4. 預檢(Preveirfy):在Java平台上對處理後的代碼進行預檢,確定加載的class檔案是可執行的。
利用Proguard,對Dex2jar進行反編譯處理後的Apk效果示例:
處理前
Proguard處理後
Proguard混淆器不僅能夠保護代碼,而且能夠精簡編譯後的程式大小,減少記憶體占用。
混淆代碼逆向分析
如果想要反編譯混淆代碼,鐘亞平分享了一個國外的工具DEGUADR,它能夠通過統計的方式來解混淆。雖然這個工具的正确率達不到100%,但是能在一定程度上幫助反編譯代碼。
使用DEGUADR解混淆的示例:
com.xxxxx.common.util.CryptoUtil網站也提供了一種反編譯服務,如下所示:
java.lang.String a(byte[]) -> encodeToString
java.lang.String a(byte[],boolean,java.lang.String) -> a
byte[] a(byte[],byte[]) -> encrypt
byte[] b(byte[]) -> getKey
byte[] b(byte[],byte[]) -> decrypt
byte[] d(java.lang.String) -> getKey
java.lang.String a(byte,char[]) -> a
java.lang.String a(java.io.File) -> getHash
java.lang.String a(java.lang.String) -> c
java.lang.String b(java.lang.String) -> encode
對 DEX 檔案進行加殼防護仍然是需要的,我們可以選擇整體 DEX 加強或者拆分 DEX 加強的方式,隐藏源碼防止直接性的反編譯。拆分 DEX 加強需要注意 DEX 檔案的資料結構,選取 classdata 和 classcode 這兩部分,即使拆分出來也不會洩露 class 資料和位元組碼資料,反編譯出來也不完整,安全性較高。尤其是虛拟機加強的方式,對位元組做一些變化處理,即使把替換後的資料恢複了,也不會變形成為之前的位元組碼,安全系數較高。
網易雲 Android 應用加強免費試用,有效防止應用被逆向分析、反編譯、二次打包,核心功能包括 DEX 加強,SO 加密保護,記憶體防 Dump 保護,防調試器,防模拟器等。