diff --git a/Gemfile.lock b/Gemfile.lock index a1e3a74625..3a73e7bec9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,6 +5,7 @@ PATH actionpack (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) bcrypt + filesize jsobfu (~> 0.2.0) json metasm (~> 1.0.2) @@ -98,6 +99,7 @@ GEM factory_girl (~> 4.5.0) railties (>= 3.0.0) ffi (1.9.8) + filesize (0.1.1) fivemat (1.2.1) gherkin (2.12.2) multi_json (~> 1.3) diff --git a/lib/rex/post/meterpreter/extensions/stdapi/fs/mount.rb b/lib/rex/post/meterpreter/extensions/stdapi/fs/mount.rb new file mode 100644 index 0000000000..0a57673f45 --- /dev/null +++ b/lib/rex/post/meterpreter/extensions/stdapi/fs/mount.rb @@ -0,0 +1,57 @@ +# -*- coding: binary -*- + +require 'rex/post/meterpreter/extensions/stdapi/stdapi' + +module Rex +module Post +module Meterpreter +module Extensions +module Stdapi +module Fs + +class Mount + + # Used when matching against windows drive types + DRIVE_TYPES = [ + :unknown, + :no_root, + :removable, + :fixed, + :remote, + :cdrom, + :ramdisk + ] + + def initialize(client) + self.client = client + end + + def show_mount + request = Packet.create_request('stdapi_fs_mount_show') + + response = client.send_request(request) + + results = [] + + response.each(TLV_TYPE_MOUNT) do |d| + results << { + name: d.get_tlv_value(TLV_TYPE_MOUNT_NAME), + type: DRIVE_TYPES[d.get_tlv_value(TLV_TYPE_MOUNT_TYPE)], + user_space: d.get_tlv_value(TLV_TYPE_MOUNT_SPACE_USER), + total_space: d.get_tlv_value(TLV_TYPE_MOUNT_SPACE_TOTAL), + free_space: d.get_tlv_value(TLV_TYPE_MOUNT_SPACE_FREE), + unc: d.get_tlv_value(TLV_TYPE_MOUNT_UNCPATH) + } + end + + results + end + +protected + attr_accessor :client # :nodoc: + +end + +end; end; end; end; end; end + + diff --git a/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb b/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb index 906c278ecd..937d6d0a03 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb @@ -7,6 +7,7 @@ require 'rex/post/meterpreter/extensions/stdapi/tlv' require 'rex/post/meterpreter/extensions/stdapi/fs/dir' require 'rex/post/meterpreter/extensions/stdapi/fs/file' require 'rex/post/meterpreter/extensions/stdapi/fs/file_stat' +require 'rex/post/meterpreter/extensions/stdapi/fs/mount' require 'rex/post/meterpreter/extensions/stdapi/net/resolve' require 'rex/post/meterpreter/extensions/stdapi/net/config' require 'rex/post/meterpreter/extensions/stdapi/net/socket' @@ -50,7 +51,8 @@ class Stdapi < Extension { 'dir' => self.dir, 'file' => self.file, - 'filestat' => self.filestat + 'filestat' => self.filestat, + 'mount' => Fs::Mount.new(client) }) }, { diff --git a/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb b/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb index 048819ea3b..a3a147ae49 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb @@ -32,6 +32,14 @@ TLV_TYPE_FILE_SIZE = TLV_META_TYPE_UINT | 1204 TLV_TYPE_FILE_SHORT_NAME = TLV_META_TYPE_STRING | 1205 TLV_TYPE_FILE_HASH = TLV_META_TYPE_RAW | 1206 +TLV_TYPE_MOUNT = TLV_META_TYPE_GROUP | 1207 +TLV_TYPE_MOUNT_NAME = TLV_META_TYPE_STRING | 1208 +TLV_TYPE_MOUNT_TYPE = TLV_META_TYPE_UINT | 1209 +TLV_TYPE_MOUNT_SPACE_USER = TLV_META_TYPE_QWORD | 1210 +TLV_TYPE_MOUNT_SPACE_TOTAL = TLV_META_TYPE_QWORD | 1211 +TLV_TYPE_MOUNT_SPACE_FREE = TLV_META_TYPE_QWORD | 1212 +TLV_TYPE_MOUNT_UNCPATH = TLV_META_TYPE_STRING | 1213 + TLV_TYPE_STAT_BUF = TLV_META_TYPE_COMPLEX | 1220 TLV_TYPE_SEARCH_RECURSE = TLV_META_TYPE_BOOL | 1230 diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb index 038e35a54d..e142bc6275 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb @@ -1,5 +1,6 @@ # -*- coding: binary -*- require 'tempfile' +require 'filesize' require 'rex/post/meterpreter' module Rex @@ -48,43 +49,45 @@ class Console::CommandDispatcher::Stdapi::Fs # def commands all = { - "cat" => "Read the contents of a file to the screen", - "cd" => "Change directory", - "del" => "Delete the specified file", - "download" => "Download a file or directory", - "edit" => "Edit a file", - "getlwd" => "Print local working directory", - "getwd" => "Print working directory", - "lcd" => "Change local working directory", - "lpwd" => "Print local working directory", - "ls" => "List files", - "mkdir" => "Make directory", - "pwd" => "Print working directory", - "rm" => "Delete the specified file", - "mv" => "Move source to destination", - "rmdir" => "Remove directory", - "search" => "Search for files", - "upload" => "Upload a file or directory", + 'cat' => 'Read the contents of a file to the screen', + 'cd' => 'Change directory', + 'del' => 'Delete the specified file', + 'download' => 'Download a file or directory', + 'edit' => 'Edit a file', + 'getlwd' => 'Print local working directory', + 'getwd' => 'Print working directory', + 'lcd' => 'Change local working directory', + 'lpwd' => 'Print local working directory', + 'ls' => 'List files', + 'mkdir' => 'Make directory', + 'pwd' => 'Print working directory', + 'rm' => 'Delete the specified file', + 'mv' => 'Move source to destination', + 'rmdir' => 'Remove directory', + 'search' => 'Search for files', + 'upload' => 'Upload a file or directory', + 'show_mount' => 'List all mount points/logical drives', } reqs = { - "cat" => [ ], - "cd" => [ "stdapi_fs_chdir" ], - "del" => [ "stdapi_fs_rm" ], - "download" => [ ], - "edit" => [ ], - "getlwd" => [ ], - "getwd" => [ "stdapi_fs_getwd" ], - "lcd" => [ ], - "lpwd" => [ ], - "ls" => [ "stdapi_fs_stat", "stdapi_fs_ls" ], - "mkdir" => [ "stdapi_fs_mkdir" ], - "pwd" => [ "stdapi_fs_getwd" ], - "rmdir" => [ "stdapi_fs_delete_dir" ], - "rm" => [ "stdapi_fs_delete_file" ], - "mv" => [ "stdapi_fs_file_move" ], - "search" => [ "stdapi_fs_search" ], - "upload" => [ ], + 'cat' => [], + 'cd' => ['stdapi_fs_chdir'], + 'del' => ['stdapi_fs_rm'], + 'download' => [], + 'edit' => [], + 'getlwd' => [], + 'getwd' => ['stdapi_fs_getwd'], + 'lcd' => [], + 'lpwd' => [], + 'ls' => ['stdapi_fs_stat', 'stdapi_fs_ls'], + 'mkdir' => ['stdapi_fs_mkdir'], + 'pwd' => ['stdapi_fs_getwd'], + 'rmdir' => ['stdapi_fs_delete_dir'], + 'rm' => ['stdapi_fs_delete_file'], + 'mv' => ['stdapi_fs_file_move'], + 'search' => ['stdapi_fs_search'], + 'upload' => [], + 'show_mount' => ['stdapi_fs_mount_show'], } all.delete_if do |cmd, desc| @@ -166,6 +169,46 @@ class Console::CommandDispatcher::Stdapi::Fs end + # + # Show all the mount points/logical drives (currently geared towards + # the Windows Meterpreter). + # + def cmd_show_mount(*args) + if args.include?('-h') + print_line('Usage: show_mount') + return true + end + + mounts = client.fs.mount.show_mount + + table = Rex::Ui::Text::Table.new( + 'Header' => 'Mounts / Drives', + 'Indent' => 0, + 'SortIndex' => 0, + 'Columns' => [ + 'Name', 'Type', 'Size (Total)', 'Size (Free)', 'Mapped to' + ] + ) + + mounts.each do |d| + ts = ::Filesize.from("#{d[:total_space]} B").pretty.split(' ') + fs = ::Filesize.from("#{d[:free_space]} B").pretty.split(' ') + table << [ + d[:name], + d[:type], + "#{ts[0].rjust(6)} #{ts[1].ljust(3)}", + "#{fs[0].rjust(6)} #{fs[1].ljust(3)}", + d[:unc] + ] + end + + print_line + print_line(table.to_s) + print_line + print_line("Total mounts/drives: #{mounts.length}") + print_line + end + # # Reads the contents of a file and prints them to the screen. # diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index d8377b55f6..9508b84fd5 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -91,4 +91,6 @@ Gem::Specification.new do |spec| spec.add_runtime_dependency 'sqlite3' # required for Time::TZInfo in ActiveSupport spec.add_runtime_dependency 'tzinfo' + # Needed so that disk size output isn't horrible + spec.add_runtime_dependency 'filesize' end