#### **概述**
我們的APK實際上就是一個ZIP壓縮文件,里面包含有一個classes.dex,我們編譯后生成的程序代碼就全部在那里了,通過apktool等工具可以輕松地將它們反編譯成smali代碼。有了這些反編譯出來的smali代碼之后,我們就可以輕松地了解別人的APK使用的一些技術或者直接修改別人的APK。由于這些APK反編譯工具的存在,我們迫切地希望能有方法去防止別人來反編譯我們的APK,從而保護自己的商業機密和利益。
主要講了三種APK防反編譯技術:
* 添加非法指令;
* 隱藏敏感代碼
* 偽APK加密技術。
此外,還探討了更高級的Dex和Native加殼技術來防止別人反編譯我們的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不一致
> 注:
> vim編輯二進制文件
> 打開文件:`vim -b <file>`
> 編輯文件::%!xxd
> 編輯完成::%!xxd –r
> 保存文件::wq
> dexdump反編譯APK
> `dexdump -d <classes.dex>`
> dexdump驗證checksum
>` dexdump -c <classes.dex>`
> apktool反編譯APK
> `apktool d <apkfile> <dir>`
* 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個字節修改為以下指令

> 注:第一條指令3200 0900表示向前跳9個code unit,一個code unit占2個字節,即向前跳18個字節,從3200 0900的偏移向前算,剛好就是下一條指令fill-array-data的payload偏移處,即hhhh hhhh后面那個字節
> 第二條指令中的00000005表示其payload位于5個code uint之后,即10個字節之后,即hhhh hhhh開始的那個字節
* 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類設置為已驗證
> 注:用dexdump -f命令查看classes.dex的頭部信息
* 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文件,從而實現加密處理
- 前言
- Android組件設計思想
- Android源代碼開發和調試環境搭建
- Android源代碼下載和編譯
- Android源代碼情景分析法
- Android源代碼調試分析法
- 手把手教你為手機編譯ROM
- 在Ubuntu上下載、編譯和安裝Android最新源代碼
- 在Ubuntu上下載、編譯和安裝Android最新內核源代碼(Linux Kernel)
- 如何單獨編譯Android源代碼中的模塊
- 在Ubuntu上為Android系統編寫Linux內核驅動程序
- 在Ubuntu上為Android系統內置C可執行程序測試Linux內核驅動程序
- 在Ubuntu上為Android增加硬件抽象層(HAL)模塊訪問Linux內核驅動程序
- 在Ubuntu為Android硬件抽象層(HAL)模塊編寫JNI方法提供Java訪問硬件服務接口
- 在Ubuntu上為Android系統的Application Frameworks層增加硬件訪問服務
- 在Ubuntu上為Android系統內置Java應用程序測試Application Frameworks層的硬件服務
- Android源代碼倉庫及其管理工具Repo分析
- Android編譯系統簡要介紹和學習計劃
- Android編譯系統環境初始化過程分析
- Android源代碼編譯命令m/mm/mmm/make分析
- Android系統鏡像文件的打包過程分析
- 從CM刷機過程和原理分析Android系統結構
- Android系統架構概述
- Android系統整體架構
- android專用驅動
- Android硬件抽象層HAL
- Android應用程序組件
- Android應用程序框架
- Android用戶界面架構
- Android虛擬機之Dalvik虛擬機
- Android硬件抽象層
- Android硬件抽象層(HAL)概要介紹和學習計劃
- Android專用驅動
- Android Logger驅動系統
- Android日志系統驅動程序Logger源代碼分析
- Android應用程序框架層和系統運行庫層日志系統源代碼分析
- Android日志系統Logcat源代碼簡要分析
- Android Binder驅動系統
- Android進程間通信(IPC)機制Binder簡要介紹和學習計劃
- 淺談Service Manager成為Android進程間通信(IPC)機制Binder守護進程之路
- 淺談Android系統進程間通信(IPC)機制Binder中的Server和Client獲得Service Manager接口之路
- Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析
- Android系統進程間通信(IPC)機制Binder中的Client獲得Server遠程接口過程源代碼分析
- Android系統進程間通信Binder機制在應用程序框架層的Java接口源代碼分析
- Android Ashmem驅動系統
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)簡要介紹和學習計劃
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)驅動程序源代碼分析
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)在進程間共享的原理分析
- Android系統匿名共享內存(Anonymous Shared Memory)C++調用接口分析
- Android應用程序進程管理
- Android應用程序進程啟動過程的源代碼分析
- Android系統進程Zygote啟動過程的源代碼分析
- Android系統默認Home應用程序(Launcher)的啟動過程源代碼分析
- Android應用程序消息機制
- Android應用程序消息處理機制(Looper、Handler)分析
- Android應用程序線程消息循環模型分析
- Android應用程序輸入事件分發和處理機制
- Android應用程序鍵盤(Keyboard)消息處理機制分析
- Android應用程序UI架構
- Android系統的開機畫面顯示過程分析
- Android幀緩沖區(Frame Buffer)硬件抽象層(HAL)模塊Gralloc的實現原理分析
- SurfaceFlinger
- Android系統Surface機制的SurfaceFlinger服務
- SurfaceFlinger服務簡要介紹和學習計劃
- 啟動過程分析
- 對幀緩沖區(Frame Buffer)的管理分析
- 線程模型分析
- 渲染應用程序UI的過程分析
- Android應用程序與SurfaceFlinger服務的關系
- 概述和學習計劃
- 連接過程分析
- 共享UI元數據(SharedClient)的創建過程分析
- 創建Surface的過程分析
- 渲染Surface的過程分析
- Android應用程序窗口(Activity)
- 實現框架簡要介紹和學習計劃
- 運行上下文環境(Context)的創建過程分析
- 窗口對象(Window)的創建過程分析
- 視圖對象(View)的創建過程分析
- 與WindowManagerService服務的連接過程分析
- 繪圖表面(Surface)的創建過程分析
- 測量(Measure)、布局(Layout)和繪制(Draw)過程分析
- WindowManagerService
- WindowManagerService的簡要介紹和學習計劃
- 計算Activity窗口大小的過程分析
- 對窗口的組織方式分析
- 對輸入法窗口(Input Method Window)的管理分析
- 對壁紙窗口(Wallpaper Window)的管理分析
- 計算窗口Z軸位置的過程分析
- 顯示Activity組件的啟動窗口(Starting Window)的過程分析
- 切換Activity窗口(App Transition)的過程分析
- 顯示窗口動畫的原理分析
- Android控件TextView的實現原理分析
- Android視圖SurfaceView的實現原理分析
- Android應用程序UI硬件加速渲染
- 簡要介紹和學習計劃
- 環境初始化過程分析
- 預加載資源地圖集服務(Asset Atlas Service)分析
- Display List構建過程分析
- Display List渲染過程分析
- 動畫執行過程分析
- Android應用程序資源管理框架
- Android資源管理框架(Asset Manager)
- Asset Manager 簡要介紹和學習計劃
- 編譯和打包過程分析
- Asset Manager的創建過程分析
- 查找過程分析
- Dalvik虛擬機和ART虛擬機
- Dalvik虛擬機
- Dalvik虛擬機簡要介紹和學習計劃
- Dalvik虛擬機的啟動過程分析
- Dalvik虛擬機的運行過程分析
- Dalvik虛擬機JNI方法的注冊過程分析
- Dalvik虛擬機進程和線程的創建過程分析
- Dalvik虛擬機垃圾收集機制簡要介紹和學習計劃
- Dalvik虛擬機Java堆創建過程分析
- Dalvik虛擬機為新創建對象分配內存的過程分析
- Dalvik虛擬機垃圾收集(GC)過程分析
- ART虛擬機
- Android ART運行時無縫替換Dalvik虛擬機的過程分析
- Android運行時ART簡要介紹和學習計劃
- Android運行時ART加載OAT文件的過程分析
- Android運行時ART加載類和方法的過程分析
- Android運行時ART執行類方法的過程分析
- ART運行時垃圾收集機制簡要介紹和學習計劃
- ART運行時Java堆創建過程分析
- ART運行時為新創建對象分配內存的過程分析
- ART運行時垃圾收集(GC)過程分析
- ART運行時Compacting GC簡要介紹和學習計劃
- ART運行時Compacting GC堆創建過程分析
- ART運行時Compacting GC為新創建對象分配內存的過程分析
- ART運行時Semi-Space(SS)和Generational Semi-Space(GSS)GC執行過程分析
- ART運行時Mark-Compact( MC)GC執行過程分析
- ART運行時Foreground GC和Background GC切換過程分析
- Android安全機制
- SEAndroid安全機制簡要介紹和學習計劃
- SEAndroid安全機制框架分析
- SEAndroid安全機制中的文件安全上下文關聯分析
- SEAndroid安全機制中的進程安全上下文關聯分析
- SEAndroid安全機制對Android屬性訪問的保護分析
- SEAndroid安全機制對Binder IPC的保護分析
- 從NDK在非Root手機上的調試原理探討Android的安全機制
- APK防反編譯
- Android視頻硬解穩定性問題探討和處理
- Android系統的智能指針(輕量級指針、強指針和弱指針)的實現原理分析
- Android應用程序安裝過程源代碼分析
- Android應用程序啟動過程源代碼分析
- 四大組件源代碼分析
- Activity
- Android應用程序的Activity啟動過程簡要介紹和學習計劃
- Android應用程序內部啟動Activity過程(startActivity)的源代碼分析
- 解開Android應用程序組件Activity的"singleTask"之謎
- Android應用程序在新的進程中啟動新的Activity的方法和過程分析
- Service
- Android應用程序綁定服務(bindService)的過程源代碼分析
- ContentProvider
- Android應用程序組件Content Provider簡要介紹和學習計劃
- Android應用程序組件Content Provider應用實例
- Android應用程序組件Content Provider的啟動過程源代碼分析
- Android應用程序組件Content Provider在應用程序之間共享數據的原理分析
- Android應用程序組件Content Provider的共享數據更新通知機制分析
- BroadcastReceiver
- Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃
- Android應用程序注冊廣播接收器(registerReceiver)的過程分析
- Android應用程序發送廣播(sendBroadcast)的過程分析