【免费下载链接】vue-after-free
PlayStation Vue code execution exploit
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.04 | 1.01–12.02 | 1.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)**手法:
- 喷射候选数组:创建 0x1000 个长度为 0x100 的数组,全部填充为
0x13371337(见 userland.ts); - 构造 marker:项目定义了两个 64 位特征值——
marker = 0xFFFF0000_13371337与indexing_header = 0x100_100。如果某个被释放对象恰好是这些数组之一,UAF 写入会把它的对象头(indexing header)和长度(length)按特征模式残留在uaf_view中; - 扫描定位:代码从偏移 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 采用了一条非常优雅的"顺藤摸瓜"路线:
| 泄露步骤 | 方法 |
|---|---|
| 1 | mem.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 基址 |
| 6 | utils.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接管:
- 修补 ucred:把进程的
cr_uid/cr_ruid改为 0、清除沙箱标志,实现 root + 沙箱逃逸; - 劫持 sysent[661](kexec):改其入口为
jmp rsigadget,配合jitshm_create创建 RWX 共享内存,写入选定固件版本的内核补丁 shellcode(kernel.ts 内置了 5.00 到 13.00 各版本的补丁字节); - 验证补丁:回读 mmap RWX 补丁位(0x33 → 0x37)、尝试分配 RWX 内存确认可执行;
- 加载 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.bin | binloader.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
相关推荐
PS4破解利器Vue-After-Free完全指南:一个PS Vue应用如何从UAF漏洞走向完整越狱
PS4破解利器Vue After Free完全指南:一个PS Vue应用如何从UAF漏洞走向完整越狱 Vue After Free 是一个基于 PlayStat
ctf-wiki 堆利用实战:Linux ptmalloc2 Use After Free(UAF)原理与 HackNote 利用详解
ctf wiki 堆利用实战:Linux ptmalloc2 Use After Free(UAF)原理与 HackNote 利用详解 本文以 ctf wiki
网络安全文档知识库教程es-toolkit 的 flattenDeep:一行代码深度展平任意嵌套数组
es toolkit 的 flattenDeep:一行代码深度展平任意嵌套数组 flattenDeep 是 es toolkit 数组工具集中用于递归展平嵌套数
前端后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考