// // ViewController.m // TrollInstaller // // Created by Lars Fröder on 17.08.22. // #import "ViewController.h" #import "kutil.h" #import "exploit/exploit.h" #import "exploit/kernel_rw.h" #import "KernelManager.h" #import "unarchive.h" #import #import extern uint64_t g_self_proc; void badLog(const char* a, ...) { va_list va; va_start(va, a); NSString* af = [NSString stringWithUTF8String:a]; NSString* msg = [[NSString alloc] initWithFormat:af arguments:va]; va_end(va); NSLog(@"%@",msg); return; } NSString* getNSStringFromFile(int fd) { NSMutableString* ms = [NSMutableString new]; ssize_t num_read; char c; while((num_read = read(fd, &c, sizeof(c)))) { [ms appendString:[NSString stringWithFormat:@"%c", c]]; } return ms.copy; } int runBinary(NSString* path, NSArray* args, NSString** output) { NSMutableArray* argsM = args.mutableCopy; [argsM insertObject:path.lastPathComponent atIndex:0]; NSUInteger argCount = [argsM count]; char **argsC = (char **)malloc((argCount + 1) * sizeof(char*)); for (NSUInteger i = 0; i < argCount; i++) { argsC[i] = strdup([[argsM objectAtIndex:i] UTF8String]); } argsC[argCount] = NULL; posix_spawn_file_actions_t action; posix_spawn_file_actions_init(&action); int out[2]; pipe(out); posix_spawn_file_actions_adddup2(&action, out[1], STDERR_FILENO); posix_spawn_file_actions_addclose(&action, out[0]); pid_t task_pid; int status = 0; int spawnError = posix_spawn(&task_pid, [path UTF8String], &action, NULL, (char* const*)argsC, NULL); for (NSUInteger i = 0; i < argCount; i++) { free(argsC[i]); } free(argsC); if(spawnError != 0) { NSLog(@"posix_spawn error %d\n", spawnError); return spawnError; } do { if (waitpid(task_pid, &status, 0) != -1) { //printf("Child status %dn", WEXITSTATUS(status)); } else { perror("waitpid"); return -222; } } while (!WIFEXITED(status) && !WIFSIGNALED(status)); close(out[1]); if(output) { *output = getNSStringFromFile(out[0]); } return WEXITSTATUS(status); } // Get root, credit: @xina520 struct k_posix_cred backup_cred; int backup_groupSize; gid_t backup_groupList[200]; int getRoot(void) { NSLog(@"attempting to get root...\n"); usleep(1000); backup_groupSize = getgroups(200, &backup_groupList[0]); backup_cred = proc_get_posix_cred(g_self_proc); struct k_posix_cred zero_cred = {0}; NSLog(@"setting posix cred to zero cred...\n"); usleep(1000); proc_set_posix_cred(g_self_proc, zero_cred); int err = setgroups(0,0); if(err) { NSLog(@"setgroups error %d\n", err); usleep(1000); } int uid = getuid(); NSLog(@"getuid => %d\n", uid); usleep(1000); return uid; } int dropRoot(void) { if(getuid() != 0) return getuid(); printf("attempting to drop root...\n"); usleep(1000); int err = setgroups(backup_groupSize,backup_groupList); if(err) { printf("setgroups error %d\n", err); usleep(1000); } proc_set_posix_cred(g_self_proc, backup_cred); int uid = getuid(); printf("dropped root??? uid: %d\n", uid); return uid; } @interface ViewController () @property (weak, nonatomic) IBOutlet UILabel *statusLabel; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } - (void)updateStatus:(NSString*)status { dispatch_async(dispatch_get_main_queue(), ^{ self.statusLabel.text = status; }); } int writeRemountPrivatePreboot(void) { return runBinary(@"/sbin/mount", @[@"-u", @"-w", @"/private/preboot"], nil); } - (void)doInstallation { NSLog(@"TrollStore out here, exploitation starting!"); usleep(1000); [self updateStatus:@"Exploiting..."]; // Run kernel exploit uint64_t kernel_base; if(exploit_get_krw_and_kernel_base(&kernel_base) != 0) { [self updateStatus:@"Exploit failed :("]; return; } // Initialize KernelManager KernelManager* km = [KernelManager sharedInstance]; [km loadOffsets]; [km loadSlidOffsetsWithKernelBase:kernel_base]; km.kread_32_d = kread32; km.kread_64_d = kread64; km.kwrite_32 = kwrite32; km.kwrite_64 = kwrite64; km.kcleanup = exploitation_cleanup; NSLog(@"Exploitation finished, post exploit stuff next!"); usleep(1000); [self updateStatus:@"Getting root..."]; // Get root getRoot(); [self updateStatus:@"Installing..."]; writeRemountPrivatePreboot(); NSString* tmpDir = @"/private/preboot/tmp"; [[NSFileManager defaultManager] createDirectoryAtPath:tmpDir withIntermediateDirectories:NO attributes:nil error:nil]; NSString* tsTarPath = [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"TrollStore.tar"]; extract(tsTarPath, tmpDir); NSString* helperPath = [tmpDir stringByAppendingPathComponent:@"TrollStore.app/trollstorehelper"]; chmod(helperPath.UTF8String, 0755); chown(helperPath.UTF8String, 0, 0); NSString* helperOutput; int ret = runBinary(helperPath, @[@"install-trollstore", tsTarPath], &helperOutput); [self updateStatus:@"Cleaning up..."]; [[NSFileManager defaultManager] removeItemAtPath:tmpDir error:nil]; // Clean everything up so the kernel doesn't panic when the app exits dropRoot(); [km finishAndCleanupIfNeeded]; [self updateStatus:@"Done!"]; NSLog(@"%@", helperOutput); // Print installed message if(ret == 0) { dispatch_async(dispatch_get_main_queue(), ^{ UIAlertController* installedAlertController = [UIAlertController alertControllerWithTitle:@"Installed TrollStore" message:@"TrollStore was installed and can now be accessed from your home screen, you can uninstall the installer application now. Some devices suffer from a bug where newly installed applications don't immediately show up, in that case reboot and TrollStore should show up." preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { exit(0); }]; [installedAlertController addAction:closeAction]; [self presentViewController:installedAlertController animated:YES completion:nil]; }); } else { dispatch_async(dispatch_get_main_queue(), ^{ UIAlertController* installedAlertController = [UIAlertController alertControllerWithTitle:@"Error" message:[NSString stringWithFormat:@"Failed to install TrollStore. trollstore helper exited with code %d. Output:\n:%@", ret, helperOutput ?: @""] preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { exit(0); }]; UIAlertAction* copyAction = [UIAlertAction actionWithTitle:@"Copy Output" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; pasteboard.string = helperOutput; exit(0); }]; [installedAlertController addAction:closeAction]; [installedAlertController addAction:copyAction]; [self presentViewController:installedAlertController animated:YES completion:nil]; }); } } - (IBAction)installButtonPressed:(id)sender { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self doInstallation]; }); } @end