clean up how help works, pull cmd_reload up so all module types can use it

git-svn-id: file:///home/svn/framework3/trunk@11658 4d416f70-5f16-0410-b530-b9f4589650da
unstable
James Lee 2011-01-28 03:29:20 +00:00
parent 1af730148f
commit a7b5e831f7
8 changed files with 225 additions and 214 deletions

View File

@ -94,6 +94,10 @@ module ModuleCommandDispatcher
include Msf::Ui::Console::CommandDispatcher include Msf::Ui::Console::CommandDispatcher
def commands
{ "reload" => "Reload the current module from disk" }
end
# #
# The active driver module, if any. # The active driver module, if any.
# #
@ -108,6 +112,49 @@ module ModuleCommandDispatcher
self.driver.active_module = m self.driver.active_module = m
end end
#
# Reloads the active module
#
def cmd_reload(*args)
begin
reload
rescue
log_error("Failed to reload: #{$!}")
end
end
def cmd_reload_help
print_line "Usage: reload [-k]"
print_line
print_line "Reloads the current module."
print @@reload_opts.usage
end
#
# Reload the current module, optionally stopping existing job
#
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...')
omod = self.mod
self.mod = framework.modules.reload_module(mod)
if(not self.mod)
print_status("Failed to reload module: #{framework.modules.failed[omod.file_path]}")
self.mod = omod
return
end
self.mod.init_ui(driver.input, driver.output)
end
end end
end end end end end end

View File

@ -25,13 +25,13 @@ class Auxiliary
# Returns the hash of commands specific to auxiliary modules. # Returns the hash of commands specific to auxiliary modules.
# #
def commands def commands
{ super.update({
"run" => "Launches the auxiliary module", "run" => "Launches the auxiliary module",
"rerun" => "Reloads and launches the auxiliary module", "rerun" => "Reloads and launches the auxiliary module",
"exploit" => "This is an alias for the run command", "exploit" => "This is an alias for the run command",
"rexploit" => "This is an alias for the rerun command", "rexploit" => "This is an alias for the rerun command",
"reload" => "Reloads the auxiliary module" "reload" => "Reloads the auxiliary module"
}.merge( (mod ? mod.auxiliary_commands : {}) ) }).merge( (mod ? mod.auxiliary_commands : {}) )
end end
# #
@ -56,58 +56,16 @@ class Auxiliary
"Auxiliary" "Auxiliary"
end end
#
# This is an alias for 'rerun'
#
def cmd_rexploit(*args)
cmd_rerun(*args)
end
#
# Reloads an auxiliary module
#
def cmd_reload(*args)
begin
omod = self.mod
self.mod = framework.modules.reload_module(mod)
if(not self.mod)
print_error("Failed to reload module: #{framework.modules.failed[omod.file_path]}")
self.mod = omod
end
rescue
log_error("Failed to reload: #{$!}")
end
end
# #
# Reloads an auxiliary module and executes it # Reloads an auxiliary module and executes it
# #
def cmd_rerun(*args) def cmd_rerun(*args)
if mod.job_id reload(true)
print_status("Stopping existing job...")
framework.jobs.stop_job(mod.job_id)
mod.job_id = nil
end
omod = self.mod
self.mod = framework.modules.reload_module(mod)
if(not self.mod)
print_error("Failed to reload module: #{framework.modules.failed[omod.file_path]}")
self.mod = omod
return
end
cmd_run(*args) cmd_run(*args)
end end
# alias cmd_rexploit cmd_rerun
# This is an alias for 'run'
#
def cmd_exploit(*args)
cmd_run(*args)
end
# #
# Executes an auxiliary module # Executes an auxiliary module
@ -131,10 +89,7 @@ class Auxiliary
when '-q' when '-q'
quiet = true quiet = true
when '-h' when '-h'
print( cmd_run_help
"Usage: run [options]\n\n" +
"Launches an auxiliary module.\n" +
@@auxiliary_opts.usage)
return false return false
end end
} }
@ -177,6 +132,17 @@ class Auxiliary
end end
end end
alias cmd_exploit cmd_run
def cmd_run_help
print_line "Usage: run [options]"
print_line
print_line "Launches an auxiliary module."
print @@auxiliary_opts.usage
end
alias cmd_exploit_help cmd_run_help
end end
end end end end end end end end

