diff --git a/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb b/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb index 3bc246e8db..f51fc5407b 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb @@ -79,6 +79,7 @@ class Dir < Rex::Post::Dir response = client.send_request(request) fname = response.get_tlvs(TLV_TYPE_FILE_NAME) + fsname = response.get_tlvs(TLV_TYPE_FILE_SHORT_NAME) fpath = response.get_tlvs(TLV_TYPE_FILE_PATH) sbuf = response.get_tlvs(TLV_TYPE_STAT_BUF) @@ -98,6 +99,7 @@ class Dir < Rex::Post::Dir { 'FileName' => file_name.value, 'FilePath' => fpath[idx].value, + 'FileShortName' => fsname[idx] ? fsname[idx].value : nil, 'StatBuf' => st, } } diff --git a/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb b/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb index d89f4acc0b..1a30b29529 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb @@ -29,6 +29,7 @@ TLV_TYPE_FILE_NAME = TLV_META_TYPE_STRING | 1201 TLV_TYPE_FILE_PATH = TLV_META_TYPE_STRING | 1202 TLV_TYPE_FILE_MODE = TLV_META_TYPE_STRING | 1203 TLV_TYPE_FILE_SIZE = TLV_META_TYPE_UINT | 1204 +TLV_TYPE_FILE_SHORT_NAME = TLV_META_TYPE_STRING | 1205 TLV_TYPE_STAT_BUF = TLV_META_TYPE_COMPLEX | 1220 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 b131e7cf44..13d30de62d 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 @@ -360,21 +360,42 @@ class Console::CommandDispatcher::Stdapi::Fs # # Lists files # - # TODO: make this more useful - # def cmd_ls(*args) + + # Check sort column + sort = args.include?('-S') ? 'Size' : 'Name' + sort = args.include?('-t') ? 'Last modified' : sort + args.delete('-S') + args.delete('-t') + + # Check whether to include the short name option + short = args.include?('-x') + args.delete('-x') + + # Check sort order + order = args.include?('-r') ? :reverse : :forward + args.delete('-r') + + # Check for cries of help + if args.length > 1 || args.any? { |a| a[0] == '-' } + print_line('Usage: ls [dir] [-x] [-S] [-t] [-r]') + print_line(' -x Show short file names') + print_line(' -S Sort by size') + print_line(' -t Sort by time modified') + print_line(' -r Reverse sort order') + return true + end + path = args[0] || client.fs.dir.getwd + + columns = [ 'Mode', 'Size', 'Type', 'Last modified', 'Name' ] + columns.insert(4, 'Short Name') if short + tbl = Rex::Ui::Text::Table.new( 'Header' => "Listing: #{path}", - 'SortIndex' => 4, - 'Columns' => - [ - 'Mode', - 'Size', - 'Type', - 'Last modified', - 'Name', - ]) + 'SortIndex' => columns.index(sort), + 'SortOrder' => order, + 'Columns' => columns) items = 0 stat = client.fs.file.stat(path) @@ -383,14 +404,16 @@ class Console::CommandDispatcher::Stdapi::Fs # No need to sort as Table will do it for us client.fs.dir.entries_with_info(path).each { |p| - tbl << - [ + row = [ p['StatBuf'] ? p['StatBuf'].prettymode : '', p['StatBuf'] ? p['StatBuf'].size : '', p['StatBuf'] ? p['StatBuf'].ftype[0,3] : '', p['StatBuf'] ? p['StatBuf'].mtime : '', p['FileName'] || 'unknown' ] + row.insert(4, p['FileShortName'] || '') if short + + tbl << row items += 1 } diff --git a/lib/rex/ui/text/table.rb b/lib/rex/ui/text/table.rb index 0cbb315494..7f455cc02e 100644 --- a/lib/rex/ui/text/table.rb +++ b/lib/rex/ui/text/table.rb @@ -74,6 +74,7 @@ class Table self.colprops = [] self.sort_index = opts['SortIndex'] || 0 + self.sort_order = opts['SortOrder'] || :forward # Default column properties self.columns.length.times { |idx| @@ -187,21 +188,22 @@ class Table # If the supplied index is an IPv4 address, handle it differently, but # avoid actually resolving domain names. # - def sort_rows(index=sort_index) + def sort_rows(index = sort_index, order = sort_order) return if index == -1 return unless rows rows.sort! do |a,b| if a[index].nil? - -1 + cmp = -1 elsif b[index].nil? - 1 + cmp = 1 elsif Rex::Socket.dotted_ip?(a[index]) and Rex::Socket.dotted_ip?(b[index]) - Rex::Socket::addr_atoi(a[index]) <=> Rex::Socket::addr_atoi(b[index]) + cmp = Rex::Socket::addr_atoi(a[index]) <=> Rex::Socket::addr_atoi(b[index]) elsif a[index] =~ /^[0-9]+$/ and b[index] =~ /^[0-9]+$/ - a[index].to_i <=> b[index].to_i + cmp = a[index].to_i <=> b[index].to_i else - a[index] <=> b[index] # assumes otherwise comparable. + cmp = a[index] <=> b[index] # assumes otherwise comparable. end + order == :forward ? cmp : -cmp end end @@ -243,7 +245,7 @@ class Table attr_accessor :columns, :rows, :colprops # :nodoc: attr_accessor :width, :indent, :cellpad # :nodoc: attr_accessor :prefix, :postfix # :nodoc: - attr_accessor :sort_index # :nodoc: + attr_accessor :sort_index, :sort_order # :nodoc: protected