Path: blob/master/lib/msf/ui/console/command_dispatcher/exploit.rb
19715 views
# -*- coding: binary -*-1module Msf2module Ui3module Console4module CommandDispatcher56###7#8# Exploit module command dispatcher.9#10###11class Exploit1213include Msf::Ui::Console::ModuleCommandDispatcher14include Msf::Ui::Console::ModuleArgumentParsing15include Msf::Ui::Console::ModuleOptionTabCompletion1617#18# Returns the hash of exploit module specific commands.19#20def commands21super.update({22"exploit" => "Launch an exploit attempt",23"rcheck" => "Reloads the module and checks if the target is vulnerable",24"rexploit" => "Reloads the module and launches an exploit attempt",25"run" => "Alias for exploit",26"recheck" => "Alias for rcheck",27"rerun" => "Alias for rexploit",28"reload" => "Just reloads the module"29})30end3132#33# Returns the name of the command dispatcher.34#35def name36"Exploit"37end3839#40# Launches an exploitation single attempt.41#42def exploit_single(mod, opts, &block)43begin44session = mod.exploit_simple(opts, &block)45rescue ::Interrupt46raise $!47rescue ::Msf::OptionValidateError => e48::Msf::Ui::Formatter::OptionValidateError.print_error(mod, e)49rescue ::Exception => e50print_error("Exploit exception (#{mod.refname}): #{e.class} #{e}")51if e.class.to_s != 'Msf::OptionValidateError'52print_error("Call stack:")53e.backtrace.each do |line|54break if line =~ /lib.msf.base.simple/55print_error(" #{line}")56end57end58end5960return session61end6263#64# Tab completion for the run command65#66def cmd_run_tabs(str, words)67fmt = {68'-e' => [ framework.encoders.module_refnames ],69'-f' => [ nil ],70'-h' => [ nil ],71'-j' => [ nil ],72'-J' => [ nil ],73'-n' => [ framework.nops.module_refnames ],74'-o' => [ true ],75'-p' => [ framework.payloads.module_refnames ],76'-r' => [ nil ],77'-t' => [ true ],78'-z' => [ nil ]79}80flags = tab_complete_generic(fmt, str, words)81options = tab_complete_option(active_module, str, words)82flags + options83end8485#86# Tab completion for the exploit command87#88alias cmd_exploit_tabs cmd_run_tabs8990#91# Launches exploitation attempts.92#93def cmd_exploit(*args, opts: {})94if (args.include?('-r') || args.include?('--reload-libs')) && !opts[:previously_reloaded]95driver.run_single('reload_lib -a')96end9798return false unless (args = parse_exploit_opts(args))99100any_session = false101force = args[:force] || false102103minrank = RankingName.invert[framework.datastore['MinimumRank']] || 0104if minrank > mod.rank105if force106print_status("Forcing #{mod.refname} to run despite MinimumRank '#{framework.datastore['MinimumRank']}'")107ilog("Forcing #{mod.refname} to run despite MinimumRank '#{framework.datastore['MinimumRank']}'", 'core')108else109print_error("This exploit is below the minimum rank, '#{framework.datastore['MinimumRank']}'.")110print_error("If you really want to run it, do 'exploit -f' or")111print_error("setg MinimumRank to something lower ('manual' is")112print_error("the lowest and would allow running all exploits).")113return114end115end116117mod_with_opts = mod.replicant118mod_with_opts.datastore.import_options_from_hash(args[:datastore_options])119rhosts = mod_with_opts.datastore['RHOSTS']120has_rhosts_option = mod.options.include?('RHOSTS') ||121mod.options.include?('RHOST') ||122mod.options.include?('rhost') ||123mod.options.include?('rhosts')124125opts = {126'Action' => args[:action],127'Encoder' => args[:encoder] || mod_with_opts.datastore['ENCODER'],128'Payload' => args[:payload] || mod_with_opts.datastore['PAYLOAD'],129'Target' => args[:target] || mod_with_opts.datastore['TARGET'],130'Nop' => args[:nop] || mod_with_opts.datastore['NOP'],131'LocalInput' => driver.input,132'LocalOutput' => driver.output,133'RunAsJob' => args[:jobify] || mod_with_opts.passive?,134'Background' => args[:background] || false,135'Force' => force,136'Quiet' => args[:quiet] || false137}138139driver.run_single('reload_lib -a') if args[:reload_libs]140141if rhosts && has_rhosts_option && !mod.class.included_modules.include?(Msf::Auxiliary::MultipleTargetHosts)142rhosts_walker = Msf::RhostsWalker.new(rhosts, mod_with_opts.datastore)143rhosts_walker_count = rhosts_walker.count144rhosts_walker = rhosts_walker.to_enum145end146147run_mod = nil148149# For multiple targets exploit attempts.150if rhosts_walker && rhosts_walker_count > 1151opts[:multi] = true152rhosts_walker.with_index do |datastore, index|153nmod = mod_with_opts.replicant154nmod.datastore.merge!(datastore)155# If rhost is the last target, let exploit handler stop.156is_last_target = (index + 1) == rhosts_walker_count157opts["multi"] = false if is_last_target158# Catch the interrupt exception to stop the whole module during exploit159begin160print_status("Exploiting target #{datastore['RHOSTS']}")161session = exploit_single(nmod, opts) { |mod| run_mod = mod }162rescue ::Interrupt163print_status("Stopping exploiting current target #{datastore['RHOSTS']}...")164print_status("Control-C again to force quit exploiting all targets.")165begin166Rex.sleep(1)167rescue ::Interrupt168raise $!169end170end171# If we were given a session, report it.172if session173print_status("Session #{session.sid} created in the background.")174any_session = true175end176end177# For single target or no rhosts option.178else179nmod = mod_with_opts.replicant180if rhosts_walker && rhosts_walker_count == 1181nmod.datastore.merge!(rhosts_walker.next)182end183session = exploit_single(nmod, opts) { |mod| run_mod = mod }184# If we were given a session, let's see what we can do with it185if session186any_session = true187if !opts['Background'] && session.interactive?188# If we aren't told to run in the background and the session can be189# interacted with, start interacting with it by issuing the session190# interaction command.191print_line192193driver.run_single("sessions -q -i #{session.sid}")194# Otherwise, log that we created a session195else196# Otherwise, log that we created a session197print_status("Session #{session.sid} created in the background.")198end199200elsif opts['RunAsJob'] && nmod.job_id201# Indicate if he exploit as a job, indicate such so the user doesn't202# wonder what's up.203print_status("Exploit running as background job #{nmod.job_id}.")204# Worst case, the exploit ran but we got no session, bummer.205end206end207208# If we didn't get any session and exploit ended launch.209unless any_session || run_mod&.error.is_a?(Msf::OptionValidateError)210# If we didn't run a payload handler for this exploit it doesn't211# make sense to complain to the user that we didn't get a session212unless mod_with_opts.datastore["DisablePayloadHandler"]213fail_msg = 'Exploit completed, but no session was created.'214print_status(fail_msg)215begin216framework.events.on_session_fail(fail_msg)217rescue ::Exception => e218wlog("Exception in on_session_open event handler: #{e.class}: #{e}")219wlog("Call Stack\n#{e.backtrace.join("\n")}")220end221end222end223end224225alias cmd_run cmd_exploit226227def cmd_exploit_help228print_module_run_or_check_usage(command: :run, options: @@exploit_opts)229end230231alias cmd_run_help cmd_exploit_help232233#234# Reloads an exploit module and checks the target to see if it's235# vulnerable.236#237def cmd_rcheck(*args)238opts = {}239if args.include?('-r') || args.include?('--reload-libs')240driver.run_single('reload_lib -a')241opts[:previously_reloaded] = true242end243244reload()245246cmd_check(*args, opts: opts)247end248249alias cmd_recheck cmd_rcheck250251#252# Reloads an exploit module and launches an exploit.253#254def cmd_rexploit(*args)255opts = {}256if args.include?('-r') || args.include?('--reload-libs')257driver.run_single('reload_lib -a')258opts[:previously_reloaded] = true259end260261return cmd_rexploit_help if args.include?('-h') || args.include?('--help')262263# Stop existing job and reload the module264if reload(true)265# Delegate to the exploit command unless the reload failed266cmd_exploit(*args, opts: opts)267end268end269270alias cmd_rerun cmd_rexploit271alias cmd_rerun_tabs cmd_run_tabs272alias cmd_rexploit_tabs cmd_exploit_tabs273274def cmd_rexploit_help275print_module_run_or_check_usage(276command: :rexploit,277description: 'Reloads a module, stopping any associated job, and launches an exploitation attempt.',278options: @@exploit_opts279)280end281282alias cmd_rerun_help cmd_rexploit_help283284# Select a reasonable default payload and minimally configure it285# @param [Msf::Module] mod286def self.choose_payload(mod)287Msf::Payload.choose_payload(mod)288end289290end291292end end end end293294295