☰
拆解Vue-After-Free的RCE原理:UAF、数组长度腐败到任意读写,一步步走向代码执行
2026/10/16 3:02:47 网站建设 项目流程

【免费下载链接】vue-after-free

PlayStation Vue code execution exploit

项目地址:https://gitcode.com/gh_mirrors/vu/vue-after-free
点击查看免费下载

Vue-After-Free 是一个针对 PlayStation 4 上 PS Vue 应用的越狱(Jailbreak)工具,它的核心是一条从 JS 引擎 UAF 漏洞出发、经由数组长度腐败获得任意读写(ARW),最终实现任意代码执行(RCE)的完整利用链。本文带你逐步拆解这条链路的每个关键环节:如何触发释放后使用、如何腐败对象结构、如何伪造对象获得任意读写、如何泄露 JSC/libc/libkernel 地址,以及它最终如何与内核漏洞利用(Lapse / Netctrl)交接,完成对主机的完全控制。

一、项目背景:一条完整利用链的组成

PS Vue 是索尼曾经推出的云电视应用,运行在 PS4 的沙箱(Sandbox)环境中。Vue-After-Free 利用其内置 JS 引擎(JSC)的内存安全漏洞逃出沙箱,再衔接内核漏洞利用完成越狱。

整个利用链可以概括为下面这张表:

阶段关键操作源码位置
1. 触发 UAF利用 for-in/for-of 变量覆盖缺陷让引擎写入已释放对象defs.ts
2. 对象泄露向 uaf_view 中喷入带 marker 的数组,在残留内存中定位目标对象userland.ts
3. 数组长度腐败把目标数组的 indexing header 改写为 0x1337,制造越界视图userland.ts
4. 任意读写(ARW)伪造 Uint32Array 的 master/slave 结构,直接映射任意地址userland.ts
5. 地址泄露从 Math.min 顺藤摸瓜得到 JSC、libc、libkernel、eboot 基址userland.ts
6. 系统调用注册 write/open/dup 等 syscall,构建 ROP 链kernel.ts
7. 内核利用自动检测固件版本,选择 Lapse(7.00–12.02)或 Netctrl(12.50–13.00)loader.ts

各固件版本的支持范围如下(来自 README.md):

vue-after-free(用户态)Lapse(内核利用)Netctrl(内核利用)
5.05–13.041.01–12.021.01–13.00

二、UAF 是如何触发的:几行代码的"障眼法"

整个利用链的起点在 defs.ts 中的make_uaf函数,它只有寥寥数行,却非常精巧:

export function make_uaf (arr: DataView) { const o = {} for (let i in { xx: '' }) { for (i of [arr]); o[i] } }

它的原理利用了 JSC 引擎在处理for...in时的一个缺陷:内层for...of会覆盖外层循环变量 i,使i的引用指向内层迭代器。当引擎继续执行for...in的属性枚举时,会向内层迭代器对象写入"下一个属性名",而这个对象在for...of结束的瞬间已被释放——于是引擎把字符串写入了一块已释放的堆内存(即 UAF 写入原语),这块内存随后可以被攻击者重新分配。

loader.ts 加载 exploit 后,userland.ts 立即执行make_uaf(uaf_view),其中uaf_view是一个 1MB 的 DataView。调用结束后,uaf_view底层内存里就可能残留着被 UAF 写入"污染"的对象结构——利用链从这里开始展开。

三、寻找"标记数组":Spray 与 Marker 技巧

UAF 写入落在哪里并不确定,所以项目采用了经典的**堆喷射(Heap Spray)**手法:

  1. 喷射候选数组:创建 0x1000 个长度为 0x100 的数组,全部填充为0x13371337(见 userland.ts);
  2. 构造 marker:项目定义了两个 64 位特征值——marker = 0xFFFF0000_13371337与indexing_header = 0x100_100。如果某个被释放对象恰好是这些数组之一,UAF 写入会把它的对象头(indexing header)和长度(length)按特征模式残留在uaf_view中;
  3. 扫描定位:代码从偏移 8 开始,每 16 字节检查一次uaf_view,一旦同时命中两个特征值,就锁定了"标记数组"的偏移marked_arr_offset(userland.ts)。

这一步把不确定的 UAF 转化成了确定性的内存布局认知:我们知道了堆中某个对象的确切位置和结构。

四、数组长度腐败:把"越界访问"变成合法操作

锁定目标后,项目把该数组的indexing header 改写为 0x1337(userland.ts)。在 JSC 中,索引型数组的 header 同时编码了长度和类型,因此改写之后,spray[i].length会报告为0x1337(4919)——一个远大于实际堆分配的大小。

这意味着通过spray[i]访问越界下标时,引擎会认为这是合法的,直接读取数组堆块之后的任意相邻内存。这就得到了最基本的**任意读(Read)**原语。

小技巧:这一步是典型的"腐败数组长度 → 越界读"手法,在浏览器漏洞利用中非常常见,Vue-After-Free 只是把它搬到了 PS4 沙箱环境。

五、伪造 Uint32Array:从任意读到任意读写(ARW)

