Skip to content
0xBURGER CTF Team
MY 18:48
All writeups
TEAM WRITEUPpwn

No Hack No CTF 2026

Web3JS

From an out-of-bounds VM stack read to a forged object and native callback retargeting.

Published
Category
pwn

Web3JS shipped a customized JavaScript shell with an evm() interface. Its stack operations trusted attacker-controlled indexes, so a JavaScript value could be read beyond the logical end of the VM stack.

The first leak was useful, but the solve depended on turning it into stable object primitives inside V8's compressed-pointer cage.

Build addrof

Pushing an object into the custom stack and reading the adjacent raw slot exposed its tagged representation. After accounting for the tag, this became a repeatable address-of primitive:

function addrof(object) {
  vm.push(object)
  return untag(vm.get(outOfBoundsIndex))
}

Keeping the carrier objects alive prevented garbage collection from invalidating the layout while the exploit was assembled.

Turn a forged tag into fakeobj

The reverse direction used an out-of-bounds slot seeded with a chosen tagged pointer. Reading that slot through the VM made the engine interpret the value as a JavaScript object.

With addrof and fakeobj, we placed a forged packed-double array header at a controlled offset inside a real backing store. Repointing its elements field gave read and write access to addresses inside the pointer-compression cage.

Retarget a native callback

The shell exposed native helper functions. Inspecting one helper's object graph led from its JSFunction to the corresponding template metadata and callback pointer.

Rather than guessing an absolute address, the exploit compared sibling helpers from the same binary and reused their relative metadata layout. It temporarily changed one benign helper so its dispatch path reached the hidden command handler.

After invoking the retargeted helper, the exploit restored the original words. That avoided teardown crashes and made the primitive easier to verify locally.

Takeaway

A small bounds error in a custom VM bridge can cross several trust layers at once: JavaScript values become raw tagged words, tagged words become forged objects, and forged objects eventually reach native callback metadata.

Event page: No Hack No CTF 2026 on CTFtime.