meterp fs wrapper action rockin the house
git-svn-id: file:///home/svn/incoming/trunk@2793 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
45b1e69210
commit
9a420ac750
|
@ -16,7 +16,9 @@ class DataStore < Hash
|
||||||
#
|
#
|
||||||
def import_options(options)
|
def import_options(options)
|
||||||
options.each_option { |name, opt|
|
options.each_option { |name, opt|
|
||||||
if (opt.default)
|
# If the option has a default value, import it, but only if the
|
||||||
|
# datastore doesn't already have a value set for it.
|
||||||
|
if (opt.default and self[name] == nil)
|
||||||
self.store(name, opt.default.to_s)
|
self.store(name, opt.default.to_s)
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
@ -130,14 +132,26 @@ class ModuleDataStore < DataStore
|
||||||
# if we can't directly find it
|
# if we can't directly find it
|
||||||
#
|
#
|
||||||
def fetch(key)
|
def fetch(key)
|
||||||
val = super || @_module.framework.datastore[key]
|
val = super
|
||||||
|
|
||||||
|
if (!val and @_module and @_module.framework)
|
||||||
|
val = @_module.framework.datastore[key]
|
||||||
|
end
|
||||||
|
|
||||||
|
return val
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Same as fetch
|
# Same as fetch
|
||||||
#
|
#
|
||||||
def [](key)
|
def [](key)
|
||||||
val = super || @_module.framework.datastore[key]
|
val = super
|
||||||
|
|
||||||
|
if (!val and @_module and @_module.framework)
|
||||||
|
val = @_module.framework.datastore[key]
|
||||||
|
end
|
||||||
|
|
||||||
|
return val
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -129,7 +129,7 @@ class Payload < Msf::Module
|
||||||
# Generates the payload and return the raw buffer
|
# Generates the payload and return the raw buffer
|
||||||
#
|
#
|
||||||
def generate
|
def generate
|
||||||
raw = payload
|
raw = payload.dup
|
||||||
|
|
||||||
# If the payload is generated and there are offsets to substitute,
|
# If the payload is generated and there are offsets to substitute,
|
||||||
# do that now.
|
# do that now.
|
||||||
|
|
|
@ -46,7 +46,7 @@ module Msf::Payload::Stager
|
||||||
# Transmit the associated stage.
|
# Transmit the associated stage.
|
||||||
#
|
#
|
||||||
def handle_connection(conn)
|
def handle_connection(conn)
|
||||||
p = stage_payload
|
p = stage_payload.dup
|
||||||
|
|
||||||
substitute_vars(p, stage_offsets) if (stage_offsets)
|
substitute_vars(p, stage_offsets) if (stage_offsets)
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ module Msf::Payload::Windows
|
||||||
method = datastore[name]
|
method = datastore[name]
|
||||||
method = 'seh' if (!method or @@exit_types.include?(method) == false)
|
method = 'seh' if (!method or @@exit_types.include?(method) == false)
|
||||||
|
|
||||||
raw[offset, 4] = [ @@exit_types[method] ].pack('V')
|
raw[offset, 4] = [ @@exit_types[method] ].pack(pack || 'V')
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
module Rex
|
module Rex
|
||||||
|
Root = File.join(File.dirname(__FILE__), 'rex')
|
||||||
end
|
end
|
||||||
|
|
||||||
# Generic classes
|
# Generic classes
|
||||||
|
|
|
@ -14,6 +14,12 @@ module Rex
|
||||||
module Post
|
module Post
|
||||||
module Meterpreter
|
module Meterpreter
|
||||||
|
|
||||||
|
#
|
||||||
|
# Just to get it in there...
|
||||||
|
#
|
||||||
|
module Extensions
|
||||||
|
end
|
||||||
|
|
||||||
###
|
###
|
||||||
#
|
#
|
||||||
# Client
|
# Client
|
||||||
|
@ -89,11 +95,18 @@ class Client
|
||||||
# Loads the client half of the supplied extension and initializes it as a
|
# Loads the client half of the supplied extension and initializes it as a
|
||||||
# registered extension that can be reached through client.ext.[extension].
|
# registered extension that can be reached through client.ext.[extension].
|
||||||
def add_extension(name)
|
def add_extension(name)
|
||||||
|
old = Rex::Post::Meterpreter::Extensions.constants
|
||||||
require("rex/post/meterpreter/extensions/#{name.downcase}/#{name.downcase}")
|
require("rex/post/meterpreter/extensions/#{name.downcase}/#{name.downcase}")
|
||||||
|
new = Rex::Post::Meterpreter::Extensions.constants
|
||||||
|
|
||||||
|
# No new constants added?
|
||||||
|
if ((diff = new - old).empty?)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
# XXX might want to be safer and catch the exception here?
|
# XXX might want to be safer and catch the exception here?
|
||||||
# maybe not since we are just going to reraise right away...
|
# maybe not since we are just going to reraise right away...
|
||||||
ext = Rex::Post::Meterpreter::Extensions.const_get(name).const_get(name).new(self)
|
ext = Rex::Post::Meterpreter::Extensions.const_get(diff[0]).const_get(diff[0]).new(self)
|
||||||
|
|
||||||
self.ext.aliases[ext.name] = ext
|
self.ext.aliases[ext.name] = ext
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ class Dir < Rex::Post::Dir
|
||||||
end
|
end
|
||||||
|
|
||||||
# Enumerates all of the files/folders in a given directory.
|
# Enumerates all of the files/folders in a given directory.
|
||||||
def Dir.entries(name)
|
def Dir.entries(name = getwd)
|
||||||
request = Packet.create_request('stdapi_fs_ls')
|
request = Packet.create_request('stdapi_fs_ls')
|
||||||
files = []
|
files = []
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ class Dir < Rex::Post::Dir
|
||||||
|
|
||||||
# Downloads the contents of a remote directory a
|
# Downloads the contents of a remote directory a
|
||||||
# local directory, optionally in a recursive fashion.
|
# local directory, optionally in a recursive fashion.
|
||||||
def Dir.download(dst, src, recursive = false)
|
def Dir.download(dst, src, recursive = false, &stat)
|
||||||
self.entries(src).each { |src_sub|
|
self.entries(src).each { |src_sub|
|
||||||
dst_item = dst + ::File::SEPARATOR + src_sub
|
dst_item = dst + ::File::SEPARATOR + src_sub
|
||||||
src_item = src + File::SEPARATOR + src_sub
|
src_item = src + File::SEPARATOR + src_sub
|
||||||
|
@ -146,7 +146,9 @@ class Dir < Rex::Post::Dir
|
||||||
src_stat = client.fs.filestat.new(src_item)
|
src_stat = client.fs.filestat.new(src_item)
|
||||||
|
|
||||||
if (src_stat.file?)
|
if (src_stat.file?)
|
||||||
|
stat.call('downloading', src_item, dst_item) if (stat)
|
||||||
client.fs.file.download(dst_item, src_item)
|
client.fs.file.download(dst_item, src_item)
|
||||||
|
stat.call('downloaded', src_item, dst_item) if (stat)
|
||||||
elsif (src_stat.directory?)
|
elsif (src_stat.directory?)
|
||||||
if (recursive == false)
|
if (recursive == false)
|
||||||
next
|
next
|
||||||
|
@ -157,14 +159,16 @@ class Dir < Rex::Post::Dir
|
||||||
rescue
|
rescue
|
||||||
end
|
end
|
||||||
|
|
||||||
download(dst_item, src_item, recursive)
|
stat.call('mirroring', src_item, dst_item) if (stat)
|
||||||
|
download(dst_item, src_item, recursive, &stat)
|
||||||
|
stat.call('mirrored', src_item, dst_item) if (stat)
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
# Uploads the contents of a local directory to a remote
|
# Uploads the contents of a local directory to a remote
|
||||||
# directory, optionally in a recursive fashion.
|
# directory, optionally in a recursive fashion.
|
||||||
def Dir.upload(dst, src, recursive = false)
|
def Dir.upload(dst, src, recursive = false, &stat)
|
||||||
::Dir.entries(src).each { |src_sub|
|
::Dir.entries(src).each { |src_sub|
|
||||||
dst_item = dst + File::SEPARATOR + src_sub
|
dst_item = dst + File::SEPARATOR + src_sub
|
||||||
src_item = src + ::File::SEPARATOR + src_sub
|
src_item = src + ::File::SEPARATOR + src_sub
|
||||||
|
@ -176,7 +180,9 @@ class Dir < Rex::Post::Dir
|
||||||
src_stat = ::File.stat(src_item)
|
src_stat = ::File.stat(src_item)
|
||||||
|
|
||||||
if (src_stat.file?)
|
if (src_stat.file?)
|
||||||
|
stat.call('uploading', src_item, dst_item) if (stat)
|
||||||
client.fs.file.upload(dst_item, src_item)
|
client.fs.file.upload(dst_item, src_item)
|
||||||
|
stat.call('uploaded', src_item, dst_item) if (stat)
|
||||||
elsif (src_stat.directory?)
|
elsif (src_stat.directory?)
|
||||||
if (recursive == false)
|
if (recursive == false)
|
||||||
next
|
next
|
||||||
|
@ -187,7 +193,9 @@ class Dir < Rex::Post::Dir
|
||||||
rescue
|
rescue
|
||||||
end
|
end
|
||||||
|
|
||||||
upload(dst_item, src_item, recursive)
|
stat.call('mirroring', src_item, dst_item) if (stat)
|
||||||
|
upload(dst_item, src_item, recursive, &stat)
|
||||||
|
stat.call('mirrored', src_item, dst_item) if (stat)
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -52,10 +52,11 @@ Separator = "\\"
|
||||||
|
|
||||||
# Upload one or more files to the remote computer the remote
|
# Upload one or more files to the remote computer the remote
|
||||||
# directory supplied in destination
|
# directory supplied in destination
|
||||||
def File.upload(destination, *src_files)
|
def File.upload(destination, *src_files, &stat)
|
||||||
src_files.each { |src|
|
src_files.each { |src|
|
||||||
dest = destination
|
dest = destination
|
||||||
|
|
||||||
|
stat.call('uploading', src, dest) if (stat)
|
||||||
if (File.basename(destination) != ::File.basename(src))
|
if (File.basename(destination) != ::File.basename(src))
|
||||||
dest += File::SEPARATOR + ::File.basename(src)
|
dest += File::SEPARATOR + ::File.basename(src)
|
||||||
end
|
end
|
||||||
|
@ -67,15 +68,18 @@ Separator = "\\"
|
||||||
|
|
||||||
dest_fd.write(src_buf)
|
dest_fd.write(src_buf)
|
||||||
dest_fd.close
|
dest_fd.close
|
||||||
|
stat.call('uploaded', src, dest) if (stat)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
# Download one or more files from the remote computer to the local
|
# Download one or more files from the remote computer to the local
|
||||||
# directory supplied in destination
|
# directory supplied in destination
|
||||||
def File.download(destination, *src_files)
|
def File.download(destination, *src_files, &stat)
|
||||||
src_files.each { |src|
|
src_files.each { |src|
|
||||||
dest = destination
|
dest = destination
|
||||||
|
|
||||||
|
stat.call('downloading', src, dest) if (stat)
|
||||||
|
|
||||||
if (::File.basename(destination) != File.basename(src))
|
if (::File.basename(destination) != File.basename(src))
|
||||||
dest += ::File::SEPARATOR + File.basename(src)
|
dest += ::File::SEPARATOR + File.basename(src)
|
||||||
end
|
end
|
||||||
|
@ -93,6 +97,8 @@ Separator = "\\"
|
||||||
|
|
||||||
src_fd.close
|
src_fd.close
|
||||||
dst_fd.close
|
dst_fd.close
|
||||||
|
|
||||||
|
stat.call('downloaded', src, dest) if (stat)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -20,13 +20,13 @@ class Console
|
||||||
|
|
||||||
# Dispatchers
|
# Dispatchers
|
||||||
require 'rex/post/meterpreter/ui/console/command_dispatcher'
|
require 'rex/post/meterpreter/ui/console/command_dispatcher'
|
||||||
require 'rex/post/meterpreter/ui/console/core'
|
require 'rex/post/meterpreter/ui/console/command_dispatcher/core'
|
||||||
|
|
||||||
#
|
#
|
||||||
# Initialize the meterpreter console
|
# Initialize the meterpreter console
|
||||||
#
|
#
|
||||||
def initialize(client)
|
def initialize(client)
|
||||||
super("%bmeterpreter%c")
|
super("%umeterpreter%c")
|
||||||
|
|
||||||
# The meterpreter client context
|
# The meterpreter client context
|
||||||
self.client = client
|
self.client = client
|
||||||
|
@ -34,7 +34,7 @@ class Console
|
||||||
# Point the input/output handles elsewhere
|
# Point the input/output handles elsewhere
|
||||||
reset_ui
|
reset_ui
|
||||||
|
|
||||||
enstack_dispatcher(Console::Core)
|
enstack_dispatcher(Console::CommandDispatcher::Core)
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
require 'rex/parser/arguments'
|
require 'rex/post/meterpreter'
|
||||||
|
|
||||||
module Rex
|
module Rex
|
||||||
module Post
|
module Post
|
||||||
|
@ -13,10 +13,16 @@ module Ui
|
||||||
# Core meterpreter client commands.
|
# Core meterpreter client commands.
|
||||||
#
|
#
|
||||||
###
|
###
|
||||||
class Console::Core
|
class Console::CommandDispatcher::Core
|
||||||
|
|
||||||
include Console::CommandDispatcher
|
include Console::CommandDispatcher
|
||||||
|
|
||||||
|
def initialize(shell)
|
||||||
|
super
|
||||||
|
|
||||||
|
self.extensions = []
|
||||||
|
end
|
||||||
|
|
||||||
@@use_opts = Rex::Parser::Arguments.new(
|
@@use_opts = Rex::Parser::Arguments.new(
|
||||||
"-m" => [ true, "The name of the module or modules to load (Ex: stdapi)." ],
|
"-m" => [ true, "The name of the module or modules to load (Ex: stdapi)." ],
|
||||||
"-h" => [ false, "Help banner." ])
|
"-h" => [ false, "Help banner." ])
|
||||||
|
@ -26,12 +32,21 @@ class Console::Core
|
||||||
#
|
#
|
||||||
def commands
|
def commands
|
||||||
{
|
{
|
||||||
|
"?" => "Help menu",
|
||||||
"exit" => "Terminate the meterpreter session",
|
"exit" => "Terminate the meterpreter session",
|
||||||
|
"help" => "Help menu",
|
||||||
"use" => "Load a one or more meterpreter extensions",
|
"use" => "Load a one or more meterpreter extensions",
|
||||||
"quit" => "Terminate the meterpreter session",
|
"quit" => "Terminate the meterpreter session",
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Core baby.
|
||||||
|
#
|
||||||
|
def name
|
||||||
|
"Core"
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Terminates the meterpreter session
|
# Terminates the meterpreter session
|
||||||
#
|
#
|
||||||
|
@ -41,6 +56,12 @@ class Console::Core
|
||||||
|
|
||||||
alias cmd_quit cmd_exit
|
alias cmd_quit cmd_exit
|
||||||
|
|
||||||
|
#
|
||||||
|
# Displays the help menu
|
||||||
|
#
|
||||||
|
def cmd_help(*args)
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Loads one or more meterpreter extensions
|
# Loads one or more meterpreter extensions
|
||||||
#
|
#
|
||||||
|
@ -66,10 +87,20 @@ class Console::Core
|
||||||
|
|
||||||
# Load each of the modules
|
# Load each of the modules
|
||||||
modules.each { |m|
|
modules.each { |m|
|
||||||
|
md = m.downcase
|
||||||
|
|
||||||
|
if (extensions.include?(md))
|
||||||
|
print_error("The '#{m}' extension has already been loaded.")
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
print("Loading extension #{m}...")
|
print("Loading extension #{m}...")
|
||||||
|
|
||||||
begin
|
begin
|
||||||
client.core.use(m)
|
# Use the remote side, then load the client-side
|
||||||
|
if (client.core.use(md) == true)
|
||||||
|
add_extension_client(md)
|
||||||
|
end
|
||||||
rescue
|
rescue
|
||||||
log_error("failure: #{$!}")
|
log_error("failure: #{$!}")
|
||||||
next
|
next
|
||||||
|
@ -81,6 +112,39 @@ class Console::Core
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
attr_accessor :extensions
|
||||||
|
|
||||||
|
CommDispatcher = Console::CommandDispatcher
|
||||||
|
|
||||||
|
#
|
||||||
|
# Loads the client extension specified in mod
|
||||||
|
#
|
||||||
|
def add_extension_client(mod)
|
||||||
|
clirb = File.join(Rex::Root, "post/meterpreter/ui/console/command_dispatcher/#{mod}.rb")
|
||||||
|
|
||||||
|
old = CommDispatcher.constants
|
||||||
|
|
||||||
|
require(clirb)
|
||||||
|
|
||||||
|
new = CommDispatcher.constants
|
||||||
|
diff = new - old
|
||||||
|
|
||||||
|
if (diff.empty? == true)
|
||||||
|
print_error("Failed to load client portion of #{mod}.")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
# Create the dispatcher
|
||||||
|
klass = CommDispatcher.const_get(diff[0])
|
||||||
|
|
||||||
|
# Enstack the dispatcher
|
||||||
|
self.shell.enstack_dispatcher(klass)
|
||||||
|
|
||||||
|
# Insert the module into the list of extensions
|
||||||
|
self.extensions << mod
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
|
@ -0,0 +1,50 @@
|
||||||
|
require 'rex/post/meterpreter'
|
||||||
|
|
||||||
|
module Rex
|
||||||
|
module Post
|
||||||
|
module Meterpreter
|
||||||
|
module Ui
|
||||||
|
|
||||||
|
###
|
||||||
|
#
|
||||||
|
# Stdapi
|
||||||
|
# ------
|
||||||
|
#
|
||||||
|
# Standard API extension.
|
||||||
|
#
|
||||||
|
###
|
||||||
|
class Console::CommandDispatcher::Stdapi
|
||||||
|
|
||||||
|
Klass = Console::CommandDispatcher::Stdapi
|
||||||
|
|
||||||
|
include Console::CommandDispatcher
|
||||||
|
|
||||||
|
require 'rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs'
|
||||||
|
|
||||||
|
def initialize(shell)
|
||||||
|
super
|
||||||
|
|
||||||
|
shell.enstack_dispatcher(Klass::Fs)
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# List of supported commands
|
||||||
|
#
|
||||||
|
def commands
|
||||||
|
{
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Name for this dispatcher
|
||||||
|
#
|
||||||
|
def name
|
||||||
|
"Standard extension"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,206 @@
|
||||||
|
require 'rex/post/meterpreter'
|
||||||
|
|
||||||
|
module Rex
|
||||||
|
module Post
|
||||||
|
module Meterpreter
|
||||||
|
module Ui
|
||||||
|
|
||||||
|
###
|
||||||
|
#
|
||||||
|
# Stdapi
|
||||||
|
# ------
|
||||||
|
#
|
||||||
|
# Standard API extension.
|
||||||
|
#
|
||||||
|
###
|
||||||
|
class Console::CommandDispatcher::Stdapi::Fs
|
||||||
|
|
||||||
|
Klass = Console::CommandDispatcher::Stdapi::Fs
|
||||||
|
|
||||||
|
include Console::CommandDispatcher
|
||||||
|
|
||||||
|
#
|
||||||
|
# Options for the download command
|
||||||
|
#
|
||||||
|
@@download_opts = Rex::Parser::Arguments.new(
|
||||||
|
"-r" => [ false, "Download recursively." ])
|
||||||
|
|
||||||
|
#
|
||||||
|
# List of supported commands
|
||||||
|
#
|
||||||
|
def commands
|
||||||
|
{
|
||||||
|
"cd" => "Change directory",
|
||||||
|
"download" => "Download a file or directory",
|
||||||
|
"getwd" => "Print working directory",
|
||||||
|
"ls" => "List files",
|
||||||
|
"mkdir" => "Make directory",
|
||||||
|
"pwd" => "Print working directory",
|
||||||
|
"rmdir" => "Remove directory",
|
||||||
|
"upload" => "Upload a file or directory",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Name for this dispatcher
|
||||||
|
#
|
||||||
|
def name
|
||||||
|
"Stdapi: File system"
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Change the working directory
|
||||||
|
#
|
||||||
|
def cmd_cd(*args)
|
||||||
|
if (args.length == 0)
|
||||||
|
print_line("Usage: cd directory")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
client.fs.dir.chdir(args[0])
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Downloads a file or directory from the remote machine to the local
|
||||||
|
# machine.
|
||||||
|
#
|
||||||
|
def cmd_download(*args)
|
||||||
|
if (args.length == 0)
|
||||||
|
print(
|
||||||
|
"Usage: download [options] src1 src2 src3 ... destination\n\n" +
|
||||||
|
"Downloads remote files and directories to the local machine.\n" +
|
||||||
|
@@download_opts.usage)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
recursive = false
|
||||||
|
src_items = []
|
||||||
|
last = nil
|
||||||
|
dest = nil
|
||||||
|
|
||||||
|
@@download_opts.parse(args) { |opt, idx, val|
|
||||||
|
case opt
|
||||||
|
when "-r"
|
||||||
|
recursive = true
|
||||||
|
when nil
|
||||||
|
if (last)
|
||||||
|
src_items << last
|
||||||
|
end
|
||||||
|
|
||||||
|
last = val
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
dest = last
|
||||||
|
|
||||||
|
# If there is no destination, assume it's the same as the source.
|
||||||
|
if (!dest)
|
||||||
|
dest = src_items[0]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Go through each source item and download them
|
||||||
|
src_items.each { |src|
|
||||||
|
stat = client.fs.file.stat(src)
|
||||||
|
|
||||||
|
if (stat.directory?)
|
||||||
|
client.fs.dir.download(dest, src, recursive) { |step, src, dst|
|
||||||
|
print_status("#{step.ljust(11)}: #{src} -> #{dst}")
|
||||||
|
}
|
||||||
|
elsif (stat.file?)
|
||||||
|
client.fs.file.download(dest, src) { |step, src, dst|
|
||||||
|
print_status("#{step.ljust(11)}: #{src} -> #{dst}")
|
||||||
|
}
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Lists files
|
||||||
|
#
|
||||||
|
# TODO: make this more useful
|
||||||
|
#
|
||||||
|
def cmd_ls(*args)
|
||||||
|
path = args[0] || client.fs.dir.getwd
|
||||||
|
tbl = Rex::Ui::Text::Table.new(
|
||||||
|
'Header' => "Listing: #{path}",
|
||||||
|
'Columns' =>
|
||||||
|
[
|
||||||
|
'Name',
|
||||||
|
'Type',
|
||||||
|
'Size',
|
||||||
|
])
|
||||||
|
|
||||||
|
items = 0
|
||||||
|
|
||||||
|
# Enumerate each item...
|
||||||
|
client.fs.dir.entries(path).sort.each { |p|
|
||||||
|
s = client.fs.file.stat(p)
|
||||||
|
|
||||||
|
tbl << [ p, s.ftype, s.size ]
|
||||||
|
|
||||||
|
items += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (items > 0)
|
||||||
|
print(tbl.to_s)
|
||||||
|
else
|
||||||
|
print_line("No entries exist in #{path}")
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Make one or more directory
|
||||||
|
#
|
||||||
|
def cmd_mkdir(*args)
|
||||||
|
if (args.length == 0)
|
||||||
|
print_line("Usage: mkdir dir1 dir2 dir3 ...")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
args.each { |dir|
|
||||||
|
print_line("Creating directory: #{dir}")
|
||||||
|
|
||||||
|
client.fs.dir.mkdir(dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Display the working directory
|
||||||
|
#
|
||||||
|
def cmd_pwd(*args)
|
||||||
|
print_line(client.fs.dir.getwd)
|
||||||
|
end
|
||||||
|
|
||||||
|
alias cmd_getwd cmd_pwd
|
||||||
|
|
||||||
|
#
|
||||||
|
# Removes one or more directory if it's empty
|
||||||
|
#
|
||||||
|
def cmd_rmdir(*args)
|
||||||
|
if (args.length == 0)
|
||||||
|
print_line("Usage: rmdir dir1 dir2 dir3 ...")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
args.each { |dir|
|
||||||
|
print_line("Removing directory: #{dir}")
|
||||||
|
client.fs.dir.rmdir(dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -115,12 +115,15 @@ module DispatcherShell
|
||||||
dispatcher_stack.each { |dispatcher|
|
dispatcher_stack.each { |dispatcher|
|
||||||
begin
|
begin
|
||||||
if (dispatcher.respond_to?('cmd_' + method))
|
if (dispatcher.respond_to?('cmd_' + method))
|
||||||
|
found = true
|
||||||
eval("
|
eval("
|
||||||
dispatcher.#{'cmd_' + method}(*arguments)
|
dispatcher.#{'cmd_' + method}(*arguments)
|
||||||
found = true")
|
")
|
||||||
end
|
end
|
||||||
rescue
|
rescue
|
||||||
output.print_error("Error while running command #{method}: #{$!}")
|
output.print_error(
|
||||||
|
"Error while running command #{method}: #{$!}" +
|
||||||
|
"\n\nCall stack:\n#{$@.join("\n")}")
|
||||||
end
|
end
|
||||||
|
|
||||||
# If the dispatcher stack changed as a result of this command,
|
# If the dispatcher stack changed as a result of this command,
|
||||||
|
|
Loading…
Reference in New Issue