一個 Jailbreak 二進位檔能告訴你什麼(不需要執行它)
用 Ghidra 對 Dopamine jailbreak 進行靜態分析。6,660 個字串加上幾個 class 名稱,就足以還原完整的四階段攻擊鏈——kernel exploit、filesystem remount、sandbox escape、persistence——一行程式碼都不需要執行。
多數安全分析關注的是程式碼執行時做了什麼。
靜態分析問的是另一個問題:程式碼在執行之前,說了什麼?
這篇文章是用 Ghidra 分析 Dopamine jailbreak 二進位檔的完整紀錄。沒有裝置、沒有 debugger、沒有執行。只有一個 2.5MB 的 Mach-O 檔案,以及它自己透露的資訊。
這個二進位檔
Dopamine 是一個 arm64 Mach-O 可執行檔——每一個 iOS app 和系統二進位檔的標準格式。檔案大小 2,612,288 bytes,內含 6,660 個嵌入字串,其中 610 個與安全性相關。
這個數字很重要。字串在 stripping 之後仍然存活。即使一個二進位檔完全沒有可見的 symbol,C 字串和 Objective-C selector 仍然存在於 __TEXT/__cstring 和 __DATA/__objc_selrefs。這是第一個要拉出來看的東西。
Binary: Dopamine
Format: Mach-O 64-bit (arm64)
Size: 2,612,288 bytes
Total strings: 6,660
Security-relevant: 610
從 Class 名稱讀出架構
Objective-C metadata 幾乎從不會被 strip 掉。Class 名稱、method selector、ivar 名稱全都存在 __DATA/__objc_classlist 裡,完整地活過整個 build 流程。
只需掃描一遍,class 階層就能告訴你完整的設計:
DOExploitManager — 選擇並執行 kernel exploit
DOExploit — 包裝單一 exploit 的 lifecycle 方法
DOBootstrapper — 管理 filesystem 設定與套件解壓縮
DOEnvironmentManager — 處理 sandbox escape 與權限提升
DOJailbreaker — 協調整個執行鏈
DOJailbreakButton — UI 層(確認這是面向使用者的 app,不是 daemon)
命名慣例(DO 前綴 = Dopamine Object)一致。關注點分離清晰。這不是被混淆的惡意程式——這是一個碰巧要提升 kernel 權限的 release-quality iOS 應用程式。
四個階段
第一階段:Kernel 攻擊
入口點是 DOExploitManager。它的 method 列表揭示了一個基於優先級的 exploit 選擇系統:
+[DOExploitManager sharedManager]
-[DOExploitManager _loadAvailableExploits]
-[DOExploitManager availableExploitsForType:]
-[DOExploitManager preferredKernelExploit]
-[DOExploitManager selectedKernelExploit]
-[DOExploitManager _findPreferredExploitForType:]
以及在新硬體上必要的 PAC/PPL bypass variant:
-[DOExploitManager preferredPACBypass]
-[DOExploitManager preferredPPLBypass]
DOExploit class 用一致的 interface 包裝每一個獨立的 exploit:
-[DOExploit isSupported] — 檢查 iOS 版本相容性
-[DOExploit priority] — 用於選擇排序
-[DOExploit run] — 執行 exploit
-[DOExploit cleanup] — 失敗時處理清理
這是一個 plugin 架構。manager 載入所有打包進去的 exploit,依照支援度和優先級評分,執行最佳的一個。__TEXT/__cstring 中的字串 "kfd" 識別出其中一個打包的 kernel exploit(kfd = kernel file descriptor exploit,在 iOS 16.7.1+ 已被修補)。
第二階段:Filesystem 存取
光有 kernel 權限還不夠——你需要可寫入的 filesystem 存取,才能安裝任何持久化的東西。DOBootstrapper 處理這部分:
-[DOBootstrapper ensurePrivatePrebootIsWritable]
-[DOBootstrapper isPrivatePrebootMountedWritable]
-[DOBootstrapper remountPrivatePrebootWritable:]
/private/preboot 是 iOS 儲存開機關鍵資料的地方。在原廠裝置上它是唯讀的。有了第一階段的 kernel r/w primitive,你可以把它重新 mount 為可寫入——這正是這個 method chain 做的事。
bootstrap 壓縮檔格式在字串中清晰可見:
%@/bootstrap_%@.tar.zst
zstd 壓縮的 tar 壓縮檔,解壓縮到 /private/preboot。完整的下載與解壓縮 pipeline 在 method 列表中一覽無遺:
-[DOBootstrapper bootstrapURL]
-[DOBootstrapper URLSession:downloadTask:didFinishDownloadingToURL:]
-[DOBootstrapper decompressZstd:toTar:]
-[DOBootstrapper extractTar:toPath:]
-[DOBootstrapper fixupPathPermissions]
-[DOBootstrapper finalizeBootstrap]
第三階段:Sandbox 逃脫
Sandbox 是 iOS 主要的 process 隔離機制。從中逃脫需要私有 entitlement——Apple 保留給系統 process 的能力。
這些字串在二進位檔中原文出現:
%com.apple.private.security.no-sandbox
*com.apple.private.mobileinstall.allowedSPI0e
!com.apple.security.network.client
no-sandbox entitlement 完全停用 app sandbox。mobileinstall entitlement 開放存取私有安裝 API。兩者合在一起,讓 process 可以寫入任何地方,並安裝系統級套件。
DOEnvironmentManager 負責這個階段:
-[DOEnvironmentManager runUnsandboxed:]
-[DOEnvironmentManager runAsRoot:]
-[DOEnvironmentManager setPrivatePrebootProtected:]
-[DOEnvironmentManager isPACBypassRequired]
-[DOEnvironmentManager isPPLBypassRequired]
PAC/PPL 檢查在 A12+ 硬體上很重要。Pointer Authentication Code (PAC) 和 Page Protection Layer (PPL) 是讓 kernel 攻擊變得更困難的硬體緩解機制。二進位檔會檢查是否需要這些 bypass,告訴你它是為了同時針對舊(A11 及以前)和新硬體而構建的。
第四階段:持久化
安裝才是區別暫時性 exploit 和 jailbreak 的關鍵。DOBootstrapper 透過 daemon patching 處理持久化:
-[DOBootstrapper patchBasebinDaemonPlist:]
-[DOBootstrapper patchBasebinDaemonPlists]
-[DOBootstrapper installPackageManagers]
-[DOBootstrapper installPackage:]
-[DOBootstrapper createSymlinkAtPath:toPath:createIntermediateDirectories:]
機制是這樣的:launchd 在開機時從系統目錄讀取 .plist 檔案。透過修改這些 plist 讓它們指向 /private/preboot 中的 bootstrap 執行檔,jailbreak 程式碼就會在每次重開機時自動執行——早於大多數安全性檢查。
完整攻擊鏈
App 啟動(受 sandbox 限制,無特殊權限)
│
▼
DOExploitManager
選擇 kfd exploit
────────────────────── 達成 kernel r/w
│
▼
DOBootstrapper
重新 mount /private/preboot 為可寫入
下載 bootstrap_%@.tar.zst
────────────────────── 取得 filesystem 存取
│
▼
DOEnvironmentManager
請求 no-sandbox + mobileinstall entitlement
────────────────────── sandbox 逃脫
│
▼
DOBootstrapper
修補 basebin daemon plist
安裝套件管理器
────────────────────── 重開機後持久存活
每個階段為下一個階段開門。Exploit 給你 kernel 存取;kernel 存取讓你重新 mount filesystem;可寫入的 filesystem 讓你注入 entitlement;entitlement 讓你修補系統 daemon;被修補的 daemon 給你持久化。
這對偵測意味著什麼
如果你在構建詐欺偵測或裝置認證,一台 jailbreak 過的裝置會從根本上改變你的信任模型。這個二進位檔精確地告訴你要尋找哪些痕跡:
Filesystem 痕跡:
- 原廠裝置不應存在的
/private/preboot/下的檔案 - 暫存目錄中的
bootstrap_*.tar.zst /var/lib/basebin/中被修改的 daemon plist
Process 痕跡:
- 在預期 sandbox 之外執行的 process
- 注入的 tweak(被非系統 process 載入的 dylib)
Entitlement 痕跡:
- 聲稱有
no-sandbox但不是系統二進位的 app - 使用者安裝的 app 上的
mobileinstallentitlement
Jailbreak 並不低調。它在每個階段都留下痕跡。問題是你的偵測機制是否在攻擊者有機會隱藏它之前就執行了。
關於混淆
Dopamine 是一個開源專案,它完全不試圖隱藏自己的行為。做同樣事情的商業工具——或試圖繞過 jailbreak 偵測的工具——會有更多混淆:stripped symbol、XOR 過的字串、被拆分的 class 名稱。
分析技術仍然相同。你只是要做更多的重建工作:從算術模式還原常數、在 xref 位置重組被拆分的字串、從 vtable 佈局識別 class 邊界。
靜態分析不需要二進位檔配合,只需要時間。
使用工具:Ghidra 12.0.4、自訂 Python Mach-O parser。二進位檔:從 Dopamine.ipa 中提取的 Dopamine.app。
保持更新
關於行動安全、越獄和 iOS 逆向工程的最新文章。