From ec04885ce5a6d5921db4b162e5e514bc4b035db5 Mon Sep 17 00:00:00 2001 From: khanhduytran0 Date: Sun, 9 Jun 2024 21:52:35 +0700 Subject: [PATCH] Feat: patch dylib for game dlopen calls Now that game can directly load macOS's JNA native library, libjnidispatch is removed. --- Natives/CMakeLists.txt | 1 + Natives/JavaLauncher.m | 1 - Natives/dyld_patch_platform.m | 70 ++++++++++++++++++ Natives/main_hook.m | 16 ++++ .../resources/Frameworks/libjnidispatch.dylib | Bin 159816 -> 0 bytes Natives/utils.h | 2 + README.md | 1 - 7 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 Natives/dyld_patch_platform.m delete mode 100644 Natives/resources/Frameworks/libjnidispatch.dylib diff --git a/Natives/CMakeLists.txt b/Natives/CMakeLists.txt index 43e29610..5b8ca647 100644 --- a/Natives/CMakeLists.txt +++ b/Natives/CMakeLists.txt @@ -99,6 +99,7 @@ target_link_libraries(PojavAccountJNI) # PojavLauncher add_executable(PojavLauncher dyld_bypass_validation.m + dyld_patch_platform.m main.m main_hook.m JavaLauncher.m diff --git a/Natives/JavaLauncher.m b/Natives/JavaLauncher.m index 64ec79fa..e3acb239 100644 --- a/Natives/JavaLauncher.m +++ b/Natives/JavaLauncher.m @@ -178,7 +178,6 @@ int launchJVM(NSString *username, id launchTarget, int width, int height, int mi margv[++margc] = "-Xms128M"; margv[++margc] = [NSString stringWithFormat:@"-Xmx%dM", allocmem].UTF8String; margv[++margc] = [NSString stringWithFormat:@"-Djava.library.path=%@/Frameworks", NSBundle.mainBundle.bundlePath].UTF8String; - margv[++margc] = [NSString stringWithFormat:@"-Djna.boot.library.path=%@/Frameworks", NSBundle.mainBundle.bundlePath].UTF8String; margv[++margc] = [NSString stringWithFormat:@"-Duser.dir=%@", gameDir].UTF8String; margv[++margc] = [NSString stringWithFormat:@"-Duser.home=%s", getenv("POJAV_HOME")].UTF8String; margv[++margc] = [NSString stringWithFormat:@"-Duser.timezone=%@", NSTimeZone.localTimeZone.name].UTF8String; diff --git a/Natives/dyld_patch_platform.m b/Natives/dyld_patch_platform.m new file mode 100644 index 00000000..ee74e229 --- /dev/null +++ b/Natives/dyld_patch_platform.m @@ -0,0 +1,70 @@ +#import +#include +#include +#include +#include +#include + +extern int dyld_get_active_platform(); + +static BOOL PLPatchMachOPlatformForSlice(const char *path, struct mach_header_64 *header) { + uint8_t *imageHeaderPtr = (uint8_t*)header + sizeof(struct mach_header_64); + + struct load_command *command = (struct load_command *)imageHeaderPtr; + for(int i = 0; i < header->ncmds; i++) { + if (command->cmd == LC_BUILD_VERSION) { + struct build_version_command *buildver = (struct build_version_command *)command; + int activePlatform = dyld_get_active_platform(); + if (buildver->platform == activePlatform) return NO; // it is already set, stop + buildver->platform = activePlatform; // set to current platform + } else if (command->cmd == LC_LOAD_DYLIB) { + struct dylib_command *dylib = (struct dylib_command *)command; + char *dylibName = (void *)dylib + dylib->dylib.name.offset; + char *verPtr = strstr(dylibName, "/Versions/"); + if (verPtr) { + // Remove "/Versions/X" + int lastComponentLen = strlen(dylibName) - (verPtr - dylibName) - 11; + memmove(verPtr, verPtr + 11, lastComponentLen); + verPtr[lastComponentLen] = '\0'; + } + } + command = (struct load_command *)((void *)command + command->cmdsize); + } + return YES; +} + + +BOOL PLPatchMachOPlatformForFile(const char *path) { + int fd = open(path, O_RDWR, (mode_t)0600); + if (fd == -1) return NO; + struct stat s; + fstat(fd, &s); + + void *map = mmap(NULL, s.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (!map) { + close(fd); + return NO; + } + + BOOL patched = NO; + uint32_t magic = *(uint32_t *)map; + if (magic == FAT_CIGAM) { + // Find compatible slice + struct fat_header *header = (struct fat_header *)map; + struct fat_arch *arch = (struct fat_arch *)(map + sizeof(struct fat_header)); + for (int i = 0; i < OSSwapInt32(header->nfat_arch); i++) { + if (OSSwapInt32(arch->cputype) == CPU_TYPE_ARM64) { + NSLog(@"[PojavLauncher] Patching %s", path); + patched |= PLPatchMachOPlatformForSlice(path, (struct mach_header_64 *)(map + OSSwapInt32(arch->offset))); + } + arch = (struct fat_arch *)((void *)arch + sizeof(struct fat_arch)); + } + } else if (magic == MH_MAGIC_64 && ((struct mach_header_64 *)map)->cputype == CPU_TYPE_ARM64) { + patched = PLPatchMachOPlatformForSlice(path, (struct mach_header_64 *)map); + } + + if (patched) msync(map, s.st_size, MS_SYNC); + munmap(map, s.st_size); + close(fd); + return patched; +} diff --git a/Natives/main_hook.m b/Natives/main_hook.m index 0d87adae..63004306 100644 --- a/Natives/main_hook.m +++ b/Natives/main_hook.m @@ -8,6 +8,7 @@ void (*orig_abort)(); void (*orig_exit)(int code); +void* (*orig_dlopen)(const char* path, int mode); int (*orig_open)(const char *path, int oflag, ...); void handle_fatal_exit(int code) { @@ -54,13 +55,27 @@ void hooked_exit(int code) { } handle_fatal_exit(code); +/* if (runtimeJavaVMPtr != NULL) { (*runtimeJavaVMPtr)->DestroyJavaVM(runtimeJavaVMPtr); } +*/ orig_exit(code); } +void* hooked_dlopen(const char* path, int mode) { + const char *home = getenv("POJAV_HOME"); + // Only proceed to check if dylib is in the home dir + // Path input from jvm is absolute path(?) + if (!path || strncmp(path, home, strlen(home))) { + return orig_dlopen(path, mode); + } + + PLPatchMachOPlatformForFile(path); + return orig_dlopen(path, mode); +} + int hooked_open(const char *path, int oflag, ...) { va_list args; va_start(args, oflag); @@ -78,6 +93,7 @@ void init_hookFunctions() { {"abort", hooked_abort, (void *)&orig_abort}, {"__assert_rtn", hooked___assert_rtn, NULL}, {"exit", hooked_exit, (void *)&orig_exit}, + {"dlopen", hooked_dlopen, (void *)&orig_dlopen}, {"open", hooked_open, (void *)&orig_open} }; rebind_symbols(rebindings, sizeof(rebindings)/sizeof(struct rebinding)); diff --git a/Natives/resources/Frameworks/libjnidispatch.dylib b/Natives/resources/Frameworks/libjnidispatch.dylib deleted file mode 100644 index e8172af143ee76eef655fa083bc03d7a23de60aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 159816 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 P!#`SX&)%3SroaCHIPZ2X diff --git a/Natives/utils.h b/Natives/utils.h index 80d091c7..59c582f1 100644 --- a/Natives/utils.h +++ b/Natives/utils.h @@ -63,6 +63,8 @@ void init_hookFunctions(); void init_hookUIKitConstructor(); void init_setupMultiDir(); +BOOL PLPatchMachOPlatformForFile(const char *path); + UIWindow* currentWindow(); UIWindow* currentWindowInScene(BOOL external); UIViewController* currentVC(); diff --git a/README.md b/README.md index c0bcf02f..b43dea0e 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,6 @@ PojavLauncher is amazing, and surprisingly stable, and it wouldn't be this way w - [LWJGLX](https://github.com/PojavLauncherTeam/lwjglx) (LWJGL2 API compatibility layer for LWJGL3): unknown license. - [DBNumberedSlider](https://github.com/khanhduytran0/DBNumberedSlider): [Apache 2.0 License](https://github.com/immago/DBNumberedSlider/blob/master/LICENSE) - [fishhook](https://github.com/khanhduytran0/fishhook): [BSD-3 License](https://github.com/facebook/fishhook/blob/main/LICENSE). -- [Java Native Access](https://github.com/java-native-access/jna): [Apache 2.0 License](https://github.com/java-native-access/jna/blob/master/LICENSE). - [shaderc](https://github.com/khanhduytran0/shaderc) (used by Vulkan rendering mods): [Apache 2.0 License](https://github.com/google/shaderc/blob/main/LICENSE). - [NRFileManager](https://github.com/mozilla-mobile/firefox-ios/tree/b2f89ac40835c5988a1a3eb642982544e00f0f90/ThirdParty/NRFileManager): [MPL-2.0 License](https://www.mozilla.org/en-US/MPL/2.0) - [AltKit](https://github.com/rileytestut/AltKit)