Files
metasploit-gs/lib/msf/ui/console/command_dispatcher/exploit.rb
T

309 lines
7.7 KiB
Ruby
Raw Normal View History

2005-07-10 07:15:20 +00:00
module Msf
module Ui
module Console
module CommandDispatcher
2005-11-15 15:11:43 +00:00
###
#
# Exploit module command dispatcher.
#
###
2005-07-10 07:15:20 +00:00
class Exploit
2005-07-14 20:36:34 +00:00
include Msf::Ui::Console::ModuleCommandDispatcher
@@exploit_opts = Rex::Parser::Arguments.new(
"-e" => [ true, "The payload encoder to use. If none is specified, ENCODER is used." ],
"-f" => [ false, "Force the exploit to run regardless of the value of MinimumRank." ],
"-h" => [ false, "Help banner." ],
2007-02-10 06:54:03 +00:00
"-j" => [ false, "Run in the context of a job." ],
"-n" => [ true, "The NOP generator to use. If none is specified, NOP is used." ],
"-o" => [ true, "A comma separated list of options in VAR=VAL format." ],
"-p" => [ true, "The payload to use. If none is specified, PAYLOAD is used." ],
2005-07-14 20:36:34 +00:00
"-t" => [ true, "The target index to use. If none is specified, TARGET is used." ],
"-z" => [ false, "Do not interact with the session after successful exploitation." ])
2010-11-09 02:31:21 +00:00
@@reload_opts = Rex::Parser::Arguments.new(
'-k' => [ false, 'Stop the current job before reloading.' ],
'-h' => [ false, 'Help banner.' ])
2005-11-15 15:11:43 +00:00
#
# Returns the hash of exploit module specific commands.
#
def commands
{
2005-10-10 00:30:14 +00:00
"check" => "Check to see if a target is vulnerable",
"exploit" => "Launch an exploit attempt",
"rcheck" => "Reloads the module and checks if the target is vulnerable",
"rexploit" => "Reloads the module and launches an exploit attempt",
2010-11-09 02:31:21 +00:00
"reload" => "Just reloads the module"
}
end
2005-11-15 15:11:43 +00:00
#
# Returns the name of the command dispatcher.
#
2005-07-14 20:18:36 +00:00
def name
"Exploit"
end
2005-07-14 20:36:34 +00:00
#
2005-11-15 15:11:43 +00:00
# Checks to see if a target is vulnerable.
2005-07-14 20:36:34 +00:00
#
def cmd_check(*args)
2007-01-30 04:48:35 +00:00
defanged?
2005-07-14 20:36:34 +00:00
begin
2007-01-30 04:48:35 +00:00
2007-03-17 19:39:30 +00:00
code = mod.check_simple(
'LocalInput' => driver.input,
'LocalOutput' => driver.output)
2005-07-14 20:36:34 +00:00
if (code and code.kind_of?(Array) and code.length > 1)
2005-07-14 20:36:34 +00:00
if (code == Msf::Exploit::CheckCode::Vulnerable)
print_good(code[1])
else
print_status(code[1])
2005-07-14 20:36:34 +00:00
end
2005-07-14 20:36:34 +00:00
else
print_error("Check failed: The state could not be determined.")
2005-07-14 20:36:34 +00:00
end
rescue ::Interrupt
raise $!
rescue ::Exception => e
print_error("Exploit check failed: #{e.class} #{e}")
if(e.class.to_s != 'Msf::OptionValidateError')
print_error("Call stack:")
e.backtrace.each do |line|
break if line =~ /lib.msf.base.simple/
print_error(" #{line}")
end
end
2005-07-14 20:36:34 +00:00
end
end
#
2005-11-15 15:11:43 +00:00
# Launches an exploitation attempt.
#
def cmd_exploit(*args)
2007-01-30 04:48:35 +00:00
defanged?
opt_str = nil
2005-07-14 20:36:34 +00:00
payload = mod.datastore['PAYLOAD']
encoder = mod.datastore['ENCODER']
target = mod.datastore['TARGET']
nop = mod.datastore['NOP']
bg = false
jobify = false
force = false
# Always run passive exploits in the background
if (mod.passive?)
jobify = true
end
2005-07-14 20:36:34 +00:00
@@exploit_opts.parse(args) { |opt, idx, val|
case opt
when '-e'
encoder = val
when '-f'
force = true
when '-j'
jobify = true
when '-n'
nop = val
when '-o'
opt_str = val
when '-p'
payload = val
when '-t'
target = val.to_i
when '-z'
bg = true
2005-07-14 20:36:34 +00:00
when '-h'
print(
"Usage: exploit [options]\n\n" +
"Launches an exploitation attempt.\n" +
@@exploit_opts.usage)
return false
end
}
minrank = RankingName.invert[framework.datastore['MinimumRank']] || 0
if minrank > mod.rank
if force
print_status("Forcing #{mod.refname} to run despite MinimumRank '#{framework.datastore['MinimumRank']}'")
ilog("Forcing #{mod.refname} to run despite MinimumRank '#{framework.datastore['MinimumRank']}'", 'core')
else
print_error("This exploit is below the minimum rank, '#{framework.datastore['MinimumRank']}'.")
print_error("If you really want to run it, do 'exploit -f' or")
print_error("setg MinimumRank to something lower ('manual' is")
print_error("the lowest and would allow running all exploits).")
return
end
end
2010-11-09 02:31:21 +00:00
2010-10-04 04:50:10 +00:00
if not payload
payload = exploit_choose_payload(mod, target)
end
begin
session = mod.exploit_simple(
'Encoder' => encoder,
'Payload' => payload,
'Target' => target,
'Nop' => nop,
'OptionStr' => opt_str,
'LocalInput' => driver.input,
'LocalOutput' => driver.output,
'RunAsJob' => jobify)
rescue ::Interrupt
raise $!
rescue ::Exception => e
print_error("Exploit exception (#{mod.refname}): #{e.class} #{e}")
if(e.class.to_s != 'Msf::OptionValidateError')
print_error("Call stack:")
e.backtrace.each do |line|
break if line =~ /lib.msf.base.simple/
print_error(" #{line}")
end
end
end
# If we were given a session, let's see what we can do with it
if (session)
# If we aren't told to run in the background and the session can be
2005-07-17 02:14:15 +00:00
# interacted with, start interacting with it by issuing the session
# interaction command.
if (bg == false and session.interactive?)
print_line
driver.run_single("sessions -q -i #{session.sid}")
# Otherwise, log that we created a session
else
print_status("Session #{session.sid} created in the background.")
end
# If we ran the exploit as a job, indicate such so the user doesn't
# wonder what's up.
elsif (jobify)
if mod.job_id
print_status("Exploit running as background job.")
end
# Worst case, the exploit ran but we got no session, bummer.
else
2006-03-30 15:06:41 +00:00
print_status("Exploit completed, but no session was created.")
end
end
2005-10-10 00:30:14 +00:00
#
2005-11-15 15:11:43 +00:00
# Reloads an exploit module and checks the target to see if it's
# vulnerable.
2005-10-10 00:30:14 +00:00
#
def cmd_rcheck(*args)
2010-11-09 02:31:21 +00:00
reload()
self.mod.init_ui(driver.input, driver.output)
cmd_check(*args)
2005-10-10 00:30:14 +00:00
end
#
2010-11-09 02:31:21 +00:00
# Reload an exploit module, optionally stopping existing job
2005-10-10 00:30:14 +00:00
#
2010-11-09 02:31:21 +00:00
def reload(should_stop_job=false)
if should_stop_job and mod.job_id
print_status('Stopping existing job...')
framework.jobs.stop_job(mod.job_id)
mod.job_id = nil
end
2010-11-09 02:31:21 +00:00
print_status('Reloading module...')
omod = self.mod
self.mod = framework.modules.reload_module(mod)
if(not self.mod)
print_status("Failed to reload module: #{framework.modules.failed[omod.file_path]}")
self.mod = omod
return
end
self.mod.init_ui(driver.input, driver.output)
2010-11-09 02:31:21 +00:00
end
2005-10-10 00:30:14 +00:00
2010-11-09 02:31:21 +00:00
#
# Handles the command to reload an exploit module.
#
def cmd_reload(*args)
# By default, do not stop the existing job
stop_existing = false
@@reload_opts.parse(args) { |opt, idx, val|
case opt
when '-k'
stop_existing = true
when '-h'
print_line "Usage: reload [-k]\n\nReloads the current module."
print_line @@reload_opts.usage
return
end
}
reload(stop_existing)
end
#
# Reloads an exploit module and launches an exploit.
#
def cmd_rexploit(*args)
# Stop existing job and reload the module
reload(true)
# Delegate to the exploit command
cmd_exploit(*args)
2005-10-10 00:30:14 +00:00
end
2010-11-09 02:31:21 +00:00
2010-10-04 04:50:10 +00:00
#
# Picks a reasonable payload and minimally configures it
#
def exploit_choose_payload(mod, target)
2010-11-09 02:31:21 +00:00
2010-10-04 04:50:10 +00:00
# Choose either the real target or an invalid address
# This is used to determine the LHOST value
rhost = mod.datastore['RHOST'] || '50.50.50.50'
2010-11-09 02:31:21 +00:00
2010-10-04 04:50:10 +00:00
# A list of preferred payloads in the best-first order
pref = [
'windows/meterpreter/reverse_tcp',
'java/meterpreter/reverse_tcp',
'php/meterpreter/reverse_tcp',
'php/meterpreter_reverse_tcp',
'cmd/unix/reverse',
'cmd/unix/reverse_perl',
'cmd/unix/reverse_netcat',
'windows/meterpreter/reverse_nonx_tcp',
'windows/meterpreter/reverse_ord_tcp',
'windows/shell/reverse_tcp',
2010-11-09 02:31:21 +00:00
'generic/shell_reverse_tcp'
2010-10-04 04:50:10 +00:00
]
pset = mod.compatible_payloads.map{|x| x[0] }
pref.each do |n|
if(pset.include?(n))
mod.datastore['PAYLOAD'] = n
mod.datastore['LHOST'] = Rex::Socket.source_address(rhost)
return n
end
2010-11-09 02:31:21 +00:00
end
2010-10-04 04:50:10 +00:00
return
end
2005-10-10 00:30:14 +00:00
2005-07-10 07:15:20 +00:00
end
end end end end