Turboflan picoCTF 2021 Solution

Published: April 2, 2026

Description

A very fast program. Find the vulnerability and exploit it to read the flag.

Download the V8 build and the challenge patch/diff.

bash
wget https://mercury.picoctf.net/static/.../d8
bash
wget https://mercury.picoctf.net/static/.../turboflan.diff
bash
chmod +x d8
  1. Step 1Read the V8 patch and identify the typer bug
    Apply the diff against the matching V8 commit and read it carefully. The bug is almost always a handful of lines in src/compiler/typer.cc, src/compiler/operation-typer.cc, or a new builtin that lies about its return range.
    bash
    less turboflan.diff
    bash
    # Look for: return Type::Range(min, max, zone)  with wrong bounds
    bash
    # Or a new builtin marked kNoWrite that actually mutates state
    Learn more

    V8 Turbofan, not C heap."Turboflan" is a pun on Turbofan, V8's optimizing JIT compiler for JavaScript. The vulnerability lives in JS-level reasoning, not in glibc heap structures.

    Typer bug families that show up in CTF:

    • Wrong range: a typer rule reports a tighter range than reality. Turbofan elides CheckBounds based on the false range, then at runtime the value escapes the range and reads/writes past the array.
    • Missing side-effect annotation: a function is marked pure when it isn't. Turbofan reorders side-effecting code across it, breaking a check.
    • NaN / -0 confusion: the typer drops a special-value case and the JIT-compiled code mis-handles it.
    • Speculation guard skipped: a bounds check is removed because the typer claimed the index was already in range.

    See real-world bug patterns for adjacent JS sandbox-escape ideas.

  2. Step 2Trigger JIT compilation and force the bug
    Standard recipe: write a small attack function, force optimization via repeated calls (or %OptimizeFunctionOnNextCall in d8 with --allow-natives-syntax), then call once with an input the typer mispredicts.
    bash
    # Run d8 with native syntax to force optimization:
    ./d8 --allow-natives-syntax exploit.js
    bash
    # Sketch of a typer-confusion exploit (specifics depend on the diff):
    # function leak(x) { return arr[x]; }
    # for (let i = 0; i < 0x10000; i++) leak(0);
    # %OptimizeFunctionOnNextCall(leak);
    # leak(badValue);   // typer thinks in-range, runtime is out-of-range -> OOB read
    Learn more

    From OOB read to flag. A typical chain: corrupt a JSArray's elements pointer (or its length) to fabricate a fake array that addresses arbitrary memory; build addrOf/read/write primitives; locate %FunctionPrototype% code object; flip a writable but executable page; drop shellcode; call. readFile("flag.txt") in d8 is often available too, sidestepping shellcode entirely.

Flag

picoCTF{...}

Turboflan is a V8 Turbofan JIT typer-confusion challenge, not a glibc heap bug. The published walkthroughs from this round are sparse and depend on the exact diff shipped, so treat this writeup as the framing rather than a turn-key exploit.

Want more picoCTF 2021 writeups?

Useful tools for Binary Exploitation

Related reading

What to try next