browser-exploitation-v8
yaklang/hack-skills
Guide d'exploitation des navigateurs et du moteur V8. À utiliser pour exploiter les vulnérabilités du moteur JavaScript, notamment la confusion de types JIT, l'élimination incorrecte des limites et le contournement du bac à sable V8, afin d'obtenir un contrôle d'exécution (RCE) au niveau du moteur de rendu et de s'échapper du bac à sable dans Chrome/Chromium.
...Développer toutÀ propos browser-exploitation-v8
Un guide de tests de sécurité permettant d'exploiter les vulnérabilités du moteur JavaScript V8 de Google (Chrome/Chromium). Il décrit le pipeline de compilation de V8 : le code source est analysé en un arbre syntaxique abstrait (AST), interprété sous forme de bytecode Ignition, puis optimisé progressivement via Sparkplug, Maglev et le JIT d’optimisation TurboFan, avec une désoptimisation vers le bytecode lorsque la spéculation échoue. Les mécanismes internes fondamentaux sont également documentés : les pointeurs balisés (SMI et objets du tas), la compression des pointeurs qui adresse les objets via un décalage de 32 bits à partir d’une base de cage au sein d’une région de 4 Go, les Maps (classes cachées), les types d’éléments, la barrière d’écriture et le ramasse-miettes Orinoco.
La majeure partie du contenu répertorie les catégories courantes de bogues et les primitives utilisées pour les exploiter. Parmi ces catégories de bogues figurent la confusion de types JIT, l’élimination incorrecte des vérifications de limites, la confusion de chaîne de prototypes, les bogues de réduction et de typage de TurboFan, les conditions de concurrence sur les SharedArrayBuffer et les erreurs « off-by-one » dans les fonctions intégrées. À partir d’un bug de corruption de mémoire, il construit les primitives classiques « addrof » et « fakeobj » (en confondant les tableaux d’objets et de doubles), passe à la lecture/écriture arbitraire via un magasin de stockage corrompu de type « Float64Array » ou « ArrayBuffer », et couvre l’accès hors limites via des limites de tableaux confondues et des pages WASM RWX.
À utiliser lors de la recherche ou de la reproduction de chaînes d’exploitation RCE du moteur de rendu et d’évasion du bac à sable dans un environnement contrôlé et autorisé. Il explique comment forcer l’optimisation JIT (en appelant une fonction à plusieurs reprises, ou via l’intrinsèque %OptimizeFunctionOnNextCall dans d8) et comment le bac à sable V8 et la compression des pointeurs limitent l’exploitation, puisque les pointeurs de la mémoire de stockage sous-jacente restent confinés dans le bac à sable et qu’une évasion distincte de celui-ci est nécessaire pour accéder à l’intégralité de la mémoire du processus. Les liens connexes renvoient vers les techniques d’évasion de la sandbox, l’exploitation du tas, les débordements de pile et ROP, ainsi que le contournement de la protection binaire, avec une référence plus approfondie dans le fichier V8_EXPLOITATION_PATTERNS.md.
FAQ
Quelles catégories de bogues V8 ce guide couvre-t-il ?
La confusion de types JIT, l’élimination incorrecte des vérifications de limites, la confusion de chaînes de prototypes, les bogues de réduction et de typage TurboFan, les conditions de concurrence SharedArrayBuffer et les erreurs « off-by-one » dans les fonctions intégrées.
Quelles sont les primitives d’exploitation principales décrites dans ce guide ?
addrof (divulgation de l’adresse d’un objet) et fakeobj (fabrication d’une référence d’objet), obtenus en confondant les tableaux d’éléments d’objets et les tableaux d’éléments de type double, puis combinés pour permettre des lectures/écritures arbitraires via un magasin de sauvegarde Float64Array ou ArrayBuffer corrompu.
Comment le bac à sable V8 et la compression des pointeurs affectent-ils l’exploitation ?
Étant donné que, depuis la version 8.0 de V8, les objets sont adressés par un décalage de 32 bits à partir d'une base de « cage » au sein d'une région de 4 Go, et que les zones de stockage sous-jacentes des ArrayBuffer sont des pointeurs de sandbox, l'accès complet à la mémoire du processus nécessite une échappement de la sandbox distincte.
Comment forcer l’optimisation JIT d’une fonction à des fins de test ?
Appelez-la plusieurs fois (par exemple 100 000 itérations) pour déclencher TurboFan, ou dans le shell d8, utilisez l’intrinsèque %OptimizeFunctionOnNextCall avant de l’appeler.
À quelles compétences connexes cela fait-il référence ?
techniques d’échappement du bac à sable (échappement du rendu IPC/Mojo), exploitation du tas, débordement de pile et ROP, contournement de la protection binaire, ainsi qu’une référence avancée V8_EXPLOITATION_PATTERNS.md pour des modèles détaillés.
Tous les fichiers
2fichiersV8_EXPLOITATION_PATTERNS.md8,9KoAfficherSKILL.md11,5 KoAfficherAI 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 bytecodeKey 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 data2. 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 timesfor (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 objectfunction 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 referencefunction 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 layoutlet 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/Wfunction 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 objectlet 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_storeis 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 pagelet 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 debuggingd8 --allow-natives-syntax exploit.js # Enable V8 intrinsics (%DebugPrint, etc.)d8 --trace-turbo exploit.js # Dump TurboFan IRd8 --print-opt-code exploit.js # Print optimized machine code# Turbolizer: visual TurboFan IR graph# Chrome DevTools Memory panel: heap snapshots# Build V8 for debugginggit clone https://chromium.googlesource.com/v8/v8.gitgclient syncgn 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) Installer browser-exploitation-v8
Téléchargez et décompressez les fichiers de compétences dans votre répertoire .claude/skills/.
Télécharger le ZIPClonez le dépôt et copiez les fichiers de compétence dans votre projet.
git clone https://github.com/yaklang/hack-skills/blob/main/skills/browser-exploitation-v8/SKILL.md # Copy SKILL.md to your .claude/skills/ directory
Copier





Maison
