Module: Msf::Ui::Console::ModuleCommandDispatcher
- Includes:
- CommandDispatcher, ModuleArgumentParsing
- Included in:
- CommandDispatcher::Auxiliary, CommandDispatcher::Encoder, CommandDispatcher::Evasion, CommandDispatcher::Exploit, CommandDispatcher::Nop, CommandDispatcher::Payload, CommandDispatcher::Post
- Defined in:
- lib/msf/ui/console/module_command_dispatcher.rb
Overview
Module-specific command dispatcher.
Constant Summary collapse
- @@reload_opts =
Rex::Parser::Arguments.new( '-k' => [ false, 'Stop the current job before reloading.' ], '-h' => [ false, 'Help banner.' ])
Instance Attribute Summary
Attributes included from CommandDispatcher
Attributes included from Rex::Ui::Text::DispatcherShell::CommandDispatcher
Instance Method Summary collapse
- #check_multiple(mod) ⇒ Object
- #check_progress ⇒ Object
- #check_show_progress ⇒ Object
- #check_simple(instance = nil) ⇒ Object
-
#cmd_check(*args, opts: {}) ⇒ Object
Checks to see if a target is vulnerable.
- #cmd_check_help ⇒ Object
-
#cmd_reload(*args) ⇒ Object
Reloads the active module.
- #cmd_reload_help ⇒ Object
- #commands ⇒ Object
-
#mod ⇒ Object
The active driver module, if any.
-
#mod=(m) ⇒ Object
Sets the active driver module.
-
#reload(should_stop_job = false) ⇒ Object
Reload the current module, optionally stopping existing job.
- #report_vuln(instance) ⇒ Object
Methods included from ModuleArgumentParsing
#append_datastore_option, #parse_check_opts, #parse_exploit_opts, #parse_opts, #parse_run_opts, #print_module_run_or_check_usage, #quote_whitespaced_value, #resembles_datastore_assignment?, #resembles_rhost_value?
Methods included from CommandDispatcher
#active_module, #active_module=, #active_session, #active_session=, #build_range_array, #docs_dir, #framework, #initialize, #load_config, #log_error, #remove_lines
Methods included from Rex::Ui::Text::DispatcherShell::CommandDispatcher
#cmd_help, #cmd_help_help, #cmd_help_tabs, #deprecated_cmd, #deprecated_commands, #deprecated_help, #docs_dir, #help_to_s, included, #initialize, #print, #print_error, #print_good, #print_line, #print_status, #print_warning, #tab_complete_directory, #tab_complete_filenames, #tab_complete_generic, #tab_complete_source_address, #unknown_command, #update_prompt
Instance Method Details
#check_multiple(mod) ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/msf/ui/console/module_command_dispatcher.rb', line 52 def check_multiple(mod) rhosts_walker = Msf::RhostsWalker.new(mod.datastore['RHOSTS'], mod.datastore).to_enum rhosts_walker_count = rhosts_walker.count # Short-circuit check_multiple if it's a single host, or doesn't have any hosts set if rhosts_walker_count <= 1 nmod = mod.replicant nmod.datastore.merge!(rhosts_walker.next) if rhosts_walker_count == 1 check_simple(nmod) return end # This part of the code is mostly from scanner.rb @show_progress = framework.datastore['ShowProgress'] || mod.datastore['ShowProgress'] || false @show_percent = ( framework.datastore['ShowProgressPercent'] || mod.datastore['ShowProgressPercent'] ).to_i @range_count = rhosts_walker_count || 0 @range_done = 0 @range_percent = 0 # Set the default thread to 1. The same behavior as before. threads_max = (framework.datastore['THREADS'] || mod.datastore['THREADS'] || 1).to_i @tl = [] if Rex::Compat.is_windows if threads_max > 16 print_warning("Thread count has been adjusted to 16") threads_max = 16 end end if Rex::Compat.is_cygwin if threads_max > 200 print_warning("Thread count has been adjusted to 200") threads_max = 200 end end loop do while @tl.length < threads_max begin datastore = rhosts_walker.next rescue StopIteration datastore = nil end break unless datastore @tl << framework.threads.spawn("CheckHost-#{datastore['RHOSTS']}", false, datastore.dup) { |thr_datastore| # Make sure this is thread-safe when assigning an IP to the RHOST # datastore option nmod = mod.replicant nmod.datastore.merge!(thr_datastore) Msf::Simple::Framework.simplify_module(nmod) check_simple(nmod) } end break if @tl.length == 0 tla = @tl.length # This exception handling is necessary, the first thread with errors can kill the # whole check_multiple and leave the rest of the threads running in background and # only accessible with the threads command (Thread.list) begin @tl.first.join rescue ::Exception => exception if exception.kind_of?(::Interrupt) raise exception else elog('Error encountered with first Thread', error: exception) end end @tl.delete_if { |t| not t.alive? } tlb = @tl.length @range_done += (tla - tlb) check_show_progress if @show_progress end end |
#check_progress ⇒ Object
38 39 40 41 |
# File 'lib/msf/ui/console/module_command_dispatcher.rb', line 38 def check_progress return 0 unless @range_done and @range_count pct = (@range_done / @range_count.to_f) * 100 end |
#check_show_progress ⇒ Object
43 44 45 46 47 48 49 50 |
# File 'lib/msf/ui/console/module_command_dispatcher.rb', line 43 def check_show_progress pct = check_progress if(pct >= (@range_percent + @show_percent)) @range_percent = @range_percent + @show_percent tdlen = @range_count.to_s.length print_status("Checked #{"%.#{tdlen}d" % @range_done} of #{@range_count} hosts (#{"%.3d" % pct.to_i}% complete)") end end |
#check_simple(instance = nil) ⇒ Object
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/msf/ui/console/module_command_dispatcher.rb', line 187 def check_simple(instance=nil) unless instance instance = mod end rhost = instance.datastore['RHOST'] rport = instance.datastore['RPORT'] peer = rhost if rport rport = instance.rport if instance.respond_to?(:rport) peer = "#{rhost}:#{rport}" end peer_msg = peer ? "#{peer} - " : '' begin if instance.respond_to?(:check_simple) code = instance.check_simple( 'LocalInput' => driver.input, 'LocalOutput' => driver.output ) else msg = "Check failed: #{instance.type.capitalize} modules do not support check." raise NotImplementedError, msg end if (code && code.kind_of?(Msf::Exploit::CheckCode)) if (code == Msf::Exploit::CheckCode::Vulnerable) print_good("#{peer_msg}#{code[1]}") # Restore RHOST for report_vuln instance.datastore['RHOST'] ||= rhost report_vuln(instance) else print_status("#{peer_msg}#{code[1]}") end else msg = "#{peer_msg}Check failed: The state could not be determined." print_error(msg) elog("#{msg}\n#{caller.join("\n")}") end rescue ::Rex::ConnectionError, ::Rex::ConnectionProxyError, ::Errno::ECONNRESET, ::Errno::EINTR, ::Rex::TimeoutError, ::Timeout::Error => e # Connection issues while running check should be handled by the module print_error("Check failed: #{e.class} #{e}") elog('Check Failed', error: e) rescue ::Msf::Exploit::Failed => e # Handle fail_with and other designated exploit failures print_error("Check failed: #{e.class} #{e}") elog('Check Failed', error: e) rescue ::RuntimeError => e # Some modules raise RuntimeError but we don't necessarily care about those when we run check() elog('Check Failed', error: e) rescue ::NotImplementedError => e print_error(e.) elog('Check Failed', error: e) rescue ::Exception => e print_error("Check failed: #{e.class} #{e}") elog('Check Failed', error: e) end end |
#cmd_check(*args, opts: {}) ⇒ Object
Checks to see if a target is vulnerable.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/msf/ui/console/module_command_dispatcher.rb', line 137 def cmd_check(*args, opts: {}) if (args.include?('-r') || args.include?('--reload-libs')) && !opts[:previously_reloaded] driver.run_single('reload_lib -a') end return false unless (args = parse_check_opts(args)) mod_with_opts = mod.replicant mod_with_opts.datastore.(args[:datastore_options]) begin mod_with_opts.validate rescue ::Msf::OptionValidateError => e ::Msf::Ui::Formatter::OptionValidateError.print_error(mod_with_opts, e) return false end begin check_multiple(mod_with_opts) rescue ::Interrupt # When the user sends interrupt trying to quit the task, some threads will still be active. # This means even though the console tells the user the task has aborted (or at least they # assume so), the checks are still running. Because of this, as soon as we detect interrupt, # we force the threads to die. if @tl @tl.each { |t| t.kill } end print_status("Caught interrupt from the console...") return end end |
#cmd_check_help ⇒ Object
169 170 171 172 173 174 175 |
# File 'lib/msf/ui/console/module_command_dispatcher.rb', line 169 def cmd_check_help print_module_run_or_check_usage(command: :check) print_line('Multi-threaded checks:') print_line('1. set THREADS 10') print_line('2. check') print_line end |
#cmd_reload(*args) ⇒ Object
Reloads the active module
249 250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/msf/ui/console/module_command_dispatcher.rb', line 249 def cmd_reload(*args) if args.include?('-r') || args.include?('--reload-libs') driver.run_single('reload_lib -a') end return cmd_reload_help if args.include?('-h') || args.include?('--help') begin reload rescue log_error("Failed to reload: #{$!}") end end |
#cmd_reload_help ⇒ Object
267 268 269 270 271 272 |
# File 'lib/msf/ui/console/module_command_dispatcher.rb', line 267 def cmd_reload_help print_line "Usage: reload [-k]" print_line print_line "Reloads the current module." print @@reload_opts.usage end |
#commands ⇒ Object
17 18 19 20 21 22 |
# File 'lib/msf/ui/console/module_command_dispatcher.rb', line 17 def commands { "reload" => "Reload the current module from disk", "check" => "Check to see if a target is vulnerable" } end |
#mod ⇒ Object
The active driver module, if any.
27 28 29 |
# File 'lib/msf/ui/console/module_command_dispatcher.rb', line 27 def mod return driver.active_module end |
#mod=(m) ⇒ Object
Sets the active driver module.
34 35 36 |
# File 'lib/msf/ui/console/module_command_dispatcher.rb', line 34 def mod=(m) self.driver.active_module = m end |
#reload(should_stop_job = false) ⇒ Object
Reload the current module, optionally stopping existing job
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
# File 'lib/msf/ui/console/module_command_dispatcher.rb', line 277 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 print_status('Reloading module...') original_mod = self.mod reloaded_mod = framework.modules.reload_module(original_mod) unless reloaded_mod error = framework.modules.module_load_error_by_path[original_mod.file_path] print_error("Failed to reload module: #{error}") self.mod = original_mod else self.mod = reloaded_mod self.mod.init_ui(driver.input, driver.output) end reloaded_mod end |
#report_vuln(instance) ⇒ Object
177 178 179 180 181 182 183 184 185 |
# File 'lib/msf/ui/console/module_command_dispatcher.rb', line 177 def report_vuln(instance) framework.db.report_vuln( workspace: instance.workspace, host: instance.rhost, name: instance.name, info: "This was flagged as vulnerable by the explicit check of #{instance.fullname}.", refs: instance.references ) end |