diff --git a/host/shellcode/shellcore_mountroot.cpp b/host/shellcode/shellcore_mountroot.cpp index de4ac99..fb55b33 100644 --- a/host/shellcode/shellcore_mountroot.cpp +++ b/host/shellcode/shellcore_mountroot.cpp @@ -4,7 +4,12 @@ #include // exports -extern "C" int __export_mount_root_original(void* pThis, const char* fs, const char* src, const char* dst, void* param_5, uint32_t* param_6); +extern "C" +{ +int __export_mount_root_original(void* pThis, const char* fs, const char* src, const char* dst, void* param_5, uint32_t* param_6); +int __export_PreLaunchCheck1(const void* pThis, const uint64_t flags); +int __export_PreLaunchCheck2(const void* pThis, const uint64_t flags, const void* param_3); +} static bool valid_str(const char* p) { @@ -58,3 +63,22 @@ extern "C" int __export_mount_root_hook(void* pThis, const char* fs, const char* } return __export_mount_root_original(pThis, fs, src, dst, param_5, param_6); } + +extern "C" +{ +int __export_PS5_PreLaunchCheck1(const void* pThis, const uint64_t flags) +{ + const uint64_t newCheckflags = flags | 1; + printf(FILE_FUNC_LINE ": (%p,%lx);", pThis, flags); + printf(" // updating checkFlags to 0x%lx\n", newCheckflags); + return __export_PreLaunchCheck1(pThis, newCheckflags); +} + +int __export_PS5_PreLaunchCheck2(const void* pThis, const uint64_t flags, const void* param_3) +{ + const uint64_t newCheckflags = flags | 1; + printf(FILE_FUNC_LINE ": (%p,%lx,%p);", pThis, flags, param_3); + printf(" // updating checkFlags to 0x%lx\n", newCheckflags); + return __export_PreLaunchCheck2(pThis, newCheckflags, param_3); +} +} diff --git a/host/shellcode_gen.cpp b/host/shellcode_gen.cpp index 2437a04..c0a7715 100644 --- a/host/shellcode_gen.cpp +++ b/host/shellcode_gen.cpp @@ -591,6 +591,17 @@ int3 int3 int3 int3 +__export_PreLaunchCheck1: +nop +__export_PreLaunchCheck2: +PUSH RBP +MOV RBP,RSP +PUSH R15 +int3 +int3 +int3 +int3 +int3 )"; try { diff --git a/patch/patch_shellcore.c b/patch/patch_shellcore.c index a858211..0e5580a 100644 --- a/patch/patch_shellcore.c +++ b/patch/patch_shellcore.c @@ -145,6 +145,80 @@ static void patchMountRoot(patch_frame_context* frame, const dynlib_info* obj, c } } +static void patchUpdateCheck(patch_frame_context* frame, const dynlib_info* obj, const pid_t pid) +{ +#if defined(__PROSPERO__) + const uintptr_t mapbase = obj->obj.mapbase; + const size_t mapsize = obj->obj.mapsize; + + uintptr_t timeout_branch = 0; + uintptr_t target_branch = 0; + bool new_fw = false; + char patch_buf[MAX_PATH + 1] = {}; + make_backup_buf(sfo_backup, 6); + static const struct pattern_entry patterns[] = { + {"55 48 89 e5 41 57 41 56 41 55 41 54 53 48 83 ec ? 4c 8b 35 ? ? ? ? 4c 8d 2d ? ? ? ?"}, // 5.50 + {"55 48 89 e5 41 57 41 56 41 55 41 54 53 48 83 ec ? 4c 8b 2d ? ? ? ? 48 89 55 ? 4c 8d 35 ? ? ? ?"}, // 11.60-13.60 + }; + const size_t pattern_count = _countof(patterns); + for (size_t idx = 0; idx < pattern_count; idx++) + { + const char* patten = patterns[idx].pattern; + const size_t patten_offset = patterns[idx].offset; + if (idx > 0) + { + debugf("couldn't find preLaunchCheck, trying (\"%s\" + %ld)!\n", patten, patten_offset); + memset(patch_buf, 0, sizeof(patch_buf)); + memset(&sfo_backup, 0, sizeof(sfo_backup)); + } + gen_backup_path(FUNC_N(0), patten, patten_offset, patch_buf, _countof_1(patch_buf)); + const bool is_ptr = false; + if (restore_cached_backup(pid, mapbase, patch_buf, &sfo_backup, sizeof(sfo_backup), sizeof(sfo_backup.bytes), &timeout_branch, is_ptr) == 1) + { + target_branch = timeout_branch; + debugf("preLaunchCheck cached %lx, preLaunchCheck from backup %lx\n", timeout_branch, target_branch); + } + else + { + timeout_branch = pid_chunk_scan(pid, mapbase, mapsize, patten, patten_offset); + debugf("preLaunchCheck: %lx\n", timeout_branch); + if (timeout_branch) + { + target_branch = timeout_branch; + } + } + if (timeout_branch) + { + new_fw = idx > 0; + debugf("new_fw %d\n", new_fw); + break; + } + } + + if (!timeout_branch) + { + notify("can't find preLaunchCheck nya, patching of pre launch softlock will not be possible."); + return; + } + + if (target_branch) + { + if (file_exists(patch_buf) == FAILED) + { + debugf("cache file not exist %s\n", patch_buf); + userland_copyout(pid, target_branch, sfo_backup.bytes, sizeof(sfo_backup.bytes)); + sfo_backup.addr = target_branch - mapbase; + write_backup_to_disk(patch_buf, &sfo_backup, sizeof(sfo_backup)); + } + const size_t num_originals = sizeof(sfo_backup.bytes); + const uintptr_t target_fn = !new_fw ? __export_PS5_PreLaunchCheck1_offset : __export_PS5_PreLaunchCheck2_offset; + const uintptr_t replace_fn = !new_fw ? (__export_PreLaunchCheck1_offset + 1) : __export_PreLaunchCheck2_offset; + pid_write_call(pid, target_branch, frame->frame_base + target_fn, true); + pid_write_call(pid, frame->frame_base + (replace_fn + num_originals), target_branch + num_originals, true); + } +#endif +} + static void patchOnNewProcess(patch_frame_context* frame, const dynlib_info* obj, const pid_t pid) { if (!is_ps4) @@ -271,6 +345,7 @@ static void patchOnNewProcess(patch_frame_context* frame, const dynlib_info* obj const size_t nbytes = sizeof(code_copy); userland_copyin(pid, code_copy, codebase, nbytes); patchMountRoot(frame, obj, pid); + patchUpdateCheck(frame, obj, pid); frame->frame_start += nbytes; frame->frame_consumed += nbytes; frame->frame_size -= nbytes; diff --git a/shared/memory.c b/shared/memory.c index 9b001c1..6106db4 100644 --- a/shared/memory.c +++ b/shared/memory.c @@ -16,9 +16,9 @@ #include "../shared/stringid.h" #include "memory.h" -#define BACKUP_VER 22761 // not random nya, 22761 does mean something. -#define UPDATE_NUM (128 * 1024) // base num -#define UPDATE_VER (UPDATE_NUM + 1) // version num, change to invalidate cache +#define BACKUP_VER 22761 // not random nya, 22761 does mean something. +#define UPDATE_NUM (128 * 1024) // base num +#define UPDATE_VER (UPDATE_NUM + 1) // version num, change to invalidate cache int sceKernelUsleep(int); diff --git a/shared/proc_rw.c b/shared/proc_rw.c index 21ef502..71c754d 100644 --- a/shared/proc_rw.c +++ b/shared/proc_rw.c @@ -37,7 +37,7 @@ static unsigned long vmspace_pmap(unsigned long vmspace_kaddr) return vmspace_kaddr + 0x2C0; case 0x105 ... 0x550: return vmspace_kaddr + 0x2E0; - case 0x600 ... 0x1360: // ← CHANGED: was 0x1340, now covers 13.42 and 13.60 + case 0x600 ... 0x1360: // ← CHANGED: was 0x1340, now covers 13.42 and 13.60 return vmspace_kaddr + 0x2E8; default: return 0;