一、前言
隨著Android應用被破解和被盜版的案例越來越多,程式安全逐漸引起使用者的重視。
在激烈的攻防過程中,安全保護手段不僅限於程式碼,還有資原始檔。這是由於資原始檔會暴露出大量敏感資訊和破解線索,一旦被篡改或被刪除,程式將無法正常執行。
加固是保護程式安全的重要途徑之一,更是程式合規上架的必然要求。本文針對第三方apk的資源保護(加密)方案進行簡單的梳理,以幫助使用者更好地選擇和使用加固產品。
二、資原始檔介紹
先來看看資原始檔的解釋。安卓資原始檔一般指res和assets目錄下的檔案,而res和assets資原始檔在apk編譯和執行過程中存在一定差異。
1、res資源
res目錄只能有一層子目錄,且子目錄必須是預定義的,如res/layout、res/values等。
res會在R.java生成索引ID,沒用到的資源不會被打包進apk中,但res/raw資料夾除外。
res用getResource()訪問。
2、assets資源
assets資源目錄可以自定義。
assets資源會原封不動地打包到apk中。
assets用AssetsManager訪問。
三、資原始檔保護方案
打包後的apk如需資源加密,只能透過在執行過程中hook相關的函式介面進行解密,來達到保護效果。市場上的資原始檔保護方案可分為定製方案和通用方案兩大類。兩種方案各有優劣。
1、# 定製方案 #
定製方案的使用場景多樣,一般根據檔案型別分類,包括指令碼類和資源類。其中,js,lua,python等指令碼,根據不同的指令碼引擎做加密,同時利用hook或重寫直譯器的方式重新解析指令碼進行解密,而u3d資源,png,jpg圖片等資源,可能會涉及資源讀取方式或基於圖片格式制定的加密方式,加密後需在特定時機進行解密。
# 優點 #
a、針對性強,只針對特殊型別的檔案,如js,lua指令碼,u3d資源
b、相容性好
c、效能好
# 缺點#
a、保護範圍小
b、每種型別的資源需針對分析載入原理,開發維護成本高
2、# 通用方案 #
# 優點 #
a、保護範圍廣
b、維護成本小
# 缺點#
a、相容性無法完全保證
b、開發難度大
c、效能低
因定製保護的方案每個型別都能單獨成為一個專題進行介紹,無法簡單地透過一篇檔案說明,下面主要介紹通用的資源保護方案的實現以及難點分析。
四、通用方案
(一)實現原理
apk本質上是個zip格式檔案,讀取資原始檔即讀取zip裡的檔案。因此,其原理離不開讀檔案和解壓兩個過程。如果能在讀檔案或者解壓兩個過程進行hook,並對檔案內容進行解密,就能達到資源保護的效果。簡單來講,一個是針對libz.so進行hook,一個是針對libc.so進行hook。
1、Libz hook
(1)# 優點 #
a、使用標準api,特徵穩定,易於hook
b、處理只限於libz.so即可達到目的,簡單且高效
c、使用got hook,功能穩定性好
(2)# 缺點#
a、使用者程式碼必須滿足壓縮資料,使用libz中的uncompress函式進行解壓並讀取資料
b、第三方sdk或遊戲引擎因將libz靜態編譯到so中,可能不滿足使用條件
2、Libc hook
(1)# 優點 #
a、hook範圍廣,適配更多情景
(2)# 缺點#
a、全範圍hook會導致效能降低
b、採用inline hook,可能引發相容性問題
從通用性來說hook libc的方案可以相容更多使用者使用場景,但只要使用者使用標準介面,不進行自定義或不以第三方不明確的sdk做資源讀取,hook libz也能適配大部分的資源讀取。
(二)通用方案難點分析
1、# 四個條件 #
對於加固功能的開發者而言,開發資源加固功能的前提是,資源讀取的流程可被hook,否則檔案無法在合適的時機進行解密。由此可見,使用者在選擇做資源保護時,要確定是否滿足以下四個條件。以下條件皆圍繞一個核心,即程式讀取apk的資源過程需要保證能被hook。如果條件滿足,使用通用的手段保護資原始檔在理論上是可行的。
# 未使用任何第三方sdk讀取資源,可能存在不確定隱私
# 自研so未自實現解壓方法
# 自研的so中實現瞭解壓方法,且透過libc直接讀取apk
#自研的so中實現瞭解壓方法,未做so加固,記憶體中so結構完整
2、# 三個問題 #
在使用者apk實現滿足以上規則的同時,資源加密還需解決如下問題:
(1)# 檔案如何加密和解密
答:檔案的加密和解密方法影響到加固後apk的結構,需要定義一套加密規則保證加密後zip格式的完整性,以及解密後檔案的完整性。
(2)# 解壓檔案是否存在校驗
答:因apk的zip頭部儲存瞭解壓後的檔案crc以及長度,需要考慮部分情況下,檔案解密後,crc和長度是否需要校驗的情況。
(3)# Android碎片化嚴重的情況下如何相容各種機型
答:需要考慮不同版本下,Android系統下libc和libz的實現變化,保證相容性。
3、# 四種不相容 #
值得注意的是,對於在記憶體裡做解密操作的功能而言,一些無法相容的情況仍然存在,下面指出幾個常見的不相容問題。
(1)# 自研so實現zip解壓方法,且使用匯編讀取檔案
答:這種情況,無明顯hook特徵,無法正常解密檔案。
(2)# 使用者so實現zip解壓,且使用so加固破壞了so的記憶體結構
答:在對so進行hook的前提下,破壞so結構可能無法進行hook並解密。
(3)# 使用者加固資源後,熱更新機制為服務端讀取apk包並和記憶體讀取的apk進行hash對比
答:資源加密最重要的一個效果就是無法靜態分析,也就是第三方工具讀取apk會讀到密文。但記憶體中讀取apk是明文,必然導致檔案無法正常校驗。
(4)# res資源因其種類較為複雜,且包含包名、圖示檔案
答:這些檔案是需要被系統讀取,而非由apk執行時解密,做加密前需要過濾出哪些檔案不能加密。
五、結語
綜上所述,安卓程式在推進資源保護之前,仍面臨一些準備工作,如檢查是否滿足條件與是否存在相關問題。
在做資源的保護時,結合自身產品情況,儘可能做到以下兩點:一是針對性,資源和產品相關,不可盲目加密所有資源,應基於產品特性選擇合適的加固方案。二是可控性,讓資源的讀寫方式標準化,採用第三方框架讀寫資源可能會導致相容性問題。
程式App風險事件頻發,在落實加固保護的過程中,將資原始檔的保護放在優先位置的重要性不言而喻。