Add `repeat` command to loop msfconsole commands
parent
de0f0a97fb
commit
8fa71ade44
|
@ -106,6 +106,7 @@ class Core
|
|||
"history" => "Show command history",
|
||||
"load" => "Load a framework plugin",
|
||||
"quit" => "Exit the console",
|
||||
"repeat" => "Repeat a list of commands",
|
||||
"route" => "Route traffic through a session",
|
||||
"save" => "Saves the active datastores",
|
||||
"sessions" => "Dump session listings and display information about sessions",
|
||||
|
@ -2083,6 +2084,78 @@ class Core
|
|||
tabs
|
||||
end
|
||||
|
||||
def cmd_repeat_help
|
||||
cmd_repeat '-h'
|
||||
end
|
||||
|
||||
#
|
||||
# Repeats (loops) a given list of commands
|
||||
#
|
||||
def cmd_repeat(*args)
|
||||
looper = method :loop
|
||||
|
||||
opts = OptionParser.new do |opts|
|
||||
opts.banner = 'Usage: repeat [OPTIONS] COMMAND...'
|
||||
opts.separator 'Repeat (loop) a ;-separated list of msfconsole commands indefinitely, or for a'
|
||||
opts.separator 'number of iterations or a certain amount of time.'
|
||||
opts.separator ''
|
||||
|
||||
opts.on '-t SECONDS', '--time SECONDS', 'Number of seconds to repeat COMMAND...', Integer do |n|
|
||||
looper = ->(&block) do
|
||||
# While CLOCK_MONOTONIC is a Linux thing, Ruby emulates it for *BSD, MacOS, and Windows
|
||||
ending_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second) + n
|
||||
while Process.clock_gettime(Process::CLOCK_MONOTONIC, :second) < ending_time
|
||||
block.call
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
opts.on '-n TIMES', '--number TIMES', 'Number of times to repeat COMMAND..', Integer do |n|
|
||||
looper = n.method(:times)
|
||||
end
|
||||
|
||||
opts.on '-h', '--help', 'Help banner.' do
|
||||
return print(opts.help)
|
||||
end
|
||||
|
||||
# Internal use
|
||||
opts.on '--generate-completions str', 'Return possible tab completions for given string.' do |str|
|
||||
return opts.candidate str
|
||||
end
|
||||
end
|
||||
|
||||
cmds = opts.order(args).slice_when do |prev, _|
|
||||
# If the last character of a shellword was a ';' it's probably to
|
||||
# delineate commands and we can remove it
|
||||
prev[-1] == ';' && prev[-1] = ''
|
||||
end.map do |c|
|
||||
Shellwords.shelljoin(c)
|
||||
end
|
||||
|
||||
begin
|
||||
looper.call do
|
||||
cmds.each do |c|
|
||||
driver.run_single c, propogate_errors: true
|
||||
end
|
||||
end
|
||||
rescue ::Exception
|
||||
# Stop looping on exception
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Almost the exact same as grep
|
||||
def cmd_repeat_tabs(str, words)
|
||||
str = '-' if str.empty? # default to use repeat's options
|
||||
tabs = cmd_repeat '--generate-completions', str
|
||||
|
||||
# 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
|
||||
|
||||
#
|
||||
# Provide tab completion for option values
|
||||
#
|
||||
|
|
Loading…
Reference in New Issue