123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545 |
- //
- // helpers.m
- // Meridian
- //
- // Created by Ben Sparkes on 30/12/2017.
- // Copyright © 2017 Ben Sparkes. All rights reserved.
- //
- #include "helpers.h"
- #include "ViewController.h"
- #include "kernel.h"
- #include "untar.h"
- #include "amfi.h"
- #include "jailbreak_daemonUser.h"
- #include <dirent.h>
- #include <unistd.h>
- #include <dlfcn.h>
- #include <sys/fcntl.h>
- #include <sys/spawn.h>
- #include <sys/stat.h>
- #include <sys/sysctl.h>
- #import <Foundation/Foundation.h>
- int call_jailbreakd(int command, pid_t pid) {
- mach_port_t jbd_port;
- if (bootstrap_look_up(bootstrap_port, "zone.sparkes.jailbreakd", &jbd_port) != 0) {
- return -1;
- }
-
- return jbd_call(jbd_port, command, pid);
- }
- uint64_t find_proc_by_name(char* name) {
- uint64_t proc = rk64(kernprocaddr + 0x08);
-
- while (proc) {
- char proc_name[40] = { 0 };
-
- kread(proc + 0x26c, proc_name, 40);
-
- if (!strcmp(name, proc_name)) {
- return proc;
- }
-
- proc = rk64(proc + 0x08);
- }
-
- return 0;
- }
- uint64_t find_proc_by_pid(uint32_t pid) {
- uint64_t proc = rk64(kernprocaddr + 0x08);
-
- while (proc) {
- uint32_t proc_pid = rk32(proc + 0x10);
-
- if (pid == proc_pid) {
- return proc;
- }
-
- proc = rk64(proc + 0x08);
- }
-
- return 0;
- }
- uint32_t get_pid_for_name(char* name) {
- uint64_t proc = find_proc_by_name(name);
- if (proc == 0) {
- return 0;
- }
-
- return rk32(proc + 0x10);
- }
- int uicache() {
- return execprog("/bin/uicache", NULL);
- }
- int start_launchdaemon(const char *path) {
- int ret = inject_trust("/bin/launchctl");
- if (ret != 0) {
- NSLog(@"Failed to inject trust to /bin/launchctl: %d", ret);
- return -30;
- }
-
- chmod(path, 0755);
- chown(path, 0, 0);
- return execprog("/bin/launchctl", (const char **)&(const char*[]) {
- "/bin/launchctl",
- "load",
- "-w",
- path,
- NULL
- });
- }
- int respring() {
- pid_t springBoard = get_pid_for_name("backboardd");
- if (springBoard == 0) {
- return 1;
- }
-
- kill(springBoard, 9);
- return 0;
- }
- int inject_library(pid_t pid, const char *path) {
- mach_port_t task_port;
- kern_return_t ret = task_for_pid(mach_task_self(), pid, &task_port);
- if (ret != KERN_SUCCESS || task_port == MACH_PORT_NULL) {
- task_port = task_for_pid_workaround(pid);
- if (task_port == MACH_PORT_NULL) {
- NSLog(@"[injector] failed to get task for pid %d", pid);
- return ret;
- }
- }
-
- NSLog(@"[injector] got task port: %x", task_port);
-
- call_remote(task_port, dlopen, 2, REMOTE_CSTRING(path), REMOTE_LITERAL(RTLD_NOW));
- uint64_t error = call_remote(task_port, dlerror, 0);
- if (error != 0) {
- uint64_t len = call_remote(task_port, strlen, 1, REMOTE_LITERAL(error));
- char* local_cstring = malloc(len + 1);
- remote_read_overwrite(task_port, error, (uint64_t)local_cstring, len + 1);
-
- NSLog(@"[injector] error: %s", local_cstring);
- return -1;
- }
-
- return 0;
- }
- int killall(const char *procname, const char *kill) {
- return execprog("/usr/bin/killall", (const char **)&(const char *[]) {
- "/usr/bin/killall",
- kill,
- procname,
- NULL
- });
- }
- int check_for_jailbreak() {
- int csops(pid_t pid, unsigned int ops, void *useraddr, size_t usersize);
-
- uint32_t flags;
- csops(getpid(), 0, &flags, 0);
-
- return flags & CS_PLATFORM_BINARY;
- }
- char *itoa(long n) {
- int len = n==0 ? 1 : floor(log10l(labs(n)))+1;
- if (n<0) len++; // room for negative sign '-'
-
- char *buf = calloc(sizeof(char), len+1); // +1 for null
- snprintf(buf, len+1, "%ld", n);
- return buf;
- }
- // remember: returns 0 if file exists
- int file_exists(const char *path) {
- return access(path, F_OK);
- }
- void read_file(const char *path) {
- char buf[65] = {0};
- int fd = open(path, O_RDONLY);
- if (fd == -1) {
- perror("open path");
- return;
- }
-
- printf("contents of %s: \n ------------------------- \n", path);
- while(read(fd, buf, sizeof(buf) - 1) == sizeof(buf) - 1) {
- printf("%s", buf);
- }
- printf("%s", buf);
- printf("\n-------------------------\n");
-
- close(fd);
- }
- int cp(const char *from, const char *to) {
- int fd_to, fd_from;
- char buf[4096];
- ssize_t nread;
- int saved_errno;
-
- fd_from = open(from, O_RDONLY);
- if (fd_from < 0)
- return -1;
-
- fd_to = open(to, O_WRONLY | O_CREAT | O_EXCL, 0666);
- if (fd_to < 0)
- goto out_error;
-
- while ((nread = read(fd_from, buf, sizeof buf)) > 0)
- {
- char *out_ptr = buf;
- ssize_t nwritten;
-
- do {
- nwritten = write(fd_to, out_ptr, nread);
-
- if (nwritten >= 0)
- {
- nread -= nwritten;
- out_ptr += nwritten;
- }
- else if (errno != EINTR)
- {
- goto out_error;
- }
- } while (nread > 0);
- }
-
- if (nread == 0)
- {
- if (close(fd_to) < 0)
- {
- fd_to = -1;
- goto out_error;
- }
- close(fd_from);
-
- /* Success! */
- return 0;
- }
-
- out_error:
- saved_errno = errno;
-
- close(fd_from);
- if (fd_to >= 0)
- close(fd_to);
-
- errno = saved_errno;
- return -1;
- }
- // https://stackoverflow.com/questions/1121383/counting-the-number-of-files-in-a-directory-using-c
- int num_files(const char *path) {
- if (file_exists(path) != 0) {
- return -1;
- }
-
- int file_count = 0;
- DIR * dirp;
- struct dirent * entry;
- dirp = opendir(path);
- while ((entry = readdir(dirp)) != NULL) {
- if (entry->d_type == DT_REG) {
- file_count++;
- }
- }
- closedir(dirp);
-
- return file_count;
- }
- char* bundled_file(const char *filename) {
- return concat(bundle_path(), filename);
- }
- char* bundle_path() {
- CFBundleRef mainBundle = CFBundleGetMainBundle();
- CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
- int len = 4096;
- char* path = malloc(len);
-
- CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8*)path, len);
-
- return concat(path, "/");
- }
- int extract_bundle(const char* bundle_name, const char* directory) {
- int ret;
-
- char *tarFile = NULL;
- asprintf(&tarFile, "%s/%s", directory, bundle_name);
-
- ret = file_exists(bundled_file(bundle_name));
- if (ret != 0) {
- NSLog(@"file does not exist: %s", bundled_file(bundle_name));
- return -1;
- }
-
- ret = file_exists(directory);
- if (file_exists(directory) != 0) {
- NSLog(@"directory does not exist: %s", directory);
- return -2;
- }
-
- ret = cp(bundled_file(bundle_name), tarFile);
- if (ret != 0) {
- NSLog(@"cp has failed: %d", ret);
- return -3;
- }
-
- ret = chdir(directory);
- if (ret != 0) {
- NSLog(@"failed to chdir *rolls eyes* code %d", ret);
- return -4;
- }
-
- ret = untar(fopen(tarFile, "r"), bundle_name);
- NSLog(@"untar returned: %d", ret);
- if (ret != 0) {
- return -5;
- }
-
- ret = unlink(tarFile);
- if (ret != 0) {
- NSLog(@"now fucking `unlink` is failing tooo? %d", ret);
- return -6;
- }
-
- free(tarFile);
- return 0;
- }
- int extract_bundle_tar(const char *bundle_name) {
- const char *file_path = bundled_file(bundle_name);
-
- if (file_exists(file_path) != 0) {
- log_message([NSString stringWithFormat:@"Error, bundle file %s was not found at path %s!",
- bundle_name, file_path]);
- return -1;
- }
-
- return execprog("/meridian/tar", (const char **)&(const char*[]) {
- "/meridian/tar",
- "--preserve-permissions",
- "--no-overwrite-dir",
- "-C",
- "/",
- "-xvf",
- file_path,
- NULL
- });
- }
- void touch_file(char *path) {
- fclose(fopen(path, "w+"));
- }
- // https://stackoverflow.com/questions/8465006/how-do-i-concatenate-two-strings-in-c
- char* concat(const char *s1, const char *s2) {
- char *result = malloc(strlen(s1)+strlen(s2)+1);
- strcpy(result, s1);
- strcat(result, s2);
- return result;
- }
- void grant_csflags(pid_t pid) {
- int tries = 3;
- while (tries-- > 0) {
- uint64_t proc = find_proc_by_pid(pid);
- if (proc == 0) {
- sleep(1);
- continue;
- }
-
- uint32_t csflags = rk32(proc + 0x2a8);
- csflags = (csflags |
- CS_PLATFORM_BINARY |
- CS_INSTALLER |
- CS_GET_TASK_ALLOW)
- & ~(CS_RESTRICT | CS_HARD);
- wk32(proc + 0x2a8, csflags);
- break;
- }
- }
- // creds to stek29 on this one
- int execprog(const char *prog, const char* args[]) {
- if (args == NULL) {
- args = (const char **)&(const char*[]){ prog, NULL };
- }
-
- if (file_exists("/meridian") != 0) {
- mkdir("/meridian", 0755);
- }
- if (file_exists("/meridian/logs") != 0) {
- mkdir("/meridian/logs", 0755);
- }
-
- const char *logfile = [NSString stringWithFormat:@"/meridian/logs/%@-%lu",
- [[NSMutableString stringWithUTF8String:prog] stringByReplacingOccurrencesOfString:@"/" withString:@"_"],
- time(NULL)].UTF8String;
-
- NSString *prog_args = @"";
- for (const char **arg = args; *arg != NULL; ++arg) {
- prog_args = [prog_args stringByAppendingString:[NSString stringWithFormat:@"%s ", *arg]];
- }
- NSLog(@"[execprog] Spawning [ %@ ] to logfile [ %s ]", prog_args, logfile);
-
- int rv;
- posix_spawn_file_actions_t child_fd_actions;
- if ((rv = posix_spawn_file_actions_init (&child_fd_actions))) {
- perror ("posix_spawn_file_actions_init");
- return rv;
- }
- if ((rv = posix_spawn_file_actions_addopen (&child_fd_actions, STDOUT_FILENO, logfile,
- O_WRONLY | O_CREAT | O_TRUNC, 0666))) {
- perror ("posix_spawn_file_actions_addopen");
- return rv;
- }
- if ((rv = posix_spawn_file_actions_adddup2 (&child_fd_actions, STDOUT_FILENO, STDERR_FILENO))) {
- perror ("posix_spawn_file_actions_adddup2");
- return rv;
- }
-
- pid_t pd;
- if ((rv = posix_spawn(&pd, prog, &child_fd_actions, NULL, (char**)args, NULL))) {
- printf("posix_spawn error: %d (%s)\n", rv, strerror(rv));
- return rv;
- }
-
- NSLog(@"[execprog] Process spawned with pid %d", pd);
-
- grant_csflags(pd);
-
- int ret, status;
- do {
- ret = waitpid(pd, &status, 0);
- if (ret > 0) {
- NSLog(@"'%s' exited with %d (sig %d)\n", prog, WEXITSTATUS(status), WTERMSIG(status));
- } else if (errno != EINTR) {
- NSLog(@"waitpid error %d: %s\n", ret, strerror(errno));
- }
- } while (ret < 0 && errno == EINTR);
-
- char buf[65] = {0};
- int fd = open(logfile, O_RDONLY);
- if (fd == -1) {
- perror("open logfile");
- return 1;
- }
-
- NSLog(@"contents of %s:", logfile);
- NSLog(@"-------------------------");
- NSString *outputString = @"";
- while(read(fd, buf, sizeof(buf) - 1) == sizeof(buf) - 1) {
- outputString = [outputString stringByAppendingString:[NSString stringWithFormat:@"%s", buf]];
- }
- NSLog(@"%@", outputString);
- NSLog(@"-------------------------");
-
- close(fd);
- remove(logfile);
- return (int8_t)WEXITSTATUS(status);
- }
- // too lazy to find & add IOKit headers so here we are
- typedef mach_port_t io_service_t;
- typedef mach_port_t io_connect_t;
- extern const mach_port_t kIOMasterPortDefault;
- CFMutableDictionaryRef IOServiceMatching(const char *name) CF_RETURNS_RETAINED;
- io_service_t IOServiceGetMatchingService(mach_port_t masterPort, CFDictionaryRef matching CF_RELEASES_ARGUMENT);
- kern_return_t IOServiceOpen(io_service_t service, task_port_t owningTask, uint32_t type, io_connect_t *client);
- kern_return_t IOConnectCallAsyncStructMethod(mach_port_t connection, uint32_t selector, mach_port_t wake_port, uint64_t *reference, uint32_t referenceCnt, const void *inputStruct, size_t inputStructCnt, void *outputStruct, size_t *outputStructCnt);
- // credits to tihmstar
- void restart_device() {
- // open user client
- CFMutableDictionaryRef matching = IOServiceMatching("IOSurfaceRoot");
- io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, matching);
- io_connect_t connect = 0;
- IOServiceOpen(service, mach_task_self(), 0, &connect);
-
- // add notification port with same refcon multiple times
- mach_port_t port = 0;
- mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
- uint64_t references;
- uint64_t input[3] = {0};
- input[1] = 1234; // keep refcon the same value
- while (1) {
- IOConnectCallAsyncStructMethod(connect, 17, port, &references, 1, input, sizeof(input), NULL, NULL);
- }
- }
- // credits to tihmstar
- double uptime() {
- struct timeval boottime;
- size_t len = sizeof(boottime);
- int mib[2] = { CTL_KERN, KERN_BOOTTIME };
- if (sysctl(mib, 2, &boottime, &len, NULL, 0) < 0) {
- return -1.0;
- }
-
- time_t bsec = boottime.tv_sec, csec = time(NULL);
-
- return difftime(csec, bsec);
- }
- // credits to tihmstar
- void suspend_all_threads() {
- thread_act_t other_thread, current_thread;
- unsigned int thread_count;
- thread_act_array_t thread_list;
-
- current_thread = mach_thread_self();
- int result = task_threads(mach_task_self(), &thread_list, &thread_count);
- if (result == -1) {
- exit(1);
- }
- if (!result && thread_count) {
- for (unsigned int i = 0; i < thread_count; ++i) {
- other_thread = thread_list[i];
- if (other_thread != current_thread) {
- int kr = thread_suspend(other_thread);
- if (kr != KERN_SUCCESS) {
- mach_error("thread_suspend:", kr);
- exit(1);
- }
- }
- }
- }
- }
- // credits to tihmstar
- void resume_all_threads() {
- thread_act_t other_thread, current_thread;
- unsigned int thread_count;
- thread_act_array_t thread_list;
-
- current_thread = mach_thread_self();
- int result = task_threads(mach_task_self(), &thread_list, &thread_count);
- if (!result && thread_count) {
- for (unsigned int i = 0; i < thread_count; ++i) {
- other_thread = thread_list[i];
- if (other_thread != current_thread) {
- int kr = thread_resume(other_thread);
- if (kr != KERN_SUCCESS) {
- mach_error("thread_suspend:", kr);
- }
- }
- }
- }
- }
|