browser-exploitation-v8
yaklang/hack-skills
Руководство по эксплуатации уязвимостей браузера и движка V8. Используется при эксплуатации уязвимостей движка JavaScript, включая путаницу типов JIT, некорректное устранение границ и обход песочницы V8, для получения удалённого выполнения кода (RCE) в рендерере и выхода из песочницы в Chrome/Chromium.
...Расширить всеО browser-exploitation-v8
Руководство по тестированию безопасности, посвящённое эксплуатации уязвимостей движка JavaScript в V8 от Google (Chrome/Chromium). В нём описан конвейер компиляции V8 — исходный код преобразуется в AST, интерпретируется как байт-код Ignition, затем постепенно оптимизируется с помощью Sparkplug, Maglev и оптимизирующего JIT-компилятора TurboFan, с деоптимизацией обратно в байт-код в случае сбоя спекулятивной оптимизации. Также описаны базовые внутренние механизмы: тегированные указатели (SMI и объекты кучи), сжатие указателей, при котором объекты адресуются через 32-битное смещение от базы «клетки» внутри области размером 4 ГБ, Maps (скрытые классы), типы элементов, барьер записи и сборщик мусора Orinoco.
Большая часть материала посвящена каталогизации распространённых классов ошибок и примитивов, используемых для их злоупотребления. Класс ошибок включает путаницу типов JIT, некорректное устранение проверок границ, путаницу в цепочке прототипов, ошибки редукции и типизации TurboFan, условия гонки в SharedArrayBuffer и ошибки «off-by-one» во встроенных функциях. На основе ошибки повреждения памяти в ней создаются классические примитивы addrof и fakeobj (путём смешения массивов объектов-элементов и массивов элементов типа double), что приводит к произвольному чтению/записи через повреждённый резервный массив Float64Array или ArrayBuffer, а также охватывает доступ за пределы границ посредством смешения границ массивов и страниц WASM RWX.
Используйте его при исследовании или воспроизведении цепочек RCE рендерера и выхода из песочницы в контролируемой и авторизованной среде. Здесь объясняется, как принудительно запустить JIT-оптимизацию (многократный вызов функции или использование встроенной функции %OptimizeFunctionOnNextCall в d8), а также как песочница V8 и сжатие указателей ограничивают возможности эксплуатации уязвимости, поскольку указатели на внутреннее хранилище остаются в пределах «клетки», и для полного доступа к памяти процесса требуется отдельный выход из песочницы. Связанные ссылки ведут к техникам выхода из песочницы, эксплуатации кучи, переполнению стека и ROP, а также обходу защиты бинарных файлов, с более подробным справочником V8_EXPLOITATION_PATTERNS.md.
Часто задаваемые вопросы
Какие классы ошибок V8 охватывает данное руководство?
Путаница типов JIT, некорректное устранение проверок границ, путаница цепочки прототипов, ошибки редукции и типизации TurboFan, условия гонки SharedArrayBuffer и ошибки «off-by-one» во встроенных функциях.
Какие основные примитивы эксплуатации в нём описаны?
addrof (утечка адреса объекта) и fakeobj (создание фальшивой ссылки на объект), реализуемые за счёт путаницы между массивами объектов и массивами элементов типа double, а затем объединяемые в произвольное чтение/запись через повреждённый внутренний массив Float64Array или ArrayBuffer.
Как песочница V8 и сжатие указателей влияют на эксплуатацию уязвимостей?
Поскольку в V8 8.0 объекты адресуются с помощью 32-битного смещения от базы «клетки» в пределах области объёмом 4 ГБ, а хранилища ArrayBuffer представляют собой указатели песочницы, для получения полного доступа к памяти процесса требуется отдельный выход из песочницы.
Как заставить функцию пройти JIT-оптимизацию для тестирования?
Вызовите её многократно (например, 100 000 итераций), чтобы запустить TurboFan, или в оболочке d8 используйте встроенную функцию %OptimizeFunctionOnNextCall перед вызовом.
На какие связанные навыки это указывает?
техники выхода из песочницы (IPC/выход из рендерера Mojo), эксплуатация кучи, переполнение стека и ROP, а также обход защиты двоичных файлов, плюс подробное справочное руководство V8_EXPLOITATION_PATTERNS.md с подробными шаблонами.
Все файлы
2файла V8_EXPLOITATION_PATTERNS.md 8,9КБ Просмотреть SKILL.md 11,5 КБ Просмотреть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 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) Установить browser-exploitation-v8
Скачайте файлы навыков и распакуйте их в каталог .claude/skills/.
Скачать ZIPКлонируйте репозиторий и скопируйте файлы навыка в свой проект.
git clone https://github.com/yaklang/hack-skills/blob/main/skills/browser-exploitation-v8/SKILL.md # Copy SKILL.md to your .claude/skills/ directory
Копировать





Дом
