概述
代碼混淆技術可以增加代碼的複雜性和模糊性,從而提高攻擊者分析代碼的難度。代碼混淆有以下幾個方面的作用:
- 保護知識產權:代碼混淆防止他人輕易複製和竊取軟件代碼,增加逆向工程難度。
- 防止逆向工程:逆向工程是分析軟件以瞭解其工作原理和實現細節的過程。代碼混淆可增加逆向工程的難度,保護應用程序免受惡意修改或破壞。
- 提高安全性:代碼混淆減少漏洞和安全風險,增加攻擊者利用漏洞的難度。
- 降低反盜版和欺詐風險:混淆代碼可增加攻擊者破解軟件許可驗證系統或修改代碼繞過付費機制的難度,從而減少盜版和欺詐。
針對工程源碼的混淆提高破解難度,縮短類和成員名稱,減小應用大小。
混淆開啓
從DevEco Studio版本4.0 Beta1開始,hvigor插件提供代碼混淆功能。開啓混淆的條件如下:
- 工程為Stage模型
- 在Release編譯模式下
- 模塊build-profile.json5文件中開啓混淆配置
注意:“enable”默認為“false”,默認不開啓代碼混淆功能。
滿足開啓混淆的條件後,選擇目標模塊,點擊 Build -> Make Module 開始編譯。
如果工程或模塊是Static Library,則該工程或模塊是一個HAR。
構建HAR時有以下三種方式:
- 以Debug模式構建HAR,會直接打包源碼,不進行代碼混淆。
- 以Release模式構建HAR,會編譯、混淆並壓縮代碼。
- 構建字節碼格式的HAR。開啓混淆時,編譯器會先對源碼中間文件進行混淆,再生成abc字節碼。
圖1DevEco Studio選擇release編譯模式
圖2DevEco Studio指定模塊編譯
混淆配置能力
編譯選項
若按照上述編譯流程開啓代碼混淆,在 DevEco Studio 5.0.3.600 之前的版本,默認僅混淆參數名和局部變量名。從 DevEco Studio 5.0.3.600 版本起,默認啓用四項推薦的混淆選項:-enable-property-obfuscation、-enable-toplevel-obfuscation、-enable-filename-obfuscation 和 -enable-export-obfuscation。開發者可以根據需要進一步修改混淆配置。
混淆配置
在每個模塊下都能找到 build-profile.json5 文件,如下圖所示。可以在此文件中配置是否開啓混淆及混淆配置文件。
圖3編譯配置文件
新建工程時,每個模塊下都有 obfuscation-rules.txt 文件,用於配置混淆。
圖4混淆配置文件
在上圖中,obfuscation-rules.txt文件中添加了-enable-property-obfuscation和-enable-toplevel-obfuscation開關,表示已啓用屬性混淆和頂層作用域名稱混淆。
DevEco Studio混淆現有選項及功能描述如下:
混淆選項
| 混淆自定義選項名稱 | 功能簡述 |
|---|---|
| -disable-obfuscation | 關閉混淆 |
| -enable-property-obfuscation | 屬性混淆 |
| -enable-toplevel-obfuscation | 頂層作用域名稱混淆 |
| -enable-filename-obfuscation | 文件名混淆 |
| -enable-export-obfuscation | export導出名稱與屬性混淆 |
| -compact | 代碼壓縮 |
| -remove-log | 刪除console.*方法 |
| -print-namecache filepath | 指定路徑輸出namecache.json文件及內容 |
| -apply-namecache filepath | 複用指定的名稱緩存文件 |
| -remove-comments | 刪除註釋 |
保留選項
| 混淆自定義選項名稱 | 功能簡述 |
|---|---|
| -keep-property-nam | 保留屬性名 |
| -keep-global-name | 保留頂層作用域和導出元素的名稱 |
| -keep-file-name | 保留指定的文件/文件夾的名稱 |
| -keep-dts | 讀取指定.d.ts文件中的名稱作為白名單 |
| -keep-comments | 保留編譯生成的聲明文件中class, function, namespace, enum, struct, interface, module, type及屬性上方的JsDoc註釋 |
| -keep | 保留指定相對路徑中的所有名稱(例如變量名、類名、屬性名等) |
| 通配符 | 名稱類和路徑類的保留選項支持通配符 |
混淆選項具體的使用方法和樣例代碼可以參考代碼混淆
混淆優化建議
開發人員混淆工程時,發現緩存文件或SDK中的文件中存在大量未混淆的源碼名稱。原因包括以下兩類:
- 混淆選項開啓較少;開啓-enable-property-obfuscation、-enable-toplevel-obfuscation、-enable-export-obfuscation、-enable-filename-obfuscation選項。
- 源碼名稱與系統白名單、語言白名單重名;添加後綴避開白名單。
混淆規則合併策略
在編譯一個模塊時,生效的混淆規則是當前編譯模塊混淆規則和依賴模塊混淆規則的合併結果。具體規則請參考:混淆規則合併策略
查看混淆結果
開發人員在編譯模塊的build目錄中可找到編譯和混淆生成的緩存文件、名稱映射表及系統API白名單文件。
- 源碼編譯及混淆緩存文件目錄:build/[…]/release/模塊名
-
混淆名稱映射表及系統API白名單目錄:build/[…]/release/obfuscation
- 名稱映射表文件:nameCache.json,記錄源碼名稱映射。
- 系統API白名單文件:systemApiCache.json,記錄SDK接口與屬性名稱。
圖5DevEco Studio編譯產物與緩存文件
調試
代碼經過混淆工具處理後,名稱會發生更改,這可能導致運行時崩潰堆棧日誌難以理解,因為堆棧與源代碼不完全一致。如果未保留調試信息,行號及名稱更改將導致無法準確定位問題。此外,啓用-enable-property-obfuscation、-enable-toplevel-obfuscation等選項後,代碼混淆可能會引發運行時崩潰或功能性錯誤。開發人員需要還原報錯堆棧,排查並配置白名單以確保功能正常。
函數調用棧還原
經過混淆的應用程序中代碼名稱會發生更改,因此報錯棧與源碼不完全一致,crash時打印的報錯棧會難以理解,如何處理請參考報錯棧還原
反混淆工具hstack
hstack需要將Node.js配置到環境變量中,詳細使用説明請參考hstack
使用第三方加固
在HarmonyOS提供的代碼混淆能力之外,開發者還可以使用第三方安全廠商提供的高級混淆和加固能力。多家安全加固廠商已經啓動了HarmonyOS開發,開發者可以根據需求選擇這些安全廠商的服務。開發者需要與第三方安全廠商自行溝通合作方式和範圍,本文檔不做詳細説明。具體的官方與第三方代碼混淆能力的關係如下:
| 特性 | 特性描述 | HarmonyOS | 三方 |
|---|---|---|---|
| 名稱混淆 | 混淆類、字段、屬性、方法和文件名。 | √ | √ |
| 控制混淆 | 混淆方法內的控制流以防禦自動或手動代碼分析,包括虛假控制流和控制流扁平化。 | × | √ |
| 指令替換 | 通過將簡單的算術和邏輯表達式轉換為難以分析的代碼來保護專有公式。 | × | √ |
| 數據混淆 | 加密敏感字符串,以防止通過嘗試搜索的黑客攻擊,也用來加密類、 asset 文件、資源文件和 Native 庫 | × | √ |
| 代碼虛擬化 | 轉換方法實現為隨機生成虛擬機的指令序列 | × | √ |
| 調用隱藏 | 為訪問敏感的 APIs 添加反射,比如用於簽名校驗和密碼操作的標準APIs | × | √ |
| 移除日誌代碼 | 移除 logging 、調試和測試代碼,以阻止任何利用此信息的企圖 | × | √ |
由於HarmonyOS代碼簽名、應用加密等安全機制的限制,以及應用市場上架審核的純淨安全要求,三方加固廠商提供的安全加固內容必須滿足以下六點要求:
- 不允許隱藏敏感系統API的調用,審核人員必須能夠清晰地看到應用的特性。
- 不允許混淆非自研的SDK。SDK應由SDK廠商自行進行混淆保護。如果非自研SDK被混淆,將會影響應用市場審核相關SDK的指紋信息。
- 通過第三方安全加固的應用程序,必須確保不包含惡意行為,以免對生態系統造成影響。此要求為約束性條款,不遵守可能導致應用被下架。
- 不允許使用第三方虛擬機,HarmonyOS系統通過代碼簽名等機制限制動態加載代碼,這可能導致應用無法正常運行。
- 不允許對方舟字節碼文件進行篡改,此方法可能讓應用無法正常運行,以及影響應用市場對應用的純淨安全進行審核。
- 不允許對系統庫使用hook技術,此方法影響應用市場對應用的純淨安全進行審核。