View File

@ -284,9 +284,7 @@ class Core
# #
def cmd_connect(*args) def cmd_connect(*args)
if args.length < 2 or args.include?("-h") if args.length < 2 or args.include?("-h")
print( "Usage: connect [options] <host> <port>\n\n" + cmd_connect_help
"Communicate with a host, similar to interacting via netcat.\n" +
@@connect_opts.usage)
return false return false
end end
@ -460,6 +458,14 @@ class Core
true true
end end
def cmd_connect_help
print_line "Usage: connect [options] <host> <port>"
print_line
print_line "Communicate with a host, similar to interacting via netcat, taking advantage of"
print_line "any configured session pivoting."
print @@connect_opts.usage
end
# #
# Instructs the driver to stop executing. # Instructs the driver to stop executing.
# #
@ -485,44 +491,6 @@ class Core
Rex::ThreadSafe.sleep(args[0].to_f) Rex::ThreadSafe.sleep(args[0].to_f)
end end
#
# Displays the command help banner or an individual command's help banner
# if we can figure out how to invoke it.
#
def cmd_help(*args)
if args and args.length > 0 and commands.include?(args[0])
if self.respond_to? "cmd_"+ args[0] + "_help"
self.send("cmd_"+ args[0] + "_help")
else
#
# This part is done in a hackish way because not all of the
# usage info is available from self.commands() or @@*_opts, so
# we check @@<cmd>_opts for "-h". It's non-optimal because
# several commands have usage info, but don't use -h to invoke
# it.
begin
opts = eval("@@" + args[0] + "_opts")
rescue
end
if opts and opts.include?("-h")
self.send("cmd_" + args[0], "-h")
else
print_line("No help available for #{args[0]}")
end
end
else
print(driver.help_to_s)
end
end
def cmd_help_tabs(str, words)
return [] if words.length > 1
return commands.keys
end
alias cmd_? cmd_help
# #
# Displays information about one or more module. # Displays information about one or more module.
# #
@ -620,10 +588,7 @@ class Core
dump_info = true dump_info = true
job_id = val job_id = val
when "-h" when "-h"
print( cmd_jobs_help
"Usage: jobs [options]\n\n" +
"Active job manipulation and interaction.\n" +
@@jobs_opts.usage())
return false return false
end end
} }
@ -670,6 +635,13 @@ class Core
[] []
end end
def cmd_jobs_help
print_line "Usage: jobs [options]"
print_line
print_line "Active job manipulation and interaction."
print @@jobs_opts.usage()
end
def cmd_kill(*args) def cmd_kill(*args)
cmd_jobs("-k", *args) cmd_jobs("-k", *args)
end end
@ -679,6 +651,13 @@ class Core
framework.jobs.keys framework.jobs.keys
end end
def cmd_kill_help
print_line "Usage: kill <job1> [job2 ...]"
print_line
print_line "Equivalent to 'jobs -k job1 -k job2 ...'"
print @@jobs_opts.usage()
end
# #
# Displays and manages running background threads # Displays and manages running background threads
# #
@ -725,10 +704,7 @@ class Core
dump_info = true dump_info = true
thread_id = val.to_i thread_id = val.to_i
when "-h" when "-h"
print( cmd_threads_help
"Usage: threads [options]\n\n" +
"Background thread management.\n" +
@@threads_opts.usage())
return false return false
end end
} }
@ -800,6 +776,13 @@ class Core
[] []
end end
def cmd_threads_help
print(
"Usage: threads [options]\n\n" +
"Background thread management.\n" +
@@threads_opts.usage())
end
# Loads a plugin from the supplied path. If no absolute path is supplied, # Loads a plugin from the supplied path. If no absolute path is supplied,
# the framework root plugin directory is used. # the framework root plugin directory is used.
# #
@ -1132,8 +1115,8 @@ class Core
def cmd_loadpath(*args) def cmd_loadpath(*args)
defanged? defanged?
if (args.length == 0) if (args.length == 0 or args.include? "-h")
print_error("No search paths were provided.") cmd_loadpath_help
return true return true
end end
@ -1205,6 +1188,13 @@ class Core
return paths return paths
end end
def cmd_loadpath_help
print_line "Usage: loadpath /path/to/modules"
print_line
print_line "Loads modules from the given directory which should contain subdirectories for"
print_line "module types, e.g. /path/to/modules/exploits"
end
# #
# Searches modules (name and description) for specified regex # Searches modules (name and description) for specified regex
# #
@ -1216,8 +1206,7 @@ class Core
@@search_opts.parse(args) { |opt, idx, val| @@search_opts.parse(args) { |opt, idx, val|
case opt case opt
when "-h" when "-h"
print_line("Usage: search [options] [regex]") cmd_search_help
print(@@search_opts.usage)
return return
when "-t" when "-t"
section = val section = val
@ -1284,12 +1273,18 @@ class Core
when "-r" when "-r"
return RankingName.sort.map{|r| r[1]} return RankingName.sort.map{|r| r[1]}
when "-t" when "-t"
return %w{auxiliary encoder exploit nop payload} return %w{auxiliary encoder exploit nop payload post}
end end
[] []
end end
def cmd_search_help
print_line "Usage: search [options] [regex]"
print_line
print @@search_opts.usage
end
# #
# Provides an interface to the sessions currently active in the framework. # Provides an interface to the sessions currently active in the framework.
# #
@ -1359,10 +1354,7 @@ class Core
# Display help banner # Display help banner
when "-h" when "-h"
print( cmd_sessions_help
"Usage: sessions [options]\n\n" +
"Active session manipulation and interaction.\n" +
@@sessions_opts.usage())
return false return false
else else
extra << val extra << val
@ -1568,6 +1560,13 @@ class Core
[] []
end end
def cmd_sessions_help
print_line "Usage: sessions [options]"
print_line
print_line "Active session manipulation and interaction."
print(@@sessions_opts.usage())
end
# #
# Sets a name to a value in a context aware environment. # Sets a name to a value in a context aware environment.
# #
@ -1736,21 +1735,7 @@ class Core
args.each { |type| args.each { |type|
case type case type
when '-h' when '-h'
global_opts = %w{all encoders nops exploits payloads auxiliary plugins options} cmd_show_help
opts = ''
global_opts.each { |el|
opts << ', ' if opts.length > 0
opts << el
}
print_status("Valid parameters for the \"show\" command are: #{opts}")
module_opts = %w{ advanced evasion targets actions }
opts = ''
module_opts.each { |el|
opts << ', ' if opts.length > 0
opts << el
}
print_status("Additional module-specific parameters are: #{opts}")
when 'all' when 'all'
show_encoders show_encoders
show_nops show_nops
@ -1835,6 +1820,14 @@ class Core
return res return res
end end
def cmd_show_help
global_opts = %w{all encoders nops exploits payloads auxiliary plugins options}
print_status("Valid parameters for the \"show\" command are: #{global_opts.join(", ")}")
module_opts = %w{ advanced evasion targets actions }
print_status("Additional module-specific parameters are: #{module_opts.join(", ")}")
end
# #
# Unloads a plugin by its name. # Unloads a plugin by its name.
# #
@ -1891,11 +1884,7 @@ class Core
# No arguments? No cookie. # No arguments? No cookie.
if (args.length == 0) if (args.length == 0)
print( cmd_unset_help
"Usage: unset var1 var2 var3 ...\n\n" +
"The unset command is used to unset one or more variables.\n" +
"To flush all entires, specify 'all' as the variable name\n")
return false return false
end end
@ -1934,6 +1923,14 @@ class Core
datastore.keys datastore.keys
end end
def cmd_unset_help
print_line "Usage: unset [-g] var1 var2 var3 ..."
print_line
print_line "The unset command is used to unset one or more variables."
print_line "To flush all entires, specify 'all' as the variable name."
print_line "With -g, operates on global datastore variables."
end
# #
# Unsets variables in the global data store. # Unsets variables in the global data store.
# #
@ -1950,6 +1947,8 @@ class Core
self.framework.datastore.keys self.framework.datastore.keys
end end
alias cmd_unsetg_help cmd_unset_help
# #
# Uses a module. # Uses a module.
# #

View File

@ -31,13 +31,13 @@ class Exploit
# Returns the hash of exploit module specific commands. # Returns the hash of exploit module specific commands.
# #
def commands def commands
{ super.update({
"check" => "Check to see if a target is vulnerable", "check" => "Check to see if a target is vulnerable",
"exploit" => "Launch an exploit attempt", "exploit" => "Launch an exploit attempt",
"rcheck" => "Reloads the module and checks if the target is vulnerable", "rcheck" => "Reloads the module and checks if the target is vulnerable",
"rexploit" => "Reloads the module and launches an exploit attempt", "rexploit" => "Reloads the module and launches an exploit attempt",
"reload" => "Just reloads the module" "reload" => "Just reloads the module"
} })
end end
# #
@ -124,10 +124,7 @@ class Exploit
when '-z' when '-z'
bg = true bg = true
when '-h' when '-h'
print( cmd_exploit_help
"Usage: exploit [options]\n\n" +
"Launches an exploitation attempt.\n" +
@@exploit_opts.usage)
return false return false
end end
} }
@ -203,6 +200,13 @@ class Exploit
end 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 # Reloads an exploit module and checks the target to see if it's
# vulnerable. # vulnerable.
@ -210,68 +214,28 @@ class Exploit
def cmd_rcheck(*args) def cmd_rcheck(*args)
reload() reload()
self.mod.init_ui(driver.input, driver.output)
cmd_check(*args) cmd_check(*args)
end end
#
# Reload an exploit module, optionally stopping existing job
#
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...')
omod = self.mod
self.mod = framework.modules.reload_module(mod)
if(not self.mod)
print_status("Failed to reload module: #{framework.modules.failed[omod.file_path]}")
self.mod = omod
return
end
self.mod.init_ui(driver.input, driver.output)
end
#
# Handles the command to reload an exploit module.
#
def cmd_reload(*args)
# By default, do not stop the existing job
stop_existing = false
@@reload_opts.parse(args) { |opt, idx, val|
case opt
when '-k'
stop_existing = true
when '-h'
print_line "Usage: reload [-k]\n\nReloads the current module."
print_line @@reload_opts.usage
return
end
}
reload(stop_existing)
end
# #
# Reloads an exploit module and launches an exploit. # Reloads an exploit module and launches an exploit.
# #
def cmd_rexploit(*args) def cmd_rexploit(*args)
return cmd_rexploit_help if args.include? "-h"
# Stop existing job and reload the module # Stop existing job and reload the module
reload(true) reload(true)
# Delegate to the exploit command # Delegate to the exploit command
cmd_exploit(*args) 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 # Picks a reasonable payload and minimally configures it
# #

View File

@ -24,9 +24,9 @@ class Nop
# Returns the hash of supported commands. # Returns the hash of supported commands.
# #
def commands def commands
{ super.update({
"generate" => "Generates a NOP sled", "generate" => "Generates a NOP sled",
} })
end end
# #

View File

@ -39,9 +39,9 @@ class Payload
# Returns the hash of commands specific to payload modules. # Returns the hash of commands specific to payload modules.
# #
def commands def commands
{ super.update({
"generate" => "Generates a payload", "generate" => "Generates a payload",
} })
end end
# #

View File

@ -24,20 +24,18 @@ class Post
# Returns the hash of commands specific to post modules. # Returns the hash of commands specific to post modules.
# #
def commands def commands
{ super.update({
"run" => "Launches the post exploitation module", "run" => "Launches the post exploitation module",
"rerun" => "Reloads and launches the module", "rerun" => "Reloads and launches the module",
"exploit" => "This is an alias for the run command", "exploit" => "This is an alias for the run command",
"rexploit" => "This is an alias for the rerun command", "rexploit" => "This is an alias for the rerun command",
"reload" => "Reloads the post exploitation module" }).merge( (mod ? mod.post_commands : {}) )
}.merge( (mod ? mod.post_commands : {}) )
end end
# #
# Allow modules to define their own commands # Allow modules to define their own commands
# #
def method_missing(meth, *args) def method_missing(meth, *args)
$stdout.puts("Post#method_missing")
if (mod and mod.respond_to?(meth.to_s)) if (mod and mod.respond_to?(meth.to_s))
# Initialize user interaction # Initialize user interaction
@ -63,22 +61,6 @@ class Post
cmd_rerun(*args) cmd_rerun(*args)
end end
#
# Reloads an auxiliary module
#
def cmd_reload(*args)
begin
omod = self.mod
self.mod = framework.modules.reload_module(mod)
if(not self.mod)
print_error("Failed to reload module: #{framework.modules.failed[omod.file_path]}")
self.mod = omod
end
rescue
log_error("Failed to reload: #{$!}")
end
end
# #
# Reloads an auxiliary module and executes it # Reloads an auxiliary module and executes it
# #
@ -102,12 +84,7 @@ class Post
cmd_run(*args) cmd_run(*args)
end end
# alias cmd_rexploit cmd_rerun
# This is an alias for 'run'
#
def cmd_exploit(*args)
cmd_run(*args)
end
# #
# Executes an auxiliary module # Executes an auxiliary module
@ -175,6 +152,15 @@ class Post
end end
end end
def cmd_run_help
print_line "Usage: run [options]"
print_line
print_line "Launches a post module."
print @@auxiliary_opts.usage
end
alias cmd_exploit_help cmd_run_help
end end
end end end end end end end end

View File

@ -1,4 +1,5 @@
require 'rex/ui' require 'rex/ui'
require 'pp'
module Rex module Rex
module Ui module Ui
@ -79,6 +80,54 @@ module DispatcherShell
shell.update_prompt(prompt) shell.update_prompt(prompt)
end end
#
# Displays the help banner. With no arguments, this is just a list of
# all commands grouped by dispatcher. Otherwise, tries to use a method
# named cmd_#{+cmd+}_help for the first dispatcher that has a command
# named +cmd+.
#
def cmd_help(cmd=nil, *ignored)
if cmd
help_found = false
cmd_found = false
shell.dispatcher_stack.each do |dispatcher|
next unless dispatcher.respond_to?(:commands)
next if (dispatcher.commands.nil?)
next if (dispatcher.commands.length == 0)
if dispatcher.respond_to?("cmd_#{cmd}")
cmd_found = true
break unless dispatcher.respond_to? "cmd_#{cmd}_help"
dispatcher.send("cmd_#{cmd}_help")
help_found = true
break
end
end
print_error("No help for #{cmd}, try -h") if cmd_found and not help_found
print_error("No such command") if not cmd_found
else
print(driver.help_to_s)
end
end
#
# Tab completion for the help command
#
# By default just returns a list of all commands in all dispatchers.
#
def cmd_help_tabs(str, words)
return [] if words.length > 1
tabs = []
shell.dispatcher_stack.each { |dispatcher|
tabs += dispatcher.commands.keys
}
return tabs
end
alias cmd_? cmd_help
# #
# No tab completion items by default # No tab completion items by default
# #