// // jailbreak.m // Meridian // // Created by Ben Sparkes on 16/02/2018. // Copyright © 2018 Ben Sparkes. All rights reserved. // #include "v0rtex.h" #include "kernel.h" #include "helpers.h" #include "root-rw.h" #include "amfi.h" #include "offsetfinder.h" #include "jailbreak.h" #include "ViewController.h" #include "patchfinder64.h" #include "patchfinders/offsetdump.h" #include "nvpatch.h" #include #include #import #import "NSData+GZip.h" #include #import "fun_objc.h" #include "kpp.h" #include "kppremount.h" //#import "NSTask.h" //experimental kpp stuff NSFileManager *fileMgr; offsets_t offsets; BOOL great_success = FALSE; BOOL isKppless = FALSE; int remount() { //[self log:@"remounting"]; NSLog(@"remounting"); if (do_remount(kslide) == KERN_SUCCESS) { // [self bootstrap]; return 0; } else { NSLog(@"ERROR: failed to remount system partition \n"); // [self log:@"ERROR: failed to remount system partition \n"]; return -1; } return -1; } int bypassKPP() { //[self log:@"pwning kernel"]; if (do_kpp(1, 0, kernel_base, kslide, tfp0) == KERN_SUCCESS) { NSLog(@"you down with kpp? yeah you know me"); return remount(); } else { NSLog(@"ERROR: kpp bypass failed \n"); //[self log:@"ERROR: kpp bypass failed \n"]; return -1; } return 0; } int makeShitHappen(ViewController *view, BOOL kppless) { int ret; isKppless = kppless; fileMgr = [NSFileManager defaultManager]; // run v0rtex [view writeText:@"running v0rtex..."]; suspend_all_threads(); ret = runV0rtex(); resume_all_threads(); if (ret != 0) { [view writeText:@"failed!"]; if (ret == -420) { [view writeTextPlain:@"failed to load offsets!"]; } return 1; } [view writeTextPlain:@"succeeded! praize siguza!"]; // set up stuff init_patchfinder(NULL); //#ifndef DO_KPPLESS if (!isKppless) { ret = init_amfi(); if (ret != 0) { [view writeTextPlain:@"failed to initialize amfi class!"]; return 1; } // patch containermanager [view writeText:@"patching containermanager..."]; ret = patchContainermanagerd(); if (ret != 0) { [view writeText:@"failed!"]; return 1; } [view writeText:@"done!"]; // remount root fs [view writeText:@"remounting rootfs as r/w..."]; ret = remountRootFs(); if (ret != 0) { [view writeText:@"failed!"]; return 1; } } else { //#else int kppReturn = bypassKPP(); if (kppReturn == 0) { [view writeText:@"KPP has been defeated!\n"]; } else { [view writeText:@"KPP bypass failed!\n"]; return 1; } } //#endif [view writeText:@"done!"]; /* Begin the filesystem fuckery */ [view writeText:@"some filesytem fuckery..."]; // Remove /meridian in the case of PB's if (file_exists("/meridian") == 0 && file_exists("/meridian/.bootstrap") != 0) { [[NSFileManager defaultManager] removeItemAtPath:@"/meridian" error:nil]; } if (file_exists("/Library/LaunchDaemons/._dropbear.plist") == 0) { unlink("/Library/LaunchDaemons/._dropbear.plist"); } if (file_exists("/meridian/.bootstrap") == 0) { unlink("/meridian/.bootstrap"); } /* //take these out later, just so i can update the plists as i tweak the payload if (file_exists("/Library/LaunchDaemons/com.openssh.sshd.plist") == 0) { unlink("/Library/LaunchDaemons/com.openssh.sshd.plist"); } if (file_exists("/Library/LaunchDaemons/dropbear.plist") == 0) { unlink("/Library/LaunchDaemons/dropbear.plist"); } */ // if (file_exists("/usr/lib/TweakInject.dylib") == 0) { // ret = unlink("/usr/lib/TweakInject.dylib"); // if (ret != 0) { // [view writeText:@"failed!"]; // [view writeTextPlain:@"removing /usr/lib/TweakInject.dylib failed with error %d: %s", errno, strerror(errno)]; // return 1; // } // // } if (file_exists("/meridian") != 0) { ret = mkdir("/meridian", 0755); if (ret != 0) { [view writeText:@"failed!"]; [view writeTextPlain:@"creating /meridian failed with error %d: %s", errno, strerror(errno)]; return 1; } } if (file_exists("/meridian/logs") != 0) { ret = mkdir("/meridian/logs", 0755); if (ret != 0) { [view writeText:@"failed!"]; [view writeTextPlain:@"creating /meridian/logs failed with error %d: %s", errno, strerror(errno)]; return 1; } } if (file_exists("/meridian/tar") == 0) { ret = unlink("/meridian/tar"); if (ret != 0) { [view writeText:@"failed!"]; [view writeTextPlain:@"removing /meridian/tar failed with error %d: %s", errno, strerror(errno)]; return 1; } } if (file_exists("/meridian/tar.tar") == 0) { ret = unlink("/meridian/tar.tar"); if (ret != 0) { [view writeText:@"failed!"]; [view writeTextPlain:@"deleting /meridian/tar.tar failed with error %d: %s", errno, strerror(errno)]; return 1; } } ret = extract_bundle("tar.tar", "/meridian"); if (ret != 0) { [view writeText:@"failed!"]; [view writeTextPlain:@"failed to extract tar.tar bundle! ret: %d, errno: %d: %s", ret, errno, strerror(errno)]; return 1; } if (file_exists("/meridian/tar") != 0) { [view writeText:@"failed!"]; [view writeTextPlain:@"/meridian/tar was not found :("]; return 1; } ret = chmod("/meridian/tar", 0755); if (ret != 0) { [view writeText:@"failed!"]; [view writeTextPlain:@"chmod(755)'ing /meridian/tar failed with error %d: %s", errno, strerror(errno)]; return 1; } ret = inject_trust("/meridian/tar"); if (ret != 0) { [view writeText:@"failed!"]; [view writeTextPlain:@"injecting trust to /meridian/tar failed with retcode %d", ret]; return 1; } [view writeText:@"done!"]; // extract meridian-bootstrap [view writeText:@"extracting meridian files..."]; ret = extractMeridianData(); if (ret != 0) { [view writeText:@"failed!"]; [view writeTextPlain:[NSString stringWithFormat:@"error code: %d", ret]]; return 1; } [view writeText:@"done!"]; // dump offsets to file for later use (/meridian/offsets.plist) dumpOffsetsToFile(&offsets, kernel_base, kslide); //#ifndef DO_KPPLESS if (!isKppless) { // patch amfid [view writeText:@"patching amfid..."]; ret = defecateAmfi(); if (ret != 0) { [view writeText:@"failed!"]; if (ret > 0) { [view writeTextPlain:[NSString stringWithFormat:@"failed to patch - %d tries", ret]]; } return 1; } [view writeText:@"done!"]; } //#endif // touch .cydia_no_stash touch_file("/.cydia_no_stash"); // symlink /Library/MobileSubstrate/DynamicLibraries -> /usr/lib/tweaks //setUpSymLinks(); // remove Substrate's SafeMode (MobileSafety) if it's installed // removing from dpkg will be handled by Cydia conflicts later if (file_exists("/usr/lib/tweaks/MobileSafety.dylib") == 0) { unlink("/usr/lib/tweaks/MobileSafety.dylib"); } if (file_exists("/usr/lib/tweaks/MobileSafety.plist") == 0) { unlink("/usr/lib/tweaks/MobileSafety.plist"); } // extract bootstrap (if not already extracted) if (file_exists("/meridian/.bootstrap") != 0) { [view writeText:@"extracting bootstrap..."]; int exitCode = 0; ret = extractBootstrap(&exitCode); if (ret != 0) { [view writeText:@"failed!"]; switch (ret) { case 1: [view writeTextPlain:@"failed to extract system-base.tar"]; break; case 2: [view writeTextPlain:@"failed to extract installer-base.tar"]; break; case 3: [view writeTextPlain:@"failed to extract dpkgdb-base.tar"]; break; case 4: [view writeTextPlain:@"failed to extract cydia-base.tar"]; break; case 5: [view writeTextPlain:@"failed to extract optional-base.tar"]; break; case 6: [view writeTextPlain:@"failed to run uicache!"]; break; } [view writeTextPlain:@"exit code: %d", exitCode]; return 1; } [view writeText:@"done!"]; } //unlink("/usr/lib/libjailbreak.dylib"); //cp("/usr/lib/libjailbreak.dylib","/electra/libjailbreak.dylib"); /* // add the midnight repo if (file_exists("/etc/apt/sources.list.d/meridian.list") != 0) { FILE *fd = fopen("/etc/apt/sources.list.d/meridian.list", "w+"); const char *text = "deb http://repo.midnight.team ./"; fwrite(text, strlen(text) + 1, 1, fd); fclose(fd); } */ pid_t pd; //posix_spawn(&pd, "/bin/bash", NULL, NULL, (char **)&(const char*[]){ "bash", "/usr/libexec/nito/firmware.sh", NULL }, NULL); //waitpid(pd, NULL, 0); posix_spawn(&pd, "/bin/bash", NULL, NULL, (char **)&(const char*[]){ "bash", "/Library/dpkg/info/openssh.postinst", NULL }, NULL); waitpid(pd, NULL, 0); // posix_spawn(&pd, "/bin/launchctl", NULL, NULL, (char **)&(const char*[]){ "launchctl", "load", "/Library/LaunchDaemons/com.openssh.sshd.plist", NULL }, NULL); // waitpid(pd, NULL, 0); //fixPerms(); /* // launch dropbear [view writeText:@"launching dropbear..."]; ret = launchDropbear(); if (ret != 0) { [view writeText:@"failed!"]; [view writeTextPlain:@"exit code: %d", ret]; return 1; } */ //launch openssh [view writeText:@"Launching openssh..."]; ret = start_launchdaemon("/Library/LaunchDaemons/com.openssh.sshd.plist"); if (ret != 0) { [view writeText:@"failed!"]; [view writeTextPlain:@"exit code: %d", ret]; //return 1; } [view writeText:@"done!"]; // link substitute stuff //setUpSubstitute(); //#ifndef DO_KPPLESS if (!isKppless) { // start jailbreakd //ret = inject_trust("/meridian/inject_criticald"); //ret = inject_trust("/meridian/amfid_payload.dylib"); //ret = inject_trust("/usr/lib/pspawn_hook.dylib"); //ret = inject_trust("/usr/lib/libjailbreak.dylib"); //ret = inject_trust("/Library/MobileSubstrate/DynamicLibraries/DalesDeadBug.dylib"); //if (ret != 0) return -1; [view writeText:@"starting jailbreakd..."]; ret = startJailbreakd(); if (ret != 0) { [view writeText:@"failed"]; if (ret > 1) { [view writeTextPlain:@"failed to launch - %d tries", ret]; } return 1; } //pid_t pid = get_pid_for_name("installd"); //ret = call_jailbreakd(JAILBREAKD_COMMAND_ENTITLE, pid); //ret = inject_library(pid, "/Library/MobileSubstrate/DynamicLibraries/DalesDeadBug.dylib"); [view writeText:@"done!"]; /* #define inject_criticald "/meridian/inject_criticald" const char* args_launchd[] = {inject_criticald, itoa(1), "/usr/lib/pspawn_hook.dylib", NULL}; int rv = posix_spawn(&pd, inject_criticald, NULL, NULL, (char **)&args_launchd, NULL); waitpid(pd, NULL, 0); */ // patch com.apple.System.boot-nonce [view writeText:@"patching boot-nonce..."]; ret = nvpatch("com.apple.System.boot-nonce"); if (ret != 0) { [view writeText:@"failed!"]; return 1; } [view writeText:@"done!"]; } //#endif // load launchdaemons [view writeText:@"loading launchdaemons..."]; ret = loadLaunchDaemons(); if (ret != 0) { [view writeText:@"failed!"]; return 1; } [view writeText:@"done!"]; great_success = TRUE; return 0; } void fixPerms() { int rv = execprog("/usr/bin/chmod", (const char **)&(const char*[]) { "/usr/bin/chmod", "-R", "0700", "/private/var/root/.ssh", NULL }); rv = execprog("/usr/bin/chmod", (const char **)&(const char*[]) { "/usr/bin/chmod", "-R", "0700", "/private/etc/dropbear", NULL }); } kern_return_t callback(task_t kern_task, kptr_t kbase, void *cb_data) { tfp0 = kern_task; kernel_base = kbase; kslide = kernel_base - 0xFFFFFFF007004000; return KERN_SUCCESS; } int runV0rtex() { offsets_t *offs = get_offsets(); if (offs == NULL) { return -420; } offsets = *offs; int ret = v0rtex(&offsets, &callback, NULL); uint64_t kernel_task_addr = rk64(offs->kernel_task + kslide); kernprocaddr = rk64(kernel_task_addr + offs->task_bsd_info); kern_ucred = rk64(kernprocaddr + offs->proc_ucred); if (ret == 0) { NSLog(@"tfp0: 0x%x", tfp0); NSLog(@"kernel_base: 0x%llx", kernel_base); NSLog(@"kslide: 0x%llx", kslide); NSLog(@"kern_ucred: 0x%llx", kern_ucred); NSLog(@"kernprocaddr: 0x%llx", kernprocaddr); } return ret; } int patchContainermanagerd() { uint64_t cmgr = find_proc_by_name("containermanager"); if (cmgr == 0) { NSLog(@"unable to find containermanager!"); return 1; } wk64(cmgr + 0x100, kern_ucred); return 0; } int remountRootFs() { NSOperatingSystemVersion osVersion = [[NSProcessInfo processInfo] operatingSystemVersion]; int pre130 = osVersion.minorVersion < 2 ? 1 : 0; int rv = mount_root(kslide, offsets.root_vnode, pre130); if (rv != 0) { return 1; } return 0; } int extractMeridianData() { int rv = extract_bundle_tar("meridian-bootstrap.tar"); unlink("/usr/bin/cynject"); unlink("/usr/bin/cycc"); symlink("/meridian/inject_criticald", "/usr/bin/cynject"); //mimic cynject symlink("/usr/bin/ssh", "/usr/local/bin/ssh"); //get scp working //rv = extract_bundle_tar("basebinaries.tar"); return rv; } void setUpSymLinks() { struct stat file; stat("/Library/MobileSubstrate/DynamicLibraries", &file); if (file_exists("/Library/MobileSubstrate/DynamicLibraries") == 0 && file_exists("/usr/lib/tweaks") == 0 && S_ISLNK(file.st_mode)) { return; } // By the end of this check, /usr/lib/tweaks should exist containing any // tweaks (if applicable), and /Lib/MobSub/DynLib should NOT exist if (file_exists("/Library/MobileSubstrate/DynamicLibraries") == 0 && file_exists("/usr/lib/tweaks") != 0) { // Move existing tweaks folder to /usr/lib/tweaks [[NSFileManager defaultManager] moveItemAtPath:@"/Library/MobileSubstrate/DynamicLibraries" toPath:@"/usr/lib/tweaks" error:nil]; } else if (file_exists("/Library/MobileSubstrate/DynamicLibraries") == 0 && file_exists("/usr/lib/tweaks") == 0) { // Move existing tweaks to /usr/lib/tweaks and delete the MobSub folder NSArray *fileList = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/Library/MobileSubstrate/DynamicLibraries" error:nil]; for (NSString *item in fileList) { NSString *fullPath = [NSString stringWithFormat:@"/Library/MobileSubstrate/DynamicLibraries/%@", item]; [[NSFileManager defaultManager] moveItemAtPath:fullPath toPath:@"/usr/lib/tweaks" error:nil]; } [[NSFileManager defaultManager] removeItemAtPath:@"/Library/MobileSubstrate/DynamicLibraries" error:nil]; } else if (file_exists("/Library/MobileSubstrate/DynamicLibraries") != 0 && file_exists("/usr/lib/tweaks") != 0) { // Just create /usr/lib/tweaks - /Lib/MobSub/DynLibs doesn't exist mkdir("/Library/MobileSubstrate", 0755); mkdir("/usr/lib/tweaks", 0755); } else if (file_exists("/Library/MobileSubstrate/DynamicLibraries") != 0 && file_exists("/usr/lib/tweaks") == 0) { // We should be fine in this case mkdir("/Library/MobileSubstrate", 0755); } // Symlink it! symlink("/usr/lib/tweaks", "/Library/MobileSubstrate/DynamicLibraries"); } void extractGz_merd(const char *from, const char *to) { NSData *gz = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@(from) ofType:@"gz"]]; NSData *extracted = [gz gunzippedData]; [extracted writeToFile:@(to) atomically:YES]; } int extractBootstrap(int *exitCode) { int rv; unlink("/meridian/bootstrap.tar"); extractGz_merd("bootstrap.tar", "/meridian/bootstrap.tar"); rv = extract_tar("/meridian/bootstrap.tar"); if (rv != 0) { *exitCode = rv; return 1; } // rv = uicache(); // if (rv != 0) { // *exitCode = rv; // return 6; // } touch_file("/meridian/.bootstrap"); touch_file("/var/mobile/Library/Preferences/.kickstart"); //touch_file("/var/mobile/Library/Preferences/.nitolaunch"); pid_t pd; posix_spawn(&pd, "/bin/bash", NULL, NULL, (char **)&(const char*[]){ "bash", "/usr/libexec/nito/firmware.sh", NULL }, NULL); waitpid(pd, NULL, 0); char *myenviron[] = { "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/usr/games", "PS1=\\h:\\w \\u\\$ ", NULL }; /* posix_spawn(&pd, "/usr/bin/dpkg", NULL, NULL, (char **)&(const char*[]){ "dpkg", "-i", "--refuse-downgrade", progname("nitotv.deb"), NULL }, (char **)&myenviron); waitpid(pd, NULL, 0); */ posix_spawn(&pd, "/usr/bin/dpkg", NULL, NULL, (char **)&(const char*[]){ "dpkg", "-i", "--refuse-downgrade", progname("safetynet.deb"), NULL }, (char **)&myenviron); waitpid(pd, NULL, 0); return 0; } int old_extractBootstrap(int *exitCode) { int rv; // extract system-base.tar rv = extract_bundle_tar("system-base.tar"); if (rv != 0) { *exitCode = rv; return 1; } // extract installer-base.tar rv = extract_bundle_tar("installer-base.tar"); if (rv != 0) { *exitCode = rv; return 2; } if (file_exists("/private/var/lib/dpkg/status") != 0) { rv = extract_bundle_tar("dpkgdb-base.tar"); if (rv != 0) { *exitCode = rv; return 3; } } // extract cydia-base.tar rv = extract_bundle_tar("cydia-base.tar"); if (rv != 0) { *exitCode = rv; return 4; } // extract optional-base.tar rv = extract_bundle_tar("optional-base.tar"); if (rv != 0) { *exitCode = rv; return 5; } //enableHiddenApps(); touch_file("/meridian/.bootstrap"); rv = uicache(); if (rv != 0) { *exitCode = rv; return 6; } return 0; } int newdefecateAmfi() { #define BinaryLocation "/electra/inject_criticald" pid_t amfid_pid = get_pid_for_name("amfid"); if (amfid_pid == 0) { return -2; } pid_t pd; int rv = 0; const char* args_amfid[] = {BinaryLocation, itoa(amfid_pid), "/electra/amfid_payload.dylib", NULL}; rv = posix_spawn(&pd, BinaryLocation, NULL, NULL, (char **)&args_amfid, NULL); waitpid(pd, NULL, 0); unlink("/.amfid_success"); const char *args_helloworld[] = {"helloworld", NULL}; rv = posix_spawn(&pd, "/electra/helloworld", NULL, NULL, (char **)&args_helloworld, NULL); waitpid(pd, NULL, 0); if (!file_exists("/.amfid_success")){ return -3; } unlink("/.amfid_success"); return 0; } int defecateAmfi() { // write kslide to file unlink("/meridian/kernel_slide"); FILE *fd = fopen("/meridian/kernel_slide", "w"); fprintf(fd, "%016llx", kslide); fclose(fd); int ret = inject_trust("/meridian/inject_criticald"); if (ret != 0) return -1; // trust our payload ret = inject_trust("/meridian/amfid_payload.dylib"); if (ret != 0) return -1; unlink("/var/tmp/amfid_payload.alive"); pid_t pid = get_pid_for_name("amfid"); if (pid == 0) { return -2; } ret = inject_library(pid, "/meridian/amfid_payload.dylib"); if (ret != 0) return -2; int tries = 0; while (file_exists("/var/tmp/amfid_payload.alive") != 0) { if (tries >= 100) { NSLog(@"failed to patch amfid (%d tries)", tries); return tries; } NSLog(@"waiting for amfid patch..."); usleep(100000); // 0.1 sec tries++; } return 0; } int launchDropbear() { return start_launchdaemon("/Library/LaunchDaemons/dropbear.plist"); } void setUpSubstitute() { // link CydiaSubstrate.framework -> /usr/lib/libsubstrate.dylib if (file_exists("/Library/Frameworks/CydiaSubstrate.framework") == 0) { [[NSFileManager defaultManager] removeItemAtPath:@"/Library/Frameworks/CydiaSubstrate.framework" error:nil]; } mkdir("/Library/Frameworks", 0755); mkdir("/Library/Frameworks/CydiaSubstrate.framework", 0755); symlink("/usr/lib/libsubstrate.dylib", "/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate"); } int start_jailbreakd_e() { unlink("/var/tmp/jailbreakd.pid"); unlink("/var/run/jailbreakd.pid"); unlink("/var/log/jailbreakd-stderr.log"); unlink("/var/log/jailbreakd-stdout.log"); NSData *blob = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"jailbreakd" ofType:@"plist"]]; NSMutableDictionary *job = [NSPropertyListSerialization propertyListWithData:blob options:NSPropertyListMutableContainers format:nil error:nil]; job[@"EnvironmentVariables"][@"KernelBase"] = [NSString stringWithFormat:@"0x%16llx", kernel_base]; [job writeToFile:@"/Library/LaunchDaemons/jailbreakd.plist" atomically:YES]; chmod("/Library/LaunchDaemons/jailbreakd.plist", 0644); chown("/Library/LaunchDaemons/jailbreakd.plist", 0, 0); pid_t pid = 0; //int rv = run("/bin/launchctl load /Library/LaunchDaemons/jailbreakd.plist"); int rv = start_launchdaemon("/Library/LaunchDaemons/jailbreakd.plist"); if (rv == -1) { return -1; } int ex = 0; waitpid(pid, &ex, 0); NSLog(@"The dragon becomes me!"); NSLog(@"once it is drawn, it cannot be sheathed without causing death"); return 0; } int startJailbreakd() { unlink("/var/tmp/jailbreakd.pid"); NSData *blob = [NSData dataWithContentsOfFile:@"/meridian/jailbreakd/jailbreakd.plist"]; NSMutableDictionary *job = [NSPropertyListSerialization propertyListWithData:blob options:NSPropertyListMutableContainers format:nil error:nil]; job[@"EnvironmentVariables"][@"KernelBase"] = [NSString stringWithFormat:@"0x%16llx", kernel_base]; job[@"EnvironmentVariables"][@"KernProcAddr"] = [NSString stringWithFormat:@"0x%16llx", kernprocaddr]; job[@"EnvironmentVariables"][@"ZoneMapOffset"] = [NSString stringWithFormat:@"0x%16llx", offsets.zone_map]; [job writeToFile:@"/meridian/jailbreakd/jailbreakd.plist" atomically:YES]; chmod("/meridian/jailbreakd/jailbreakd.plist", 0600); chown("/meridian/jailbreakd/jailbreakd.plist", 0, 0); int rv = start_launchdaemon("/meridian/jailbreakd/jailbreakd.plist"); if (rv != 0) return 1; int tries = 0; while (file_exists("/var/tmp/jailbreakd.pid") != 0) { printf("Waiting for jailbreakd \n"); tries++; usleep(300000); // 300ms if (tries >= 100) { NSLog(@"too many tries for jbd - %d", tries); return tries; } } //return 0; usleep(100000); // tell jailbreakd to platformize launchd // this adds skip-lib-val to MACF slot and allows us // to inject pspawn without it being in trust cache // (plus FAT/multiarch in trust cache is a pain to code, i'm lazy) rv = call_jailbreakd(JAILBREAKD_COMMAND_ENTITLE, 1); if (rv != 0) return 2; // inject pspawn_hook.dylib to launchd rv = inject_library(1, "/usr/lib/pspawn_hook.dylib"); //rv = inject_library(1, "/meridian/pspawn_payload.dylib"); if (rv != 0) return 3; /* rv = execprog("/meridian/inject_criticald", (const char **)&(const char*[]) { "/meridian/inject_criticald", "1", "/meridian/pspawn_payload.dylib", NULL }); if (rv != 0) return 3; */ return 0; } int loadLaunchDaemons() { NSArray *daemons = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/Library/LaunchDaemons" error:nil]; for (NSString *file in daemons) { NSString *path = [NSString stringWithFormat:@"/Library/LaunchDaemons/%@", file]; NSLog(@"found launchdaemon: %@", path); chmod([path UTF8String], 0755); chown([path UTF8String], 0, 0); } return start_launchdaemon("/Library/LaunchDaemons"); } void enableHiddenApps() { // enable showing of system apps on springboard // this is some funky killall stuff tho killall("cfprefsd", "-SIGSTOP"); NSMutableDictionary* md = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/mobile/Library/Preferences/com.apple.springboard.plist"]; [md setObject:[NSNumber numberWithBool:YES] forKey:@"SBShowNonDefaultSystemApps"]; [md writeToFile:@"/var/mobile/Library/Preferences/com.apple.springboard.plist" atomically:YES]; killall("cfprefsd", "-9"); }