跳至主要内容
全部题解
团队题解Pwn

No Hack No CTF 2026

Web3JS

从虚拟机栈越界读取,构造伪造对象并重定向原生回调。

发布日期
类别
Pwn / 二进制利用

Web3JS 提供了一个带有 evm() 接口的定制 JavaScript shell。它的栈操作直接信任攻击者控制的索引,因此能够读取 VM 栈逻辑边界之外的 JavaScript 值。

第一次泄漏虽然有用,但真正的关键,是在 V8 的指针压缩笼区内将它转化为稳定的对象操作原语。

构建 addrof

将对象压入定制栈,再读取相邻的原始槽位,就能暴露其带标签表示。处理标签后,即可得到可重复使用的取址原语:

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

让承载对象持续存活,可以避免垃圾回收在漏洞利用构建期间破坏内存布局。

将伪造标签转化为 fakeobj

反向操作利用一个写入了指定带标签指针的越界槽位。通过 VM 读取这个槽位,会让引擎把该值解释成 JavaScript 对象。

有了 addroffakeobj,我们便能在真实后备存储的可控偏移处布置一个伪造的紧凑双精度数组头。重定向它的元素字段后,就能读写指针压缩笼区内的地址。

重定向原生回调

该 shell 暴露了多个原生辅助函数。检查其中一个辅助函数的对象关系后,我们从它的 JSFunction 追踪到对应的模板元数据与回调指针。

漏洞利用没有猜测绝对地址,而是比较来自同一二进制文件的同类辅助函数,并复用它们相对一致的元数据布局。我们临时修改一个无害辅助函数,让它的分派路径抵达隐藏的命令处理器。

调用被重定向的辅助函数后,漏洞利用恢复了原始数据。这既避免了退出阶段崩溃,也让原语更容易在本地验证。

关键结论

定制 VM 桥接层中的一个小型越界错误,可能一次跨越多层信任边界:JavaScript 值变成原始带标签数据,带标签数据变成伪造对象,而伪造对象最终触及原生回调元数据。

赛事页面:CTFtime 上的 No Hack No CTF 2026