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" }) 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 def cmd_exploit_help print_line "Usage: exploit [options]" print_line print_line "Launches an exploitation attempt." print @@exploit_opts.usage end # # 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 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 # # Picks a reasonable payload and minimally configures it # def exploit_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', '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', '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