Land #4950: ls unicode and sorting in meterpreter

This commit is contained in:
OJ 2015-03-20 06:28:29 +10:00
commit 040ef1e3e9
No known key found for this signature in database
GPG Key ID: D5DC61FB93260597
7 changed files with 62 additions and 34 deletions

View File

@ -9,7 +9,7 @@ PATH
json
metasploit-concern (~> 0.3.0)
metasploit-model (~> 0.29.0)
meterpreter_bins (= 0.0.14)
meterpreter_bins (= 0.0.16)
msgpack
nokogiri
packetfu (= 1.1.9)
@ -132,7 +132,7 @@ GEM
pg
railties (< 4.0.0)
recog (~> 1.0)
meterpreter_bins (0.0.14)
meterpreter_bins (0.0.16)
method_source (0.8.2)
mime-types (1.25.1)
mini_portile (0.6.1)

View File

@ -61,7 +61,7 @@ class Dir < Rex::Post::Dir
response = client.send_request(request)
response.each(TLV_TYPE_FILE_NAME) { |file_name|
files << client.unicode_filter_encode( file_name.value )
files << file_name.value
}
return files
@ -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)
@ -96,8 +97,9 @@ class Dir < Rex::Post::Dir
files <<
{
'FileName' => client.unicode_filter_encode( file_name.value ),
'FilePath' => client.unicode_filter_encode( fpath[idx].value ),
'FileName' => file_name.value,
'FilePath' => fpath[idx].value,
'FileShortName' => fsname[idx] ? fsname[idx].value : nil,
'StatBuf' => st,
}
}
@ -145,7 +147,7 @@ class Dir < Rex::Post::Dir
response = client.send_request(request)
return client.unicode_filter_encode( response.get_tlv(TLV_TYPE_DIRECTORY_PATH).value )
return response.get_tlv(TLV_TYPE_DIRECTORY_PATH).value
end
#
@ -195,8 +197,8 @@ class Dir < Rex::Post::Dir
def Dir.download(dst, src, recursive = false, force = true, &stat)
self.entries(src).each { |src_sub|
dst_item = dst + ::File::SEPARATOR + client.unicode_filter_encode( src_sub )
src_item = src + client.fs.file.separator + client.unicode_filter_encode( src_sub )
dst_item = dst + ::File::SEPARATOR + src_sub
src_item = src + client.fs.file.separator + src_sub
if (src_sub == '.' or src_sub == '..')
next
@ -240,8 +242,8 @@ class Dir < Rex::Post::Dir
#
def Dir.upload(dst, src, recursive = false, &stat)
::Dir.entries(src).each { |src_sub|
dst_item = dst + client.fs.file.separator + client.unicode_filter_encode( src_sub )
src_item = src + ::File::SEPARATOR + client.unicode_filter_encode( src_sub )
dst_item = dst + client.fs.file.separator + src_sub
src_item = src + ::File::SEPARATOR + src_sub
if (src_sub == '.' or src_sub == '..')
next

View File

@ -91,8 +91,8 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO
if( response.result == 0 )
response.each( TLV_TYPE_SEARCH_RESULTS ) do | results |
files << {
'path' => client.unicode_filter_encode( results.get_tlv_value( TLV_TYPE_FILE_PATH ).chomp( '\\' ) ),
'name' => client.unicode_filter_encode( results.get_tlv_value( TLV_TYPE_FILE_NAME ) ),
'path' => results.get_tlv_value( TLV_TYPE_FILE_PATH ).chomp( '\\' ),
'name' => results.get_tlv_value( TLV_TYPE_FILE_NAME ),
'size' => results.get_tlv_value( TLV_TYPE_FILE_SIZE )
}
end
@ -138,7 +138,7 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO
response = client.send_request(request)
return client.unicode_filter_encode( response.get_tlv_value(TLV_TYPE_FILE_PATH) )
return response.get_tlv_value(TLV_TYPE_FILE_PATH)
end

View File

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

View File

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

View File

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

View File

@ -64,7 +64,7 @@ Gem::Specification.new do |spec|
# are needed when there's no database
spec.add_runtime_dependency 'metasploit-model', '~> 0.29.0'
# Needed for Meterpreter on Windows, soon others.
spec.add_runtime_dependency 'meterpreter_bins', '0.0.14'
spec.add_runtime_dependency 'meterpreter_bins', '0.0.16'
# Needed by msfgui and other rpc components
spec.add_runtime_dependency 'msgpack'
# Needed by anemone crawler