Chrome v8 pwn 前置
字数 1668 2025-08-20 18:18:05

V8 JavaScript 引擎深入解析与PWN前置知识

1. V8引擎概述

V8是Google用C++开发的开源JavaScript引擎,用于Chromium和Node.js等项目中执行JavaScript代码。V8的主要特点包括:

  • 采用Just-in-time (JIT)编译技术
  • 将JS代码编译为机器码执行以提高性能
  • 编译后的二进制名称为d8而非v8

V8处理流程

  1. 解析(Parser):将JS代码转换为抽象语法树(AST)
  2. 解释(Ignition):将AST转换为字节码并在VM中执行
  3. 非优化编译(Sparkplug):对频繁执行的代码生成简单机器码
  4. 优化编译(TurboFan):对热点代码进行深度优化

2. 环境搭建

系统要求

推荐使用Ubuntu 20.04,18.04可能存在兼容性问题

依赖安装

sudo apt install bison cdbs curl flex g++ git python vim pkg-config

工具链安装

  1. 获取depot_tools:
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
echo 'export PATH=$PATH:"/path/to/depot_tools"' >> ~/.bashrc
cd depot_tools
git reset --hard 138bff28
export DEPOT_TOOLS_UPDATE=0
  1. 安装ninja:
git clone https://github.com/ninja-build/ninja.git
cd ninja && ./configure.py --bootstrap && cd ..
echo 'export PATH=$PATH:"/path/to/ninja"' >> ~/.bashrc

V8源码获取与编译

fetch v8  # 或fetch --force v8
cd v8
gclient sync -D
git checkout 7.6.303.28  # 指定版本
./build/install-build-deps.sh  # 添加--no-chromeos-fonts参数避免字体问题

编译选项

  1. 生成配置:
./tools/dev/v8gen.py x64.release  # 推荐release版本
# 或
./tools/dev/v8gen.py x64.debug
  1. 编译:
ninja -C out.gn/x64.release
# 或使用预设选项
./tools/dev/gm.py x64.release

3. 调试工具与技巧

调试准备

在~/.gdbinit中添加:

source /path/to/v8/tools/gdbinit
source /path/to/v8/tools/gdb-v8-support.py

调试命令

gdb ./d8
set args --allow-natives-syntax ./exp.js

调试函数

  • %DebugPrint():显示对象详细信息
  • %DebugPrintPtr():显示指针指向的对象
  • %SystemBreak():设置断点

调试示例

var a = [1, 2, 3, 1.1];
%DebugPrint(a);
%SystemBreak();

4. V8对象模型

JSObject结构

V8中的对象由以下几部分组成:

  1. Map (HiddenClass):描述对象形状
  2. Properties:指向命名属性存储
  3. Elements:指向编号属性存储
  4. In-Object Properties:初始化时定义的命名属性

Hidden Class

  • 位于对象的前8字节(64位)或4字节(32位)
  • 包含对象类型信息、属性描述等
  • 相同Map的对象具有相同类型

属性存储方式

1. 快速属性(Fast Properties)

  • In-object properties:直接存储在对象中
  • Descriptor Array:通过Map Transition机制动态维护

2. 慢速属性(Dictionary Mode)

  • 使用哈希表存储属性
  • 适用于频繁删除属性的对象

编号属性(Elements)

  • 存储在连续内存中
  • 类型包括:
    • SMI_ELEMENTS:小整数
    • DOUBLE_ELEMENTS:浮点数
    • ELEMENTS:其他类型
  • 类型转换是单向的

5. 常用类型结构

Smi (小整数)

  • 32位架构:31位值 + 0标志位
  • 64位架构(旧版):32位值 + 32位0填充

指针

  • 最低位为1表示指针
  • 倒数第二位表示强弱引用

浮点数

  • 64位存储
  • 纯浮点数数组使用FixedDoubleArray优化

指针压缩

  • 较新版本使用32位偏移+基址寄存器
  • 减少内存使用

6. 函数调用栈

新版栈帧结构(从底到顶):

  1. 函数参数(按顺序压入)
  2. 参数个数(Argc)
  3. 返回地址
  4. 上一个栈帧指针
  5. JSFunction对象指针
  6. Context上下文指针
  7. BytecodeArray函数字节码指针
  8. BytecodeOffset(当前字节码偏移量)
  9. 局部变量("寄存器")

7. WASM特性

  • 可以在JS引擎地址空间中导入可读可写可执行的内存页
  • 示例:
let wasm_code = new Uint8Array([...]);
let wasm_mod = new WebAssembly.Instance(new WebAssembly.Module(wasm_code), {});
let f = wasm_mod.exports.main;
%SystemBreak();

8. 优化分析与Turbolizer

编译标志

  • --trace-turbo:生成优化过程信息
  • --trace-turbo-path:指定输出路径
  • --trace-opt:打印编译优化信息
  • --trace-deopt
  • --print-opt-code

