Land #9145, ERB/<ruby> for Meterpreter resource

bug/bundler_fix
William Vu 2017-11-01 13:48:51 -05:00
commit 5de190f092
No known key found for this signature in database
GPG Key ID: 68BD00CE25866743
3 changed files with 122 additions and 30 deletions

View File

@ -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|

View File

@ -1530,49 +1530,73 @@ class Console::CommandDispatcher::Core
end
def cmd_resource_help
print_line('Usage: resource <path1> [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 <ruby></ruby> 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
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
files.each do |filename|
print_status("Reading #{filename}")
if (not ::File.readable?(filename))
print_error("Could not read file #{filename}")
next
end
end
if good_res
client.console.load_resource(good_res)
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
end
end
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

View File

@ -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 =~ /<ruby/
if line =~ /\s+binding=(?:'(\w+)'|"(\w+)")(>|\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.
#