Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/msf/ui/console/module_command_dispatcher.rb
Views: 11783
# -*- coding: binary -*-12module Msf3module Ui4module Console56###7#8# Module-specific command dispatcher.9#10###11module ModuleCommandDispatcher1213include Msf::Ui::Console::CommandDispatcher14include Msf::Ui::Console::ModuleArgumentParsing1516def commands17{18"reload" => "Reload the current module from disk",19"check" => "Check to see if a target is vulnerable"20}21end2223#24# The active driver module, if any.25#26def mod27return driver.active_module28end2930#31# Sets the active driver module.32#33def mod=(m)34self.driver.active_module = m35end3637def check_progress38return 0 unless @range_done and @range_count39pct = (@range_done / @range_count.to_f) * 10040end4142def check_show_progress43pct = check_progress44if(pct >= (@range_percent + @show_percent))45@range_percent = @range_percent + @show_percent46tdlen = @range_count.to_s.length47print_status("Checked #{"%.#{tdlen}d" % @range_done} of #{@range_count} hosts (#{"%.3d" % pct.to_i}% complete)")48end49end5051def check_multiple(mod)52rhosts_walker = Msf::RhostsWalker.new(mod.datastore['RHOSTS'], mod.datastore).to_enum53rhosts_walker_count = rhosts_walker.count5455# Short-circuit check_multiple if it's a single host, or doesn't have any hosts set56if rhosts_walker_count <= 157nmod = mod.replicant58nmod.datastore.merge!(rhosts_walker.next) if rhosts_walker_count == 159check_simple(nmod)60return61end6263# This part of the code is mostly from scanner.rb64@show_progress = framework.datastore['ShowProgress'] || mod.datastore['ShowProgress'] || false65@show_percent = ( framework.datastore['ShowProgressPercent'] || mod.datastore['ShowProgressPercent'] ).to_i6667@range_count = rhosts_walker_count || 068@range_done = 069@range_percent = 07071# Set the default thread to 1. The same behavior as before.72threads_max = (framework.datastore['THREADS'] || mod.datastore['THREADS'] || 1).to_i73@tl = []7475if Rex::Compat.is_windows76if threads_max > 1677print_warning("Thread count has been adjusted to 16")78threads_max = 1679end80end8182if Rex::Compat.is_cygwin83if threads_max > 20084print_warning("Thread count has been adjusted to 200")85threads_max = 20086end87end8889loop do90while @tl.length < threads_max91begin92datastore = rhosts_walker.next93rescue StopIteration94datastore = nil95end96break unless datastore9798@tl << framework.threads.spawn("CheckHost-#{datastore['RHOSTS']}", false, datastore.dup) { |thr_datastore|99# Make sure this is thread-safe when assigning an IP to the RHOST100# datastore option101nmod = mod.replicant102nmod.datastore.merge!(thr_datastore)103Msf::Simple::Framework.simplify_module(nmod)104check_simple(nmod)105}106end107108break if @tl.length == 0109110tla = @tl.length111112# This exception handling is necessary, the first thread with errors can kill the113# whole check_multiple and leave the rest of the threads running in background and114# only accessible with the threads command (Thread.list)115begin116@tl.first.join117rescue ::Exception => exception118if exception.kind_of?(::Interrupt)119raise exception120else121elog('Error encountered with first Thread', error: exception)122end123end124125@tl.delete_if { |t| not t.alive? }126tlb = @tl.length127128@range_done += (tla - tlb)129check_show_progress if @show_progress130end131end132133#134# Checks to see if a target is vulnerable.135#136def cmd_check(*args, opts: {})137if (args.include?('-r') || args.include?('--reload-libs')) && !opts[:previously_reloaded]138driver.run_single('reload_lib -a')139end140141return false unless (args = parse_check_opts(args))142143mod_with_opts = mod.replicant144mod_with_opts.datastore.import_options_from_hash(args[:datastore_options])145146begin147mod_with_opts.validate148rescue ::Msf::OptionValidateError => e149::Msf::Ui::Formatter::OptionValidateError.print_error(mod_with_opts, e)150return false151end152153begin154check_multiple(mod_with_opts)155rescue ::Interrupt156# When the user sends interrupt trying to quit the task, some threads will still be active.157# This means even though the console tells the user the task has aborted (or at least they158# assume so), the checks are still running. Because of this, as soon as we detect interrupt,159# we force the threads to die.160if @tl161@tl.each { |t| t.kill }162end163print_status("Caught interrupt from the console...")164return165end166end167168def cmd_check_help169print_module_run_or_check_usage(command: :check)170print_line('Multi-threaded checks:')171print_line('1. set THREADS 10')172print_line('2. check')173print_line174end175176def report_vuln(instance)177framework.db.report_vuln(178workspace: instance.workspace,179host: instance.rhost,180name: instance.name,181info: "This was flagged as vulnerable by the explicit check of #{instance.fullname}.",182refs: instance.references183)184end185186def check_simple(instance=nil)187unless instance188instance = mod189end190191rhost = instance.datastore['RHOST']192rport = instance.datastore['RPORT']193peer = rhost194if rport195rport = instance.rport if instance.respond_to?(:rport)196peer = "#{rhost}:#{rport}"197end198peer_msg = peer ? "#{peer} - " : ''199200begin201if instance.respond_to?(:check_simple)202code = instance.check_simple(203'LocalInput' => driver.input,204'LocalOutput' => driver.output205)206else207msg = "Check failed: #{instance.type.capitalize} modules do not support check."208raise NotImplementedError, msg209end210211if (code && code.kind_of?(Msf::Exploit::CheckCode))212if (code == Msf::Exploit::CheckCode::Vulnerable)213print_good("#{peer_msg}#{code[1]}")214# Restore RHOST for report_vuln215instance.datastore['RHOST'] ||= rhost216report_vuln(instance)217else218print_status("#{peer_msg}#{code[1]}")219end220else221msg = "#{peer_msg}Check failed: The state could not be determined."222print_error(msg)223elog("#{msg}\n#{caller.join("\n")}")224end225rescue ::Rex::ConnectionError, ::Rex::ConnectionProxyError, ::Errno::ECONNRESET, ::Errno::EINTR, ::Rex::TimeoutError, ::Timeout::Error => e226# Connection issues while running check should be handled by the module227print_error("Check failed: #{e.class} #{e}")228elog('Check Failed', error: e)229rescue ::Msf::Exploit::Failed => e230# Handle fail_with and other designated exploit failures231print_error("Check failed: #{e.class} #{e}")232elog('Check Failed', error: e)233rescue ::RuntimeError => e234# Some modules raise RuntimeError but we don't necessarily care about those when we run check()235elog('Check Failed', error: e)236rescue ::NotImplementedError => e237print_error(e.message)238elog('Check Failed', error: e)239rescue ::Exception => e240print_error("Check failed: #{e.class} #{e}")241elog('Check Failed', error: e)242end243end244245#246# Reloads the active module247#248def cmd_reload(*args)249if args.include?('-r') || args.include?('--reload-libs')250driver.run_single('reload_lib -a')251end252253return cmd_reload_help if args.include?('-h') || args.include?('--help')254255begin256reload257rescue258log_error("Failed to reload: #{$!}")259end260end261262@@reload_opts = Rex::Parser::Arguments.new(263'-k' => [ false, 'Stop the current job before reloading.' ],264'-h' => [ false, 'Help banner.' ])265266def cmd_reload_help267print_line "Usage: reload [-k]"268print_line269print_line "Reloads the current module."270print @@reload_opts.usage271end272273#274# Reload the current module, optionally stopping existing job275#276def reload(should_stop_job=false)277if should_stop_job and mod.job_id278print_status('Stopping existing job...')279280framework.jobs.stop_job(mod.job_id)281mod.job_id = nil282end283284print_status('Reloading module...')285286original_mod = self.mod287reloaded_mod = framework.modules.reload_module(original_mod)288289unless reloaded_mod290error = framework.modules.module_load_error_by_path[original_mod.file_path]291292print_error("Failed to reload module: #{error}")293294self.mod = original_mod295else296self.mod = reloaded_mod297298self.mod.init_ui(driver.input, driver.output)299end300301reloaded_mod302end303304end305306307end end end308309310311