diff --git a/lib/msf/ui/console/command_dispatcher/resource.rb b/lib/msf/ui/console/command_dispatcher/resource.rb index b020bd743f..8f2e6277fd 100644 --- a/lib/msf/ui/console/command_dispatcher/resource.rb +++ b/lib/msf/ui/console/command_dispatcher/resource.rb @@ -59,8 +59,8 @@ module Msf elsif # let's check to see if it's in the scripts/resource dir (like when tab completed) [ - ::Msf::Config.script_directory + ::File::SEPARATOR + "resource", - ::Msf::Config.user_script_directory + ::File::SEPARATOR + "resource" + ::Msf::Config.script_directory + ::File::SEPARATOR + 'resource', + ::Msf::Config.user_script_directory + ::File::SEPARATOR + 'resource' ].each do |dir| res_path = dir + ::File::SEPARATOR + res if ::File.exist?(res_path) @@ -97,7 +97,7 @@ module Msf [ ::Msf::Config.script_directory + File::SEPARATOR + "resource", ::Msf::Config.user_script_directory + File::SEPARATOR + "resource", - "." + '.' ].each do |dir| next if not ::File.exist? dir tabs += ::Dir.new(dir).find_all { |e| diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb index a9cafc2d71..5d854c6fd1 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb @@ -1530,49 +1530,73 @@ class Console::CommandDispatcher::Core end def cmd_resource_help - print_line('Usage: resource [path2 ...]') + print_line "Usage: resource path1 [path2 ...]" print_line - print_line('Run the commands stored in the supplied files.') + print_line "Run the commands stored in the supplied files (- for stdin)." + print_line "Resource files may also contain ERB or Ruby code between tags." print_line end def cmd_resource(*args) if args.empty? + cmd_resource_help return false end - args.each do |glob| - files = ::Dir.glob(::File.expand_path(glob)) - if files.empty? - print_error("No such file #{glob}") - next - end - files.each do |filename| - print_status("Reading #{filename}") - if (not ::File.readable?(filename)) - print_error("Could not read file #{filename}") - next - else - ::File.open(filename, 'r').each_line do |line| - next if line.strip.length < 1 - next if line[0,1] == '#' - begin - print_status("Running #{line}") - client.console.run_single(line) - rescue ::Exception => e - print_error("Error Running Command #{line}: #{e.class} #{e}") - end - + args.each do |res| + good_res = nil + if res == '-' + good_res = res + elsif ::File.exist?(res) + good_res = res + elsif + # let's check to see if it's in the scripts/resource dir (like when tab completed) + [ + ::Msf::Config.script_directory + ::File::SEPARATOR + 'resource' + ::File::SEPARATOR + 'meterpreter', + ::Msf::Config.user_script_directory + ::File::SEPARATOR + 'resource' + ::File::SEPARATOR + 'meterpreter' + ].each do |dir| + res_path = dir + ::File::SEPARATOR + res + if ::File.exist?(res_path) + good_res = res_path + break end end end + if good_res + client.console.load_resource(good_res) + else + print_error("#{res} is not a valid resource file") + next + end end end def cmd_resource_tabs(str, words) - return [] if words.length > 1 - - tab_complete_filenames(str, words) + tabs = [] + #return tabs if words.length > 1 + if ( str and str =~ /^#{Regexp.escape(::File::SEPARATOR)}/ ) + # then you are probably specifying a full path so let's just use normal file completion + return tab_complete_filenames(str,words) + elsif (not words[1] or not words[1].match(/^\//)) + # then let's start tab completion in the scripts/resource directories + begin + [ + ::Msf::Config.script_directory + ::File::SEPARATOR + 'resource' + ::File::SEPARATOR + 'meterpreter', + ::Msf::Config.user_script_directory + ::File::SEPARATOR + 'resource' + ::File::SEPARATOR + 'meterpreter', + '.' + ].each do |dir| + next if not ::File.exist? dir + tabs += ::Dir.new(dir).find_all { |e| + path = dir + ::File::SEPARATOR + e + ::File.file?(path) and ::File.readable?(path) + } + end + rescue Exception + end + else + tabs += tab_complete_filenames(str,words) + end + return tabs end def cmd_enable_unicode_encoding diff --git a/lib/rex/ui/text/dispatcher_shell.rb b/lib/rex/ui/text/dispatcher_shell.rb index 1869156be7..0be205750a 100644 --- a/lib/rex/ui/text/dispatcher_shell.rb +++ b/lib/rex/ui/text/dispatcher_shell.rb @@ -2,6 +2,7 @@ require 'rex/ui' require 'pp' require 'rex/text/table' +require 'erb' module Rex module Ui @@ -368,6 +369,73 @@ module DispatcherShell return items end + # Processes a resource script file for the console. + # + # @param path [String] Path to a resource file to run + # @return [void] + def load_resource(path) + if path == '-' + resource_file = $stdin.read + path = 'stdin' + elsif ::File.exist?(path) + resource_file = ::File.read(path) + else + print_error("Cannot find resource script: #{path}") + return + end + + # Process ERB directives first + print_status "Processing #{path} for ERB directives." + erb = ERB.new(resource_file) + processed_resource = erb.result(binding) + + lines = processed_resource.each_line.to_a + bindings = {} + while lines.length > 0 + + line = lines.shift + break if not line + line.strip! + next if line.length == 0 + next if line =~ /^#/ + + # Pretty soon, this is going to need an XML parser :) + # TODO: case matters for the tag and for binding names + if line =~ /|\s+)/ + bin = ($~[1] || $~[2]) + bindings[bin] = binding unless bindings.has_key? bin + bin = bindings[bin] + else + bin = binding + end + buff = '' + while lines.length > 0 + line = lines.shift + break if not line + break if line =~ /<\/ruby>/ + buff << line + end + if ! buff.empty? + session = client + framework = client.framework + + print_status("resource (#{path})> Ruby Code (#{buff.length} bytes)") + begin + eval(buff, bin) + rescue ::Interrupt + raise $! + rescue ::Exception => e + print_error("resource (#{path})> Ruby Error: #{e.class} #{e} #{e.backtrace}") + end + end + else + print_line("resource (#{path})> #{line}") + run_single(line) + end + end + end + # # Run a single command line. #