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 e8172af1..00000000 Binary files a/Natives/resources/Frameworks/libjnidispatch.dylib and /dev/null differ 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)