Turbolizer使用

  1. 安装Node.js:
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt-get install -y nodejs
  1. 启动Turbolizer:
cd v8/tools/turbolizer
npm install
npm run-script build
python -m SimpleHTTPServer
  1. 生成分析数据:
./d8 exp.js --allow-natives-syntax --trace-turbo --trace-turbo-path=/path/to/output

9. 示例代码分析

优化示例

function add(x, y) {
    return x + y;
}
for (let i = 0; i < 10000; i++) {
    add(i, i + 1);
}
%OptimizeFunctionOnNextCall(add);
console.log(add(1, 2));

对象结构分析

const obj = {name: "John", age: 30, hobbies: ["reading", "swimming"], 1: 111};
obj.city = "New York";
%DebugPrint(obj);
%SystemBreak();

10. 关键数据结构

ArrayBuffer

  • 表示原始二进制数据缓冲区
  • 示例:
let buffer = new ArrayBuffer(16);
let int32View = new Int32Array(buffer);
int32View[0] = 123456;

DataView

  • 提供灵活的数据访问接口
  • 示例:
let buffer = new ArrayBuffer(8);
let dataView = new DataView(buffer);
dataView.setInt16(0, 12345);
dataView.setFloat32(2, 3.1415);

总结

本文详细介绍了V8引擎的内部结构和工作原理,包括环境搭建、调试技巧、对象模型、类型系统、函数调用等核心概念,为深入理解V8漏洞利用和PWN技术奠定了坚实基础。

V8 JavaScript 引擎深入解析与PWN前置知识 1. V8引擎概述 V8是Google用C++开发的开源JavaScript引擎,用于Chromium和Node.js等项目中执行JavaScript代码。V8的主要特点包括: 采用Just-in-time (JIT)编译技术 将JS代码编译为机器码执行以提高性能 编译后的二进制名称为d8而非v8 V8处理流程 解析(Parser) :将JS代码转换为抽象语法树(AST) 解释(Ignition) :将AST转换为字节码并在VM中执行 非优化编译(Sparkplug) :对频繁执行的代码生成简单机器码 优化编译(TurboFan) :对热点代码进行深度优化 2. 环境搭建 系统要求 推荐使用Ubuntu 20.04,18.04可能存在兼容性问题 依赖安装 工具链安装 获取depot_ tools: 安装ninja: V8源码获取与编译 编译选项 生成配置: 编译: 3. 调试工具与技巧 调试准备 在~/.gdbinit中添加: 调试命令 调试函数 %DebugPrint() :显示对象详细信息 %DebugPrintPtr() :显示指针指向的对象 %SystemBreak() :设置断点 调试示例 4. V8对象模型 JSObject结构 V8中的对象由以下几部分组成: Map (HiddenClass) :描述对象形状 Properties :指向命名属性存储 Elements :指向编号属性存储 In-Object Properties :初始化时定义的命名属性 Hidden Class 位于对象的前8字节(64位)或4字节(32位) 包含对象类型信息、属性描述等 相同Map的对象具有相同类型 属性存储方式 1. 快速属性(Fast Properties) In-object properties :直接存储在对象中 Descriptor Array :通过Map Transition机制动态维护 2. 慢速属性(Dictionary Mode) 使用哈希表存储属性 适用于频繁删除属性的对象 编号属性(Elements) 存储在连续内存中 类型包括: SMI_ ELEMENTS:小整数 DOUBLE_ ELEMENTS:浮点数 ELEMENTS:其他类型 类型转换是单向的 5. 常用类型结构 Smi (小整数) 32位架构:31位值 + 0标志位 64位架构(旧版):32位值 + 32位0填充 指针 最低位为1表示指针 倒数第二位表示强弱引用 浮点数 64位存储 纯浮点数数组使用FixedDoubleArray优化 指针压缩 较新版本使用32位偏移+基址寄存器 减少内存使用 6. 函数调用栈 新版栈帧结构(从底到顶): 函数参数(按顺序压入) 参数个数(Argc) 返回地址 上一个栈帧指针 JSFunction对象指针 Context上下文指针 BytecodeArray函数字节码指针 BytecodeOffset(当前字节码偏移量) 局部变量("寄存器") 7. WASM特性 可以在JS引擎地址空间中导入可读可写可执行的内存页 示例: 8. 优化分析与Turbolizer 编译标志 --trace-turbo :生成优化过程信息 --trace-turbo-path :指定输出路径 --trace-opt :打印编译优化信息 --trace-deopt --print-opt-code Turbolizer使用 安装Node.js: 启动Turbolizer: 生成分析数据: 9. 示例代码分析 优化示例 对象结构分析 10. 关键数据结构 ArrayBuffer 表示原始二进制数据缓冲区 示例: DataView 提供灵活的数据访问接口 示例: 总结 本文详细介绍了V8引擎的内部结构和工作原理,包括环境搭建、调试技巧、对象模型、类型系统、函数调用等核心概念,为深入理解V8漏洞利用和PWN技术奠定了坚实基础。