APP加固攻防梳理
背景
現在市面上對APP的安全合規管控越來越嚴格了,也就要求了APP在上架之前一定要做合規檢測和加固處理。對APP就是加固的好處,可以提高APP的安全性,提高APP被逆向分析破解的門檻,同時通過加固保護可以提高過安全合規的檢測。由于APP加固技術不斷被攻破情況,因此加固技術也是不斷在快速迭代的過程。現在市面上的加固產品的還是比較多的,并且各個加固技術產品都有其各自優缺點,但是加固產品的所采用技術去有很多共性的地方。下面就對加固和脫殼對抗方案做些梳理總結。
加固準備
APP加固主要是對APP中的dex文件、so文件、資源文件等進行保護,因此這邊對這APP中的關鍵文件結構做簡短梳理總結。
App文件的結構

Dex文件結構

SO文件結構

簡單的APP加固原理的流程
- 加固的代碼先運行,進行初始化工作;
- 加固的代碼開始解密被保護的核心代碼;
- 加固的代碼開始加載解密后的核心代碼;
- 加固的代碼把控制權轉交給核心代碼。
第一代加固和脫殼
第一代加固技術主要做了進行對app的dex文件進行保護和做了一些簡單的反調試保護。
Dex保護:
Dex文件整體加密、字符串加密、自定義DexClassLoader。
動態防護:
ptrace反調試、TracePid值校驗反調試。
第一代加固的出現也同時出現各種對加固技術的攻破。從而出現了各種對抗加固的脫殼方法。
最突出的是直接從內存dump出dex完整結構脫殼原理:
程序在啟動過程中,要保證程序正常運行,那么加固殼會自動解密受保護的dex文件并完成加載,基于這個子解密的原理,我可以選擇在dex加載完成這個時機點,將其dump下來。從而實現第一層防護殼、加密殼的脫殼。
下面羅列幾個脫殼方案
- 緩存脫殼法:
第一代的某些加固產品,安裝包是加密壓縮的,安裝后回在data/dalvik-cache目錄下生成解密的odex文件,這時候只需要獲取odex文件進行做為分析的突破點。
- 內存 dump脫殼法
通過工具:IDA Pro + dumpDEX
1、通過/proc/%d/maps獲取內存映射
2、在內存中查找關鍵字 dex.035或dex.036
3、手動dump查找到的數據。
- 動態調試脫殼法
1、通過基于IDA的android_server的代理方式進行附加app。
2、再IDA中下dvmDexFileOpenPartial 斷點,確認要dump的起始地址和大小。
3、用ida的腳本方式進行dump出原始數據。
- HOOK脫殼法
Hook脫殼法一般都是基于frida和xposed這兩個框架進行做hook操作的。
這種hook脫殼法:先需要進行分析app應用,找到可以進行hook的函數,
然后在選擇用的順手的、適用的frida或xposed框架進行 hook。
(xposed是java編譯,適用于java層hook;frida適用于java層和native層hook)。
通過對關鍵函數dvmDexFileOpenPartial進行hook實現脫殼。
也可以通過xposed框架hook ClassLoader的loadClass函數實現脫殼。
- 定制系統脫殼法
主要是通過修改系統源碼中的關鍵函數,接著將修改后的源碼重新編譯并進行刷機。
例如通過修改系統dvmdexfileopenpartial函數的關鍵邏輯。在函數里面修改寫入我們想要實現的功能。
第二代加固和脫殼
由于第一代加固是整體性加固的,因此只要dump到關鍵點后,就可以完整的獲取到dex整個內容。由于第一代殼的缺點,隨之而來的就是進行對APP中關鍵類的抽取技術。那么第二代加固主要進行如下的功能點。
- DEX保護: DEX類抽取、DEX動態加載、SO動態加載
- So保護:SO加密
- 動態防護: 反調試,防HOOK
- 資源文件保護:本地數據庫保護、本地文件保護
脫殼技術方案
脫殼原理:
主動調用類中的每一個方法,并實現函數指令的還原
常見的加固廠商的指令抽取的實現方式主要又兩大類,一種是指令代碼在dex文件原便宜位置處還原,另外一種就是隨機分配,通過修訂偏移的方式,使程序在執行過程中通過修定的便宜找到函數指令;android程序在執行過程,使用到類時候,都需要進行加載,而在加載過程中,函數指令就會進行指令還原或修訂函數指令指向的位置,我們可以利用這個時機,將代碼拷貝到原代碼位置,進而實現類抽取殼的脫殼。
下面羅列針對第二代加固的脫殼法
- 內存重組脫殼法
通過內存中dex文件的格式,找到完整的dex文件,將其組合到一起。
- 內存dump脫殼法
通過工具:IDA Pro + dumpDEX
1、通過/proc/%d/maps獲取內存映射
2、在內存中查找關鍵字 dex.035或dex.036
3、手動dump查找到的數據。
也可以直接用frida中的dump腳本進行內存dump脫殼。
- 動態調試脫殼法
1、通過基于IDA的android_server的代理方式進行附加app。
2、再IDA中下dvmDexFileOpenPartial 斷點,確認要dump的起始地址和大小。
3、用ida的腳本方式進行dump出原始數據。
- HOOK脫殼法
Hook脫殼法一般都是基于frida和xposed這兩個框架進行做hook操作的。
這種hook脫殼法:先需要進行分析app應用,找到可以進行hook的函數,
然后在選擇用的順手的、適用的frida或xposed框架進行 對關鍵函數hook。
(xposed是java編譯,適用于java層hook;frida適用于java層和native層hook)。
通過對關鍵函數memcmp、dexFileParse進行hook實現脫殼。
也可以通過hook ClassLoader的loadClass函數實現脫殼。
- 定制系統脫殼法
主要是通過修改系統源碼中的關鍵函數,接著將修改后的源碼重新編譯并進行刷機。
例如通過修改系統memcmp、dexFileParse函數的關鍵邏輯。在函數里面修改寫入我們想要實現的功能。
第三代加固和脫殼
第三代加固方案主要進行對函數進行做抽取,并進行做動態加解密方式,下面羅列關鍵的加固技術點
- DEX保護: DEX Method代碼抽取、Dex Method動態解密
- SO保護:SO加殼
- 動態防護:防內存dump、防系統核心庫HOOK
- 資源文件保護:H5文件保護
APP函數抽取指令流程:
1、解析原始dex文件格式,保存所有方法的代碼結構體信息。
2、通過傳入需要置空指令的方法和類名,檢索到其代碼結構體信息。
3、通過方法的代碼結構體信息獲取指令個數和偏移地址,構造空指令集,然后覆蓋原始指令。
4、重新計算dex文件的checksum和signature信息,回寫到頭部信息中。
脫殼方法:
- HOOK脫殼法
通過利用frida框架進行hook關鍵函數DexFile,OpenFile、dexFindClass等關鍵函數實現脫殼。
- 定制系統脫殼法
通過修改系統源碼中的關鍵函數如DexFile、OpenFile、dexFindClass函數的關鍵邏輯,然后進行重編系統。
在ART中通過修改定制dex2oat法進行脫殼。
第四代加固和脫殼
現在市面上強度最強加固方案實屬代碼虛擬化保護的方案。通過將程序的代碼編譯為虛擬機指令也就是虛擬機代碼(也就是自定義的代碼集),通過虛擬機cpu解釋并執行的一種方式。
下面羅列下關鍵的加固技術點
- DEX保護:代碼VMP虛擬化保護
- SO保護:基于llvm的SO文件保護(ELF VMP)
脫殼方案
- HOOK脫殼法
- 可以基于frida框架進行針對不同虛擬機(dalvik和art)實現進行hook。
- 定制系統脫殼法
總結
利用frida脫殼方法:
1、通過找到DexFile對象(art虛擬機是DexFile對象,dalvik虛擬機下是DexFile結構體),獲取到DEX文件的起始地址和大小,然后dump下來。
常見能夠找到DexFile對象的函數有LoadMethod、ResolveMethod函數等,能直接獲取到DEX起始地址和大小的常見函數有openMemory、dexparse、dexFileParse、dvmDexFileOpenPartial等函數。frida_unpack便是其中的代表作。
2、利用frida的搜索內存,通過匹配DEX文件的特征,例如DEX文件的文件頭中的魔法值---dex.035或dex.036這個特征。frida-Dexdump便是這種脫殼方法的代表作。
自定義系統和定制的android設備方法:
1、采用定制的android的rom,可以有效對抗市場中所有的加密殼、類抽取類型的殼;相比開源的脫殼工具,大體都是基于hook框架,例如frida、Xposed;目前大多加固廠商已經對hook框架,以及脫殼框架的特征進行了安全檢測,這會導致app啟動失敗,從而實現脫殼失敗,而通過自定義的rom,沒有依賴hook框架,也就沒有相關框架特征代碼標志,所以脫殼成功率會比較高。
2、采用定制android硬件設備優勢,基于android的開源性,google公司每次發布新版的rom,都會率先在Pixel、Nexus系列的設備上最早應用,這也導致大部分安全從業者為了提升工作效率,間隔的采用自定義ROM實現方式,在市場中開源脫殼ROM,大多是需要刷Nexus、Pixel系列機型,這也使得大多加固廠商對這Nexus、Pixel系列機型做特殊,更深層次的安全防護檢測,以此保證程序在運行過程中的安全性。通過定制android硬件設備,沒有Nexus、pixel設備相關特征,更能提高脫殼的成功率。