Merge branch 'master' of https://github.com/rapid7/metasploit-framework
commit
7c90d0a125
|
@ -65,6 +65,17 @@ class Core
|
|||
"-w" => [ true, "Specify connect timeout." ],
|
||||
"-z" => [ false, "Just try to connect, then return." ])
|
||||
|
||||
@@grep_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner." ],
|
||||
"-i" => [ false, "Ignore case." ],
|
||||
"-m" => [ true, "Stop after arg matches." ],
|
||||
"-v" => [ false, "Invert match." ],
|
||||
"-A" => [ true, "Show arg lines of output After a match." ],
|
||||
"-B" => [ true, "Show arg lines of output Before a match." ],
|
||||
"-s" => [ true, "Skip arg lines of output before attempting match."],
|
||||
"-k" => [ true, "Keep (include) arg lines at start of output." ],
|
||||
"-c" => [ false, "Only print a count of matching lines." ])
|
||||
|
||||
@@search_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner." ])
|
||||
|
||||
|
@ -86,6 +97,7 @@ class Core
|
|||
"color" => "Toggle color",
|
||||
"exit" => "Exit the console",
|
||||
"go_pro" => "Launch Metasploit web GUI",
|
||||
"grep" => "Grep the output of another command",
|
||||
"help" => "Help menu",
|
||||
"info" => "Displays information about one or more module",
|
||||
"irb" => "Drop into irb scripting mode",
|
||||
|
@ -236,6 +248,10 @@ class Core
|
|||
#
|
||||
# Tab completion for the resource command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_resource_tabs(str, words)
|
||||
tabs = []
|
||||
#return tabs if words.length > 1
|
||||
|
@ -314,8 +330,8 @@ class Core
|
|||
driver.destack_dispatcher
|
||||
|
||||
# Restore the prompt
|
||||
prompt = framework.datastore['Prompt'] || "%undmsf%clr "
|
||||
prompt_char = framework.datastore['PromptChar'] || ">"
|
||||
prompt = framework.datastore['Prompt'] || Msf::Ui::Console::Driver::DefaultPrompt
|
||||
prompt_char = framework.datastore['PromptChar'] || Msf::Ui::Console::Driver::DefaultPromptChar
|
||||
driver.update_prompt("#{prompt}", prompt_char, true)
|
||||
end
|
||||
end
|
||||
|
@ -671,6 +687,10 @@ class Core
|
|||
#
|
||||
# Tab completion for the info command (same as use)
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_info_tabs(str, words)
|
||||
cmd_use_tabs(str, words)
|
||||
end
|
||||
|
@ -787,6 +807,10 @@ class Core
|
|||
#
|
||||
# Tab completion for the jobs command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_jobs_tabs(str, words)
|
||||
if words.length == 1
|
||||
return @@jobs_opts.fmt.keys
|
||||
|
@ -810,6 +834,13 @@ class Core
|
|||
cmd_jobs("-k", *args)
|
||||
end
|
||||
|
||||
#
|
||||
# Tab completion for the kill command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_kill_tabs(str, words)
|
||||
return [] if words.length > 1
|
||||
framework.jobs.keys
|
||||
|
@ -928,6 +959,10 @@ class Core
|
|||
#
|
||||
# Tab completion for the threads command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_threads_tabs(str, words)
|
||||
if words.length == 1
|
||||
return @@threads_opts.fmt.keys
|
||||
|
@ -1004,6 +1039,10 @@ class Core
|
|||
#
|
||||
# Tab completion for the load command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_load_tabs(str, words)
|
||||
tabs = []
|
||||
|
||||
|
@ -1163,6 +1202,10 @@ class Core
|
|||
#
|
||||
# Tab completion for the route command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_route_tabs(str, words)
|
||||
if words.length == 1
|
||||
return %w{add remove get flush print}
|
||||
|
@ -1285,6 +1328,13 @@ class Core
|
|||
print(added)
|
||||
end
|
||||
|
||||
#
|
||||
# Tab completion for the loadpath command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_loadpath_tabs(str, words)
|
||||
return [] if words.length > 1
|
||||
|
||||
|
@ -1403,6 +1453,13 @@ class Core
|
|||
print_line(tbl.to_s)
|
||||
end
|
||||
|
||||
#
|
||||
# Tab completion for the search command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_search_tabs(str, words)
|
||||
if words.length == 1
|
||||
return @@search_opts.fmt.keys
|
||||
|
@ -1718,6 +1775,10 @@ class Core
|
|||
#
|
||||
# Tab completion for the sessions command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_sessions_tabs(str, words)
|
||||
if words.length == 1
|
||||
return @@sessions_opts.fmt.keys
|
||||
|
@ -1839,6 +1900,10 @@ class Core
|
|||
#
|
||||
# Tab completion for the set command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_set_tabs(str, words)
|
||||
|
||||
# A value has already been specified
|
||||
|
@ -1920,6 +1985,10 @@ class Core
|
|||
#
|
||||
# Tab completion for the setg command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_setg_tabs(str, words)
|
||||
cmd_set_tabs(str, words)
|
||||
end
|
||||
|
@ -2016,6 +2085,10 @@ class Core
|
|||
#
|
||||
# Tab completion for the show command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_show_tabs(str, words)
|
||||
return [] if words.length > 1
|
||||
|
||||
|
@ -2061,6 +2134,10 @@ class Core
|
|||
#
|
||||
# Tab completion for the unload command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_unload_tabs(str, words)
|
||||
return [] if words.length > 1
|
||||
|
||||
|
@ -2134,6 +2211,10 @@ class Core
|
|||
#
|
||||
# Tab completion for the unset command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_unset_tabs(str, words)
|
||||
datastore = active_module ? active_module.datastore : self.framework.datastore
|
||||
datastore.keys
|
||||
|
@ -2158,6 +2239,10 @@ class Core
|
|||
#
|
||||
# Tab completion for the unsetg command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_unsetg_tabs(str, words)
|
||||
self.framework.datastore.keys
|
||||
end
|
||||
|
@ -2239,8 +2324,8 @@ class Core
|
|||
mod.init_ui(driver.input, driver.output)
|
||||
|
||||
# Update the command prompt
|
||||
prompt = framework.datastore['Prompt'] || "%undmsf%clr "
|
||||
prompt_char = framework.datastore['PromptChar'] || ">"
|
||||
prompt = framework.datastore['Prompt'] || Msf::Ui::Console::Driver::DefaultPrompt
|
||||
prompt_char = framework.datastore['PromptChar'] || Msf::Ui::Console::Driver::DefaultPromptChar
|
||||
driver.update_prompt("#{prompt} #{mod.type}(%bld%red#{mod.shortname}%clr) ", prompt_char, true)
|
||||
end
|
||||
|
||||
|
@ -2286,6 +2371,13 @@ class Core
|
|||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Tab completion for the pushm command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_pushm_tabs(str, words)
|
||||
tab_complete_module(str, words)
|
||||
end
|
||||
|
@ -2339,6 +2431,10 @@ class Core
|
|||
#
|
||||
# Tab completion for the use command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completd
|
||||
|
||||
def cmd_use_tabs(str, words)
|
||||
return [] if words.length > 1
|
||||
|
||||
|
@ -2361,6 +2457,153 @@ class Core
|
|||
return true
|
||||
end
|
||||
|
||||
def cmd_grep_help
|
||||
print_line "Usage: grep [options] pattern cmd"
|
||||
print_line
|
||||
print_line "Grep the results of a console command (similar to Linux grep command)"
|
||||
print(@@grep_opts.usage())
|
||||
end
|
||||
|
||||
#
|
||||
# Greps the output of another console command, usage is similar the shell grep command
|
||||
# grep [options] pattern other_cmd [other command's args], similar to the shell's grep [options] pattern file
|
||||
# however it also includes -k to keep lines and -s to skip lines. grep -k 5 is useful for keeping table headers
|
||||
#
|
||||
# @param args [Array<String>] Args to the grep command minimally including a pattern & a command to search
|
||||
# @return [String,nil] Results matching the regular expression given
|
||||
|
||||
def cmd_grep(*args)
|
||||
return cmd_grep_help if args.length < 2
|
||||
match_mods = {:insensitive => false}
|
||||
output_mods = {:count => false, :invert => false}
|
||||
@@grep_opts.parse(args.dup) do |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
return cmd_grep_help
|
||||
when "-m"
|
||||
# limit to arg matches
|
||||
match_mods[:max] = val.to_i
|
||||
# delete opt and val from args list
|
||||
args.shift(2)
|
||||
when "-A"
|
||||
# also return arg lines after a match
|
||||
output_mods[:after] = val.to_i
|
||||
# delete opt and val from args list
|
||||
args.shift(2)
|
||||
when "-B"
|
||||
# also return arg lines before a match
|
||||
output_mods[:before] = val.to_i
|
||||
# delete opt and val from args list
|
||||
args.shift(2)
|
||||
when "-v"
|
||||
# invert match
|
||||
match_mods[:invert] = true
|
||||
# delete opt from args list
|
||||
args.shift
|
||||
when "-i"
|
||||
# case insensitive
|
||||
match_mods[:insensitive] = true
|
||||
args.shift
|
||||
when "-c"
|
||||
# just count matches
|
||||
output_mods[:count] = true
|
||||
args.shift
|
||||
when "-k"
|
||||
# keep arg number of lines at the top of the output, useful for commands with table headers in output
|
||||
output_mods[:keep] = val.to_i
|
||||
args.shift(2)
|
||||
when "-s"
|
||||
# skip arg number of lines at the top of the output, useful for avoiding undesirable matches
|
||||
output_mods[:skip] = val.to_i
|
||||
args.shift(2)
|
||||
end
|
||||
end
|
||||
# after deleting parsed options, the only args left should be the pattern, the cmd to run, and cmd args
|
||||
pattern = args.shift
|
||||
if match_mods[:insensitive]
|
||||
rx = Regexp.new(pattern, true)
|
||||
else
|
||||
rx = Regexp.new(pattern)
|
||||
end
|
||||
cmd = args.join(" ")
|
||||
|
||||
# get a ref to the current console driver
|
||||
orig_driver = self.driver
|
||||
# redirect output after saving the old ones and getting a new output buffer to use for redirect
|
||||
orig_driver_output = orig_driver.output
|
||||
orig_driver_input = orig_driver.input
|
||||
# we use a rex buffer but add a write method to the instance, which is required in order to be valid $stdout
|
||||
temp_output = Rex::Ui::Text::Output::Buffer.new
|
||||
def temp_output.write(msg = '')
|
||||
self.print_raw(msg)
|
||||
end
|
||||
orig_driver.init_ui(orig_driver_input,temp_output)
|
||||
# run the desired command to be grepped
|
||||
orig_driver.run_single(cmd)
|
||||
# restore original output
|
||||
orig_driver.init_ui(orig_driver_input,orig_driver_output)
|
||||
# restore the prompt so we don't get "msf > >".
|
||||
prompt = framework.datastore['Prompt'] || Msf::Ui::Console::Driver::DefaultPrompt
|
||||
prompt_char = framework.datastore['PromptChar'] || Msf::Ui::Console::Driver::DefaultPromptChar
|
||||
mod = active_module
|
||||
if mod # if there is an active module, give them the fanciness they have come to expect
|
||||
driver.update_prompt("#{prompt} #{mod.type}(%bld%red#{mod.shortname}%clr) ", prompt_char, true)
|
||||
else
|
||||
driver.update_prompt("#{prompt}", prompt_char, true)
|
||||
end
|
||||
|
||||
# dump the command's output so we can grep it
|
||||
cmd_output = temp_output.dump_buffer
|
||||
|
||||
# Bail if the command failed
|
||||
if cmd_output =~ /Unknown command:/
|
||||
print_error("Unknown command: #{args[0]}.")
|
||||
return false
|
||||
end
|
||||
# put lines into an array so we can access them more easily and split('\n') doesn't work on the output obj.
|
||||
all_lines = cmd_output.lines.select {|line| line}
|
||||
# control matching based on remaining match_mods (:insensitive was already handled)
|
||||
if match_mods[:invert]
|
||||
statement = 'not line =~ rx'
|
||||
else
|
||||
statement = 'line =~ rx'
|
||||
end
|
||||
|
||||
our_lines = []
|
||||
count = 0
|
||||
all_lines.each_with_index do |line, line_num|
|
||||
next if (output_mods[:skip] and line_num < output_mods[:skip])
|
||||
our_lines << line if (output_mods[:keep] and line_num < output_mods[:keep])
|
||||
# we don't wan't to keep processing if we have a :max and we've reached it already (not counting skips/keeps)
|
||||
break if match_mods[:max] and count >= match_mods[:max]
|
||||
if eval statement
|
||||
count += 1
|
||||
# we might get a -A/after and a -B/before at the same time
|
||||
our_lines += retrieve_grep_lines(all_lines,line_num,output_mods[:before], output_mods[:after])
|
||||
end
|
||||
end
|
||||
|
||||
# now control output based on remaining output_mods such as :count
|
||||
return print_status(count.to_s) if output_mods[:count]
|
||||
our_lines.each {|line| print line}
|
||||
end
|
||||
|
||||
#
|
||||
# Tab completion for the grep command
|
||||
#
|
||||
# @param str [String] the string currently being typed before tab was hit
|
||||
# @param words [Array<String>] the previously completed words on the command line. words is always
|
||||
# at least 1 when tab completion has reached this stage since the command itself has been completed
|
||||
|
||||
def cmd_grep_tabs(str, words)
|
||||
tabs = @@grep_opts.fmt.keys || [] # default to use grep's options
|
||||
# if not an opt, use normal tab comp.
|
||||
# @todo uncomment out next line when tab_completion normalization is complete RM7649 or
|
||||
# replace with new code that permits "nested" tab completion
|
||||
# tabs = driver.get_all_commands if (str and str =~ /\w/)
|
||||
tabs
|
||||
end
|
||||
|
||||
#
|
||||
# Tab complete module names
|
||||
#
|
||||
|
@ -2811,7 +3054,7 @@ class Core
|
|||
[ 'MinimumRank', framework.datastore['MinimumRank'] || '', 'The minimum rank of exploits that will run without explicit confirmation' ],
|
||||
[ 'SessionLogging', framework.datastore['SessionLogging'] || '', 'Log all input and output for sessions' ],
|
||||
[ 'TimestampOutput', framework.datastore['TimestampOutput'] || '', 'Prefix all console output with a timestamp' ],
|
||||
[ 'Prompt', framework.datastore['Prompt'] || '', 'The prompt string, defaults to "%undmsf%clr"' ],
|
||||
[ 'Prompt', framework.datastore['Prompt'] || '', 'The prompt string, defaults to "#{Msf::Ui::Console::Driver::DefaultPrompt}"' ],
|
||||
[ 'PromptChar', framework.datastore['PromptChar'] || '', 'The prompt character, defaults to ">"' ],
|
||||
[ 'PromptTimeFormat', framework.datastore['PromptTimeFormat'] || '', 'A format for timestamp escapes in the prompt, see ruby\'s strftime docs' ],
|
||||
].each { |r| tbl << r }
|
||||
|
@ -2941,6 +3184,24 @@ class Core
|
|||
'Columns' => [ 'Name', 'Disclosure Date', 'Rank', 'Description' ]
|
||||
)
|
||||
end
|
||||
#
|
||||
# Returns an array of lines at the provided line number plus any before and/or after lines requested
|
||||
# from all_lines by supplying the +before+ and/or +after+ parameters which are always positive
|
||||
#
|
||||
# @param all_lines [Array<String>] An array of all lines being considered for matching
|
||||
# @param line_num [Integer] The line number in all_lines which has satisifed the match
|
||||
# @param after [Integer] The number of lines after the match line to include (should always be positive)
|
||||
# @param before [Integer] The number of lines before the match line to include (should always be positive)
|
||||
# @return [Array<String>] Array of lines including the line at line_num and any +before+ and/or +after+
|
||||
|
||||
def retrieve_grep_lines(all_lines,line_num, before = nil, after = nil)
|
||||
after = after.to_i.abs
|
||||
before = before.to_i.abs
|
||||
start = line_num - before
|
||||
start = 0 if start < 0
|
||||
finish = line_num + after
|
||||
return all_lines.slice(start..finish)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -1527,7 +1527,7 @@ class Db
|
|||
print_error("The database is not connected")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
print_status("Purging and rebuilding the module cache in the background...")
|
||||
framework.threads.spawn("ModuleCacheRebuild", true) do
|
||||
framework.db.purge_all_module_details
|
||||
|
|
|
@ -333,13 +333,13 @@ module DispatcherShell
|
|||
str = Regexp.escape(str)
|
||||
end
|
||||
|
||||
# XXX - This still doesn't fix some Regexp warnings:
|
||||
# @todo - This still doesn't fix some Regexp warnings:
|
||||
# ./lib/rex/ui/text/dispatcher_shell.rb:171: warning: regexp has `]' without escape
|
||||
|
||||
# Match based on the partial word
|
||||
items.find_all { |e|
|
||||
e =~ /^#{str}/
|
||||
# Prepend the rest of the command (or it gets replaced!)
|
||||
# Prepend the rest of the command (or it all gets replaced!)
|
||||
}.map { |e|
|
||||
tab_words.dup.push(e).join(' ')
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue