Files
metasploit-gs/lib/msf/ui/console/command_dispatcher/exploit.rb
T
James Lee 5e65976089 Alias 'run' to 'exploit'
Allows console users to use the 'run' command for exploits as well as
auxiliary and post, in the same way that 'exploit' works for all three.
Saves some typing and makes it do the right thing so users don't have to
remember what kind of module they're using.
2013-05-20 11:20:12 -05:00

286 lines
7.4 KiB
Ruby

# -*- coding: binary -*-
module Msf
module Ui
module Console
module CommandDispatcher
###
#
# Exploit module command dispatcher.
#
###
class Exploit
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." ],
"-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." ],
"-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." ])
#
# Returns the hash of exploit module specific commands.
#
def commands
super.update({
"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",
"reload" => "Just reloads the module",
"run" => "Alias for exploit",
"rerun" => "Alias for rexploit",
})
end
#
# Returns the name of the command dispatcher.
#
def name
"Exploit"
end
#
# Checks to see if a target is vulnerable.
#
def cmd_check(*args)
defanged?
begin
code = mod.check_simple(
'LocalInput' => driver.input,
'LocalOutput' => driver.output)
if (code and code.kind_of?(Array) and code.length > 1)
if (code == Msf::Exploit::CheckCode::Vulnerable)
print_good(code[1])
else
print_status(code[1])
end
else
print_error("Check failed: The state could not be determined.")
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
end
end
#
# Launches an exploitation attempt.
#
def cmd_exploit(*args)
defanged?
opt_str = nil
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
@@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
when '-h'
cmd_exploit_help
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
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
# 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
# If we didn't run a payload handler for this exploit it doesn't
# make sense to complain to the user that we didn't get a session
unless (mod.datastore["DisablePayloadHandler"])
print_status("Exploit completed, but no session was created.")
end
end
end
alias cmd_run cmd_exploit
def cmd_exploit_help
print_line "Usage: exploit [options]"
print_line
print_line "Launches an exploitation attempt."
print @@exploit_opts.usage
end
alias cmd_run_help cmd_exploit_help
#
# Reloads an exploit module and checks the target to see if it's
# vulnerable.
#
def cmd_rcheck(*args)
reload()
cmd_check(*args)
end
#
# Reloads an exploit module and launches an exploit.
#
def cmd_rexploit(*args)
return cmd_rexploit_help if args.include? "-h"
# Stop existing job and reload the module
if reload(true)
# Delegate to the exploit command unless the reload failed
cmd_exploit(*args)
end
end
alias cmd_rerun cmd_rexploit
def cmd_rexploit_help
print_line "Usage: rexploit [options]"
print_line
print_line "Reloads a module, stopping any associated job, and launches an exploitation attempt."
print @@exploit_opts.usage
end
alias cmd_rerun_help cmd_rexploit_help
#
# Picks a reasonable payload and minimally configures it
#
def self.choose_payload(mod, target)
# 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'
# 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',
'ruby/shell_reverse_tcp',
'cmd/unix/interact',
'cmd/unix/reverse',
'cmd/unix/reverse_perl',
'cmd/unix/reverse_netcat_gaping',
'windows/meterpreter/reverse_nonx_tcp',
'windows/meterpreter/reverse_ord_tcp',
'windows/shell/reverse_tcp',
'generic/shell_reverse_tcp'
]
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
end
return
end
end
end end end end