Skip to content

Commit 040ef1e

Browse files
committed
Land rapid7#4950: ls unicode and sorting in meterpreter
2 parents 1dcad7c + 830f328 commit 040ef1e

File tree

7 files changed

+62
-34
lines changed

7 files changed

+62
-34
lines changed

Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ PATH
99
json
1010
metasploit-concern (~> 0.3.0)
1111
metasploit-model (~> 0.29.0)
12-
meterpreter_bins (= 0.0.14)
12+
meterpreter_bins (= 0.0.16)
1313
msgpack
1414
nokogiri
1515
packetfu (= 1.1.9)
@@ -132,7 +132,7 @@ GEM
132132
pg
133133
railties (< 4.0.0)
134134
recog (~> 1.0)
135-
meterpreter_bins (0.0.14)
135+
meterpreter_bins (0.0.16)
136136
method_source (0.8.2)
137137
mime-types (1.25.1)
138138
mini_portile (0.6.1)

lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def Dir.entries(name = getwd)
6161
response = client.send_request(request)
6262

6363
response.each(TLV_TYPE_FILE_NAME) { |file_name|
64-
files << client.unicode_filter_encode( file_name.value )
64+
files << file_name.value
6565
}
6666

6767
return files
@@ -79,6 +79,7 @@ def Dir.entries_with_info(name = getwd)
7979
response = client.send_request(request)
8080

8181
fname = response.get_tlvs(TLV_TYPE_FILE_NAME)
82+
fsname = response.get_tlvs(TLV_TYPE_FILE_SHORT_NAME)
8283
fpath = response.get_tlvs(TLV_TYPE_FILE_PATH)
8384
sbuf = response.get_tlvs(TLV_TYPE_STAT_BUF)
8485

@@ -96,8 +97,9 @@ def Dir.entries_with_info(name = getwd)
9697

9798
files <<
9899
{
99-
'FileName' => client.unicode_filter_encode( file_name.value ),
100-
'FilePath' => client.unicode_filter_encode( fpath[idx].value ),
100+
'FileName' => file_name.value,
101+
'FilePath' => fpath[idx].value,
102+
'FileShortName' => fsname[idx] ? fsname[idx].value : nil,
101103
'StatBuf' => st,
102104
}
103105
}
@@ -145,7 +147,7 @@ def Dir.pwd
145147

146148
response = client.send_request(request)
147149

148-
return client.unicode_filter_encode( response.get_tlv(TLV_TYPE_DIRECTORY_PATH).value )
150+
return response.get_tlv(TLV_TYPE_DIRECTORY_PATH).value
149151
end
150152

151153
#
@@ -195,8 +197,8 @@ def Dir.unlink(path)
195197
def Dir.download(dst, src, recursive = false, force = true, &stat)
196198

