網頁

2017年1月7日 星期六

Android Apk防反編譯技術

【ReD】Android Apk防反編譯技術

本文分為四大部分

  • 添加非法指令
  • 隱藏敏感代碼
  • 偽APK加密技術
  • 總結和思考

添加非法指令
Step 1: 在APK包含一個無關類Bomb,該類有一個成員函數drop
Step 2: 將APK的classes.dex解壓出來,並且用dexdump進行反編譯,找到Bomb.drop在classes.dex的偏移
Step 3: 用vim以二進制方式打開classes.dex,轉到Bomb.drop的偏移處,將前兩個字節修改為FF FF(非法指令)
Step 4: 重新打包和簽名APK,用adb install命令安裝,日誌提示checksum不一致
Step 5: 用dexdump驗證APK的checksum,並且將正確的checksum替換原classes.dex的checksum
Step 6: 重新打包和簽名APK,用adb install安裝,DONE

隱藏敏感代碼
Step 1:在APK包含一個無關類Bomb,該類有一個成員函數drop,前面留有18個字節的垃圾指令
Step 2:將APK的classes.dex解壓出來,並且用dexdump進行反編譯,找到Bomb.drop在classes.dex的偏移
Step 3:用vim以二進制方式打開classes.dex,轉到Bomb.drop的偏移處,將前18個字節修改為以下指令
 
Step 4: 用dexdump查看classes.dex的頭部信息,找到class_def的偏移,以及Bomb類的class index
Step 5: class_def的偏移,加上Bomb類的class index乘以32的積,即可得到用來描述Bomb類的class_def結構體偏移,再往前4個字節,即為其access_flags,將它的第16位設置為1,一般就是設置為0x10001,也就是將0100 0000設置為0100 0100,這樣可以將Bomb類設置為已驗證
Step 6: 用dexdump驗證APK的checksum,並且將正確的checksum替換原classes.dex的checksum
Step 7: 重新打包和簽名APK,用adb install安裝,DONE

偽Apk加密技術
ZIP中的每一個文件都有一個2字節大小的全局方式位標記,其中第0位表示是否加密
如果ZIP中的一個文件標誌為加密,那麼在解壓時,就需要指定解壓密碼
APK默認都是不加密的,也就是APK在安裝解壓時,它裡面的文件的加密位標誌都會被忽略
Apktool發現APK是加密的時候,會拋出一個異常出來
利用上述差異,就可以給APK設置一個加密標誌,但不對其進行加密,從而阻止Apktool反編譯


總結
APK在安裝時,會對APK進行驗證,主要是checksum驗證和指令合法性驗證
安裝通過驗證的APK會被標記為已驗證,並且會被優化
安裝沒有通過驗證的APK仍然會被成功安裝,但是它會被標記為未驗證
未驗證的APK的某個類在被加載時,會被驗證,一旦驗證失敗,就會拋出異常
反編譯工具會對APK的所有類進行驗證,不管這個類安裝後會不會被加載,一旦驗證不通過,就會拋出異常

根據以上的APK安裝、驗證和加載流程,就可以通過以下兩個方法來阻止反編譯:
包含一個有非法指令(不能執行)的類,但是這個類保證永遠不會被加載
包含一個有非法指令(能執行)的類,同時將該類預先設置為已驗證的

思考
反編譯工具,如Apktool,採用的是線性掃描算法來分析指令流,當遇到非法指令時,就會異常退出
如果遇到非法指令只是簡單忽略,那麼就仍能正常工作
如果反編譯工具採用的遞歸遍曆算法來分析指令流,那麼就能將fill-array-data之類的偽指令反編譯出來
如果反編譯工具忽略掉APK的加密標誌,那麼就能將偽加密的APK也反編譯出來
如果反編譯工具更智能一些,那麼一切皆可反編譯…….
怎麼辦?


Dex Code加密
Android 4.0及以上的DexFile提供有加載內存dex文件的隱藏接口openDexFile和defineClass,通過它們就可以從內存中加載一個dex文件,在真正加載這塊內存之前,可以對其進行加密
Android 4.0之前的版本,可以用libdvm的導出函數來實現上述相同的功能
Native Code加密
系統中的每一個so文件都是由/system/bin/linker來進行加載和解析的
參考/system/bin/linker,實現一個自己的linker,這個linker可以加載和解析內存so文件,從而實現加密處理

沒有留言:

張貼留言

有任何問題隨時可以留言請教我