只有读还不够。为了获得写能力,项目构造了一个假的Uint32Array对象(userland.ts):

  • 伪造 js_cell:手工拼装 64 位的 JSC 对象头,依次设置IndexingType、JSType::Uint32ArrayType、TypeInfo标志和CellType,并递增 structure_id 试错,直到spray[i][1]真的被引擎识别为Uint32Array(instanceof判断成功即命中);
  • 伪造 butterfly:JS 对象的内部数据缓冲区(butterfly)被指向攻击者控制的slave(一个 DataView),引擎从此认为这个 typed array 的底层内存就在 slave 中;
  • 修复结构细节:通过已有的任意读原语直接修补 master/slave 结构的若干字段(如setUint8(6, 0xA0)、写入长度标志等),让对象在 GC 和类型检查下保持稳定。

至此mem.view(addr)可以直接读写任意虚拟地址——任意读写(ARW)达成。这也是整条链的转折点:从"破坏内存"变成了"操控内存"。

六、地址泄露:定位 JSC、libc、libkernel 与 eboot

PS4 的 ASLR 要求所有基址必须在运行时动态泄露。userland.ts 采用了一条非常优雅的"顺藤摸瓜"路线:

泄露步骤方法
1mem.addrof(Math.min)得到内置函数对象地址
2读其 scope(偏移 0x10)与 native executable(偏移 0x18)
3从 native executable 的函数指针减去固定偏移0xC6380,得到JSC 基址jsc_addr
4在 JSC 中读取_error、strerror符号,反推出libc 基址(strerror - 0x40410)
5由jsmaf.gc的 native invoke 指针减去0x39330,得到eboot 基址
6utils.base_addr(_error_addr)得到libkernel 基址

拿到全部基址后,项目注册了 ROP 基础设施(rop.init(jsc_addr)),并注册了_error、strerror、getpid、dup、write、open、close等函数包装(userland.ts),最后通过syscalls.init(libkernel_addr)建立完整的系统调用映射表——沙箱内可以直接发起原始 syscall 了。

七、与内核利用的交接:Lapse 与 Netctrl

用户态 ARW + syscall 只是"逃出沙箱"的前置条件,真正的越狱还要靠内核漏洞。loader.ts 中有一段自动调度逻辑:

  • 7.00–12.02:加载并运行 lapse.ts——基于 AIO 竞态条件的内核漏洞利用(由 c0w-ar 移植);
  • 12.50–13.00:加载 netctrl_c0w_twins.ts——针对新版固件的内核利用(Netctrl/Poopsploit);
  • 用户也可在配置中通过jb_behavior强制指定任一策略。

Lapse 成功后,kernel.ts 中的jailbreak_shared接管:

  1. 修补 ucred:把进程的cr_uid/cr_ruid改为 0、清除沙箱标志,实现 root + 沙箱逃逸;
  2. 劫持 sysent[661](kexec):改其入口为jmp rsigadget,配合jitshm_create创建 RWX 共享内存,写入选定固件版本的内核补丁 shellcode(kernel.ts 内置了 5.00 到 13.00 各版本的补丁字节);
  3. 验证补丁:回读 mmap RWX 补丁位(0x33 → 0x37)、尝试分配 RWX 内存确认可执行;
  4. 加载 payload:通过 binloader.ts 从 USB 或/data/目录加载payload.bin(如 HEN / GoldHEN),完成最终越狱。

如果利用失败(UAF 落点未命中、竞态超时等),界面会显示失败提示并建议重启重试——这也是该 exploit 依赖一定概率的内存布局、失败时可重复尝试的原因。

八、源码导读:从哪些文件开始看

如果你想深入阅读源码,建议按利用链顺序:

模块说明路径
加载器exploit 编排、固件版本检测、Lapse/Netctrl 调度loader.ts
UAF 原语make_uaf与结构注册defs.ts
用户态利用spray、长度腐败、ARW、地址泄露userland.ts
内核工具库内核偏移表、kexec 补丁、syscall 封装kernel.ts
Lapse 内核利用AIO 竞态利用移植lapse.ts
Netctrl 内核利用12.50–13.00 固件利用netctrl_c0w_twins.ts
Payload 加载从 USB 加载 payload.binbinloader.ts
类型/工具定义BigInt、mem、rop、syscalls 等基础设施types.ts

辅助工具方面,encrypt_aes_files.py 与 decrypt_aes_files.py 用于加解密仓库中的 AES 混淆文件,module-remover/index.js 则用于构建时移除特定模块。

九、总结:一条教科书级的浏览器利用链

Vue-After-Free 的 RCE 路径可以浓缩为一句话:

UAF 写入 → 堆喷定位 → 长度腐败越界读 → 伪造 Uint32Array 得 ARW → 符号链泄露基址 → 原始 syscall + ROP → Lapse/Netctrl 内核利用 → 沙箱逃逸 + 加载 payload。

它对新手的学习价值在于:每一步都是漏洞利用领域的经典技法(UAF、spray、corruption、fake object、ASLR bypass、ROP),且代码组织清晰、注释明确,是研究"从内存破坏到代码执行"完整链路的优秀开源样本。当然,本文仅作技术原理分析——此类技术只应用于自己拥有或已获授权的设备,未经授权对他人主机进行越狱或漏洞利用可能违反当地法律。

【免费下载链接】vue-after-free

PlayStation Vue code execution exploit

项目地址:https://gitcode.com/gh_mirrors/vu/vue-after-free
点击查看免费下载
上一篇:用代码驱动 Paneru 窗口管理器:send-cmd 命令全清单与 JSON 状态订阅实战指南
下一篇:Monibuca 存储架构解析:Local/S3/OSS/COS 多后端统一接口设计,一套接口搞定对象存储

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询