SpiderMonkey漏洞利用入门
背景介绍
本文记录了针对SpiderMonkey JavaScript Shell解释器和Mozilla Firefox在Windows 10 RS5 64位环境下的三个漏洞利用开发过程。作者从零开始,逐步深入浏览器漏洞利用领域,通过三个不同阶段的利用代码展示了技术演进过程。
环境搭建
首先需要设置调试环境,建议在虚拟机中进行。获取Mozilla的gecko-dev代码库:
|
|
应用blaze.patch补丁文件,该补丁为Array对象添加了blaze方法,允许将数组长度修改为420,从而产生越界访问漏洞。
使用MozillaBuild工具链编译JavaScript Shell解释器js.exe,支持调试和发布两种构建模式。
SpiderMonkey内部机制
JS::Values和JSObjects
JavaScript对象在内存中的布局使用JS::Value结构,高17位用于编码类型信息,低47位存储实际值或对象指针。数组对象在内存中连续存储,包含长度、容量和初始化长度等信息。
形状(Shapes)和槽(Slots)
形状对象描述对象的属性和类信息,通过链表结构连接。属性值存储在对象的槽中,可以通过形状对象找到对应的存储位置。
漏洞利用开发
基础利用(basic.js)
第一个利用针对特定的js.exe构建,包含大量硬编码偏移。通过越界访问相邻的TypedArray对象,构建内存读写原语和控制流劫持能力。
关键步骤包括:
- 构建任意内存访问原语
- 构建对象地址泄露原语
- 劫持控制流
- 栈转移
- 泄露ntdll基地址
- 执行任意本地代码
改进利用(kaizen.js)
第二个利用改进了可靠性和动态解析能力:
- 提高内存访问原语的可靠性
- 动态解析导出函数地址
- 利用基线JIT生成ROP gadget
高级利用(ifrit.js)
最终利用针对Firefox浏览器:
- 编译Windows 64位Firefox版本
- 配置Firefox开发环境
- 利用JIT编译完整本地Payload
技术细节
内存操作原语
通过越界写入TypedArray的DATA_SLOT和LENGTH_SLOT,实现任意内存读写能力。使用Int64.js库处理64位整数操作。
控制流劫持
通过覆盖js::ObjectGroup的clasp_字段,最终修改cOps函数指针,在添加对象属性时触发控制流劫持。
JIT代码重用
利用基线JIT没有常量盲化的特性,通过精心构造的JavaScript函数,让JIT引擎生成特定的机器指令片段,实现代码复用攻击。
工具和资源
提供了完整的代码库和相关工具:
- sm.js调试器扩展
- 三个利用的源代码
- JavaScript Shell调试和发布构建
- Firefox二进制文件和符号信息
- Payload生成脚本
结论
通过三个逐步改进的漏洞利用,展示了从基础内存操作到高级JIT代码重用的完整技术演进过程。文章提供了深入的技术细节和实际代码示例,为浏览器漏洞利用研究提供了有价值的参考。
所有相关材料和代码可在blazefox GitHub仓库中找到,鼓励读者亲自实践和探索。