197199
self.entries(src).each { |src_sub|
198-
dst_item = dst + ::File::SEPARATOR + client.unicode_filter_encode( src_sub )
199-
src_item = src + client.fs.file.separator + client.unicode_filter_encode( src_sub )
200+
dst_item = dst + ::File::SEPARATOR + src_sub
201+
src_item = src + client.fs.file.separator + src_sub
200202

201203
if (src_sub == '.' or src_sub == '..')
202204
next
@@ -240,8 +242,8 @@ def Dir.download(dst, src, recursive = false, force = true, &stat)
240242
#
241243
def Dir.upload(dst, src, recursive = false, &stat)
242244
::Dir.entries(src).each { |src_sub|
243-
dst_item = dst + client.fs.file.separator + client.unicode_filter_encode( src_sub )
244-
src_item = src + ::File::SEPARATOR + client.unicode_filter_encode( src_sub )
245+
dst_item = dst + client.fs.file.separator + src_sub
246+
src_item = src + ::File::SEPARATOR + src_sub
245247

246248
if (src_sub == '.' or src_sub == '..')
247249
next

lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ def File.search( root=nil, glob="*.*", recurse=true, timeout=-1 )
9191
if( response.result == 0 )
9292
response.each( TLV_TYPE_SEARCH_RESULTS ) do | results |
9393
files << {
94-
'path' => client.unicode_filter_encode( results.get_tlv_value( TLV_TYPE_FILE_PATH ).chomp( '\\' ) ),
95-
'name' => client.unicode_filter_encode( results.get_tlv_value( TLV_TYPE_FILE_NAME ) ),
94+
'path' => results.get_tlv_value( TLV_TYPE_FILE_PATH ).chomp( '\\' ),
95+
'name' => results.get_tlv_value( TLV_TYPE_FILE_NAME ),
9696
'size' => results.get_tlv_value( TLV_TYPE_FILE_SIZE )
9797
}
9898
end
@@ -138,7 +138,7 @@ def File.expand_path(path)
138138

139139
response = client.send_request(request)
140140

141-
return client.unicode_filter_encode( response.get_tlv_value(TLV_TYPE_FILE_PATH) )
141+
return response.get_tlv_value(TLV_TYPE_FILE_PATH)
142142
end
143143

144144

lib/rex/post/meterpreter/extensions/stdapi/tlv.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ module Stdapi
2929
TLV_TYPE_FILE_PATH = TLV_META_TYPE_STRING | 1202
3030
TLV_TYPE_FILE_MODE = TLV_META_TYPE_STRING | 1203
3131
TLV_TYPE_FILE_SIZE = TLV_META_TYPE_UINT | 1204
32+
TLV_TYPE_FILE_SHORT_NAME = TLV_META_TYPE_STRING | 1205
3233

3334
TLV_TYPE_STAT_BUF = TLV_META_TYPE_COMPLEX | 1220
3435

lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -360,21 +360,42 @@ def cmd_lpwd(*args)
360360
#
361361
# Lists files
362362
#
363-
# TODO: make this more useful
364-
#
365363
def cmd_ls(*args)
364+
365+
# Check sort column
366+
sort = args.include?('-S') ? 'Size' : 'Name'
367+
sort = args.include?('-t') ? 'Last modified' : sort
368+
args.delete('-S')
369+
args.delete('-t')
370+
371+
# Check whether to include the short name option
372+
short = args.include?('-x')
373+
args.delete('-x')
374+
375+
# Check sort order
376+
order = args.include?('-r') ? :reverse : :forward
377+
args.delete('-r')
378+
379+
# Check for cries of help
380+
if args.length > 1 || args.any? { |a| a[0] == '-' }
381+
print_line('Usage: ls [dir] [-x] [-S] [-t] [-r]')
382+
print_line(' -x Show short file names')
383+
print_line(' -S Sort by size')
384+
print_line(' -t Sort by time modified')
385+
print_line(' -r Reverse sort order')
386+
return true
387+
end
388+
366389
path = args[0] || client.fs.dir.getwd
390+
391+
columns = [ 'Mode', 'Size', 'Type', 'Last modified', 'Name' ]
392+
columns.insert(4, 'Short Name') if short
393+
367394
tbl = Rex::Ui::Text::Table.new(
368395
'Header' => "Listing: #{path}",
369-
'SortIndex' => 4,
370-
'Columns' =>
371-
[
372-
'Mode',
373-
'Size',
374-
'Type',
375-
'Last modified',
376-
'Name',
377-
])
396+
'SortIndex' => columns.index(sort),
397+
'SortOrder' => order,
398+
'Columns' => columns)
378399

379400
items = 0
380401
stat = client.fs.file.stat(path)
@@ -383,14 +404,16 @@ def cmd_ls(*args)
383404
# No need to sort as Table will do it for us
384405
client.fs.dir.entries_with_info(path).each { |p|
385406

386-
tbl <<
387-
[
407+
row = [
388408
p['StatBuf'] ? p['StatBuf'].prettymode : '',
389409
p['StatBuf'] ? p['StatBuf'].size : '',
390410
p['StatBuf'] ? p['StatBuf'].ftype[0,3] : '',
391411
p['StatBuf'] ? p['StatBuf'].mtime : '',
392412
p['FileName'] || 'unknown'
393413
]
414+
row.insert(4, p['FileShortName'] || '') if short
415+
416+
tbl << row
394417

395418
items += 1
396419
}

lib/rex/ui/text/table.rb

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ def initialize(opts = {})
7474
self.colprops = []
7575

7676
self.sort_index = opts['SortIndex'] || 0
77+
self.sort_order = opts['SortOrder'] || :forward
7778

7879
# Default column properties
7980
self.columns.length.times { |idx|
@@ -187,21 +188,22 @@ def add_row(fields = [])
187188
# If the supplied index is an IPv4 address, handle it differently, but
188189
# avoid actually resolving domain names.
189190
#
190-
def sort_rows(index=sort_index)
191+
def sort_rows(index = sort_index, order = sort_order)
191192
return if index == -1
192193
return unless rows
193194
rows.sort! do |a,b|
194195
if a[index].nil?
195-
-1
196+
cmp = -1
196197
elsif b[index].nil?
197-
1
198+
cmp = 1
198199
elsif Rex::Socket.dotted_ip?(a[index]) and Rex::Socket.dotted_ip?(b[index])
199-
Rex::Socket::addr_atoi(a[index]) <=> Rex::Socket::addr_atoi(b[index])
200+
cmp = Rex::Socket::addr_atoi(a[index]) <=> Rex::Socket::addr_atoi(b[index])
200201
elsif a[index] =~ /^[0-9]+$/ and b[index] =~ /^[0-9]+$/
201-
a[index].to_i <=> b[index].to_i
202+
cmp = a[index].to_i <=> b[index].to_i
202203
else
203-
a[index] <=> b[index] # assumes otherwise comparable.
204+
cmp = a[index] <=> b[index] # assumes otherwise comparable.
204205
end
206+
order == :forward ? cmp : -cmp
205207
end
206208
end
207209

@@ -243,7 +245,7 @@ def [](*col_names)
243245
attr_accessor :columns, :rows, :colprops # :nodoc:
244246
attr_accessor :width, :indent, :cellpad # :nodoc:
245247
attr_accessor :prefix, :postfix # :nodoc:
246-
attr_accessor :sort_index # :nodoc:
248+
attr_accessor :sort_index, :sort_order # :nodoc:
247249

248250
protected
249251

metasploit-framework.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Gem::Specification.new do |spec|
6464
# are needed when there's no database
6565
spec.add_runtime_dependency 'metasploit-model', '~> 0.29.0'
6666
# Needed for Meterpreter on Windows, soon others.
67-
spec.add_runtime_dependency 'meterpreter_bins', '0.0.14'
67+
spec.add_runtime_dependency 'meterpreter_bins', '0.0.16'
6868
# Needed by msfgui and other rpc components
6969
spec.add_runtime_dependency 'msgpack'
7070
# Needed by anemone crawler

0 commit comments

Comments
 (0)