librex 0.0.28 → 0.0.29
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +1 -1
- data/Rakefile +1 -1
- data/lib/rex/parser/arguments.rb +12 -2
- data/lib/rex/parser/nexpose_xml.rb +2 -1
- data/lib/rex/parser/nmap_xml.rb +12 -4
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +9 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun.rb.ts.rb +5 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb +31 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/tlv.rb +2 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +32 -0
- data/lib/rex/post/meterpreter/ui/console.rb +2 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher.rb +24 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +97 -48
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +4 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +1 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +1 -26
- data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +3 -0
- data/lib/rex/proto/proxy/socks4a.rb +5 -5
- data/lib/rex/ui/interactive.rb +5 -0
- metadata +3 -3
data/README.markdown
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
A non-official re-packaging of the Rex library as a gem for easy of usage of the Metasploit REX framework in a non Metasploit application. I received permission from HDM to create this package.
|
4
4
|
|
5
5
|
Currently based on:
|
6
|
-
SVN Revision:
|
6
|
+
SVN Revision: 12371
|
7
7
|
|
8
8
|
# Credits
|
9
9
|
The Metasploit development team <http://www.metasploit.com>
|
data/Rakefile
CHANGED
@@ -86,7 +86,7 @@ task :update do
|
|
86
86
|
system "mv README.markdown.1 README.markdown &> /dev/null"
|
87
87
|
|
88
88
|
system "git commit -a -m \"Updated for Revision #{rev[1]}\" &> /dev/null"
|
89
|
-
puts "Commiting and Pushing Updates for Revision #{rev[1]}"
|
89
|
+
puts "[*] Commiting and Pushing Updates for Revision #{rev[1]}"
|
90
90
|
system "git push &> /dev/null"
|
91
91
|
|
92
92
|
#Twitter tweet for the update, I am that lazy yes.
|
data/lib/rex/parser/arguments.rb
CHANGED
@@ -26,6 +26,11 @@ class Arguments
|
|
26
26
|
#
|
27
27
|
def initialize(fmt)
|
28
28
|
self.fmt = fmt
|
29
|
+
# I think reduce is a better name for this method, but it doesn't exist
|
30
|
+
# before 1.8.7, so use the stupid inject instead.
|
31
|
+
self.longest = fmt.keys.inject(0) { |max, str|
|
32
|
+
max = ((max > str.length) ? max : str.length)
|
33
|
+
}
|
29
34
|
end
|
30
35
|
|
31
36
|
#
|
@@ -77,7 +82,7 @@ class Arguments
|
|
77
82
|
fmt.sort.each { |entry|
|
78
83
|
fmtspec, val = entry
|
79
84
|
|
80
|
-
txt << " #{fmtspec}" + ((val[0] == true) ? " <opt> " : " ")
|
85
|
+
txt << " #{fmtspec.ljust(longest)}" + ((val[0] == true) ? " <opt> " : " ")
|
81
86
|
txt << val[1] + "\n"
|
82
87
|
}
|
83
88
|
|
@@ -89,7 +94,12 @@ class Arguments
|
|
89
94
|
return fmt.include?(search)
|
90
95
|
end
|
91
96
|
|
92
|
-
|
97
|
+
def arg_required?(opt)
|
98
|
+
fmt[opt][0] if fmt[opt]
|
99
|
+
end
|
100
|
+
|
101
|
+
attr_accessor :fmt # :nodoc:
|
102
|
+
attr_accessor :longest # :nodoc:
|
93
103
|
|
94
104
|
end
|
95
105
|
|
@@ -29,6 +29,7 @@ class NexposeXMLStreamParser
|
|
29
29
|
@host["os_vendor"] = attributes["vendor"]
|
30
30
|
@host["os_family"] = attributes["family"]
|
31
31
|
@host["os_product"] = attributes["product"]
|
32
|
+
@host["os_version"] = attributes["version"]
|
32
33
|
@host["arch"] = attributes["arch"]
|
33
34
|
@host["os_certainty"] = attributes["certainty"]
|
34
35
|
end
|
@@ -76,7 +77,7 @@ class NexposeXMLStreamParser
|
|
76
77
|
when "vulnerability"
|
77
78
|
callback.call(:vuln, @vuln) if callback
|
78
79
|
reset_state
|
79
|
-
when "service","reference"
|
80
|
+
when "service","reference","names"
|
80
81
|
@state = :generic_state
|
81
82
|
end
|
82
83
|
end
|
data/lib/rex/parser/nmap_xml.rb
CHANGED
@@ -70,10 +70,18 @@ class NmapXMLStreamParser
|
|
70
70
|
@host["addr"] = attributes["addr"]
|
71
71
|
end
|
72
72
|
when "osclass"
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
73
|
+
# If there is more than one, take the highest accuracy. In case of
|
74
|
+
# a tie, this will have the effect of taking the last one in the
|
75
|
+
# list. Last is really no better than first but nmap appears to
|
76
|
+
# put OSes in chronological order, at least for Windows.
|
77
|
+
# Accordingly, this will report XP instead of 2000, 7 instead of
|
78
|
+
# Vista, etc, when each has the same accuracy.
|
79
|
+
if (@host["os_accuracy"].to_i <= attributes["accuracy"].to_i)
|
80
|
+
@host["os_vendor"] = attributes["vendor"]
|
81
|
+
@host["os_family"] = attributes["osfamily"]
|
82
|
+
@host["os_version"] = attributes["osgen"]
|
83
|
+
@host["os_accuracy"] = attributes["accuracy"]
|
84
|
+
end
|
77
85
|
when "osmatch"
|
78
86
|
if(attributes["accuracy"].to_i == 100)
|
79
87
|
@host["os_match"] = attributes["name"]
|
@@ -96,7 +96,15 @@ Separator = "\\"
|
|
96
96
|
def File.stat(name)
|
97
97
|
return client.fs.filestat.new(name)
|
98
98
|
end
|
99
|
-
|
99
|
+
|
100
|
+
#
|
101
|
+
# Determines if a file exists and returns true/false
|
102
|
+
#
|
103
|
+
def File.exists?(name)
|
104
|
+
r = client.fs.filestat.new(name) rescue nil
|
105
|
+
r ? true : false
|
106
|
+
end
|
107
|
+
|
100
108
|
#
|
101
109
|
# Performs a delete on the specified file.
|
102
110
|
#
|
@@ -1,4 +1,9 @@
|
|
1
1
|
$:.unshift(File.join(File.dirname(__FILE__)))
|
2
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', '..','..','..','..','..', 'lib'))
|
3
|
+
|
4
|
+
require 'test/unit'
|
5
|
+
require 'rex'
|
6
|
+
|
2
7
|
require 'railgun/api_constants.rb.ut'
|
3
8
|
require 'railgun/buffer_item.rb.ut'
|
4
9
|
require 'railgun/dll_function.rb.ut'
|
@@ -25,6 +25,8 @@
|
|
25
25
|
require 'rex/post/meterpreter/extensions/stdapi/railgun/dll_helper'
|
26
26
|
require 'rex/post/meterpreter/extensions/stdapi/railgun/dll_function'
|
27
27
|
require 'rex/post/meterpreter/extensions/stdapi/railgun/buffer_item'
|
28
|
+
require 'rex/post/meterpreter/extensions/stdapi/railgun/tlv'
|
29
|
+
require 'rex/post/meterpreter/packet'
|
28
30
|
|
29
31
|
module Rex
|
30
32
|
module Post
|
@@ -299,8 +301,36 @@ class DLL
|
|
299
301
|
end
|
300
302
|
end
|
301
303
|
#puts return_hash
|
302
|
-
#puts "finished"
|
303
304
|
|
305
|
+
#puts "finished"
|
306
|
+
# puts("
|
307
|
+
#=== START of proccess_function_call snapshot ===
|
308
|
+
# {
|
309
|
+
# :platform => '#{@native == 'Q' ? 'x64/win64' : 'x86/win32'}',
|
310
|
+
# :name => '#{function.windows_name}',
|
311
|
+
# :params => #{function.params},
|
312
|
+
# :return_type => '#{function.return_type}',
|
313
|
+
# :dll_name => '#{@dll_path}',
|
314
|
+
# :ruby_args => #{args.inspect},
|
315
|
+
# :request_to_client => {
|
316
|
+
# TLV_TYPE_RAILGUN_SIZE_OUT => #{out_only_size_bytes},
|
317
|
+
# TLV_TYPE_RAILGUN_STACKBLOB => #{literal_pairs_blob.inspect},
|
318
|
+
# TLV_TYPE_RAILGUN_BUFFERBLOB_IN => #{in_only_buffer.inspect},
|
319
|
+
# TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => #{inout_buffer.inspect},
|
320
|
+
# TLV_TYPE_RAILGUN_DLLNAME => '#{@dll_path}',
|
321
|
+
# TLV_TYPE_RAILGUN_FUNCNAME => '#{function.windows_name}',
|
322
|
+
# },
|
323
|
+
# :response_from_client => {
|
324
|
+
# TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => #{rec_inout_buffers.inspect},
|
325
|
+
# TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => #{rec_out_only_buffers.inspect},
|
326
|
+
# TLV_TYPE_RAILGUN_BACK_RET => #{rec_return_value.inspect},
|
327
|
+
# TLV_TYPE_RAILGUN_BACK_ERR => #{rec_last_error},
|
328
|
+
# },
|
329
|
+
# :returned_hash => #{return_hash.inspect},
|
330
|
+
# },
|
331
|
+
#=== END of proccess_function_call snapshot ===
|
332
|
+
# ")
|
333
|
+
#
|
304
334
|
return return_hash
|
305
335
|
end
|
306
336
|
|
@@ -219,6 +219,38 @@ class UI < Rex::Post::UI
|
|
219
219
|
return response.get_tlv_value(TLV_TYPE_KEYS_DUMP);
|
220
220
|
end
|
221
221
|
|
222
|
+
#
|
223
|
+
# Extract the keystroke from the buffer data
|
224
|
+
#
|
225
|
+
def keyscan_extract(buffer_data)
|
226
|
+
outp = ""
|
227
|
+
buffer_data.unpack("n*").each do |inp|
|
228
|
+
fl = (inp & 0xff00) >> 8
|
229
|
+
vk = (inp & 0xff)
|
230
|
+
kc = VirtualKeyCodes[vk]
|
231
|
+
|
232
|
+
f_shift = fl & (1<<1)
|
233
|
+
f_ctrl = fl & (1<<2)
|
234
|
+
f_alt = fl & (1<<3)
|
235
|
+
|
236
|
+
if(kc)
|
237
|
+
name = ((f_shift != 0 and kc.length > 1) ? kc[1] : kc[0])
|
238
|
+
case name
|
239
|
+
when /^.$/
|
240
|
+
outp << name
|
241
|
+
when /shift|click/i
|
242
|
+
when 'Space'
|
243
|
+
outp << " "
|
244
|
+
else
|
245
|
+
outp << " <#{name}> "
|
246
|
+
end
|
247
|
+
else
|
248
|
+
outp << " <0x%.2x> " % vk
|
249
|
+
end
|
250
|
+
end
|
251
|
+
return outp
|
252
|
+
end
|
253
|
+
|
222
254
|
protected
|
223
255
|
attr_accessor :client # :nodoc:
|
224
256
|
|
@@ -80,6 +80,8 @@ class Console
|
|
80
80
|
#
|
81
81
|
def interact_with_channel(channel)
|
82
82
|
channel.extend(InteractiveChannel) unless (channel.kind_of?(InteractiveChannel) == true)
|
83
|
+
channel.on_command_proc = self.on_command_proc if self.on_command_proc
|
84
|
+
channel.on_print_proc = self.on_print_proc if self.on_print_proc
|
83
85
|
|
84
86
|
channel.interact(input, output)
|
85
87
|
channel.reset_ui
|
@@ -36,6 +36,11 @@ module Console::CommandDispatcher
|
|
36
36
|
@@file_hash[name] = klass
|
37
37
|
end
|
38
38
|
|
39
|
+
def initialize(shell)
|
40
|
+
@msf_loaded = nil
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
39
44
|
#
|
40
45
|
# Returns the meterpreter client context.
|
41
46
|
#
|
@@ -43,6 +48,24 @@ module Console::CommandDispatcher
|
|
43
48
|
shell.client
|
44
49
|
end
|
45
50
|
|
51
|
+
#
|
52
|
+
# Returns true if the client has a framework object.
|
53
|
+
#
|
54
|
+
# Used for firing framework session events
|
55
|
+
#
|
56
|
+
def msf_loaded?
|
57
|
+
return @msf_loaded unless @msf_loaded.nil?
|
58
|
+
# if we get here we must not have initialized yet
|
59
|
+
|
60
|
+
if client.framework
|
61
|
+
# We have a framework instance so the msf libraries should be
|
62
|
+
# available. Load up the ones we're going to use
|
63
|
+
require 'msf/base/serializer/readable_text'
|
64
|
+
end
|
65
|
+
@msf_loaded = !!(client.framework)
|
66
|
+
@msf_loaded
|
67
|
+
end
|
68
|
+
|
46
69
|
#
|
47
70
|
# Log that an error occurred.
|
48
71
|
#
|
@@ -59,4 +82,4 @@ end
|
|
59
82
|
end
|
60
83
|
end
|
61
84
|
end
|
62
|
-
end
|
85
|
+
end
|
@@ -27,23 +27,9 @@ class Console::CommandDispatcher::Core
|
|
27
27
|
self.bgjobs = []
|
28
28
|
self.bgjob_id = 0
|
29
29
|
|
30
|
-
@msf_loaded = nil
|
31
30
|
end
|
32
31
|
|
33
|
-
|
34
|
-
return @msf_loaded unless @msf_loaded.nil?
|
35
|
-
# if we get here we must not have initialized yet
|
36
|
-
|
37
|
-
if client.framework
|
38
|
-
# We have a framework instance so the msf libraries should be
|
39
|
-
# available. Load up the ones we're going to use
|
40
|
-
require 'msf/base/serializer/readable_text'
|
41
|
-
end
|
42
|
-
@msf_loaded = !!(client.framework)
|
43
|
-
@msf_loaded
|
44
|
-
end
|
45
|
-
|
46
|
-
@@use_opts = Rex::Parser::Arguments.new(
|
32
|
+
@@load_opts = Rex::Parser::Arguments.new(
|
47
33
|
"-l" => [ false, "List all available extensions" ],
|
48
34
|
"-h" => [ false, "Help menu." ])
|
49
35
|
|
@@ -61,7 +47,8 @@ class Console::CommandDispatcher::Core
|
|
61
47
|
"interact" => "Interacts with a channel",
|
62
48
|
"irb" => "Drop into irb scripting mode",
|
63
49
|
"migrate" => "Migrate the server to another process",
|
64
|
-
"use" => "
|
50
|
+
"use" => "Deprecated alias for 'load'",
|
51
|
+
"load" => "Load one or more meterpreter extensions",
|
65
52
|
"quit" => "Terminate the meterpreter session",
|
66
53
|
"resource" => "Run the commands stored in a file",
|
67
54
|
"read" => "Reads data from a channel",
|
@@ -85,6 +72,13 @@ class Console::CommandDispatcher::Core
|
|
85
72
|
"Core"
|
86
73
|
end
|
87
74
|
|
75
|
+
def cmd_background_help
|
76
|
+
print_line "Usage: background"
|
77
|
+
print_line
|
78
|
+
print_line "Stop interacting with this session and return to the parent prompt"
|
79
|
+
print_line
|
80
|
+
end
|
81
|
+
|
88
82
|
def cmd_background
|
89
83
|
client.interacting = false
|
90
84
|
end
|
@@ -93,37 +87,61 @@ class Console::CommandDispatcher::Core
|
|
93
87
|
# Displays information about active channels
|
94
88
|
#
|
95
89
|
@@channel_opts = Rex::Parser::Arguments.new(
|
90
|
+
"-c" => [ true, "Close the given channel." ],
|
91
|
+
"-i" => [ true, "Interact with the given channel." ],
|
96
92
|
"-l" => [ false, "List active channels." ],
|
97
|
-
"-
|
93
|
+
"-r" => [ true, "Read from the given channel." ],
|
94
|
+
"-w" => [ true, "Write to the given channel." ],
|
95
|
+
"-h" => [ false, "Help menu." ])
|
96
|
+
|
97
|
+
def cmd_channel_help
|
98
|
+
print_line "Usage: channel [options]"
|
99
|
+
print_line
|
100
|
+
print_line "Displays information about active channels."
|
101
|
+
print_line @@channel_opts.usage
|
102
|
+
end
|
98
103
|
|
99
104
|
#
|
100
105
|
# Performs operations on the supplied channel.
|
101
106
|
#
|
102
107
|
def cmd_channel(*args)
|
103
|
-
if
|
104
|
-
|
108
|
+
if args.include?("-h") or args.include?("--help")
|
109
|
+
cmd_channel_help
|
110
|
+
return
|
105
111
|
end
|
106
112
|
|
107
113
|
mode = nil
|
114
|
+
chan = nil
|
115
|
+
data = []
|
108
116
|
|
109
117
|
# Parse options
|
110
118
|
@@channel_opts.parse(args) { |opt, idx, val|
|
111
119
|
case opt
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
+
when "-l"
|
121
|
+
mode = :list
|
122
|
+
when "-c"
|
123
|
+
mode = :close
|
124
|
+
chan = val
|
125
|
+
when "-i"
|
126
|
+
mode = :interact
|
127
|
+
chan = val
|
128
|
+
when "-r"
|
129
|
+
mode = :read
|
130
|
+
chan = val
|
131
|
+
when "-w"
|
132
|
+
mode = :write
|
133
|
+
chan = val
|
134
|
+
end
|
135
|
+
if @@channel_opts.arg_required?(opt)
|
136
|
+
unless chan
|
137
|
+
print_error("Channel ID required")
|
138
|
+
return
|
139
|
+
end
|
120
140
|
end
|
121
141
|
}
|
122
142
|
|
123
|
-
|
124
|
-
|
125
|
-
return true
|
126
|
-
elsif (mode == 'list')
|
143
|
+
case mode
|
144
|
+
when :list
|
127
145
|
tbl = Rex::Ui::Text::Table.new(
|
128
146
|
'Indent' => 4,
|
129
147
|
'Columns' =>
|
@@ -144,6 +162,17 @@ class Console::CommandDispatcher::Core
|
|
144
162
|
else
|
145
163
|
print("\n" + tbl.to_s + "\n")
|
146
164
|
end
|
165
|
+
when :close
|
166
|
+
cmd_close(chan)
|
167
|
+
when :interact
|
168
|
+
cmd_interact(chan)
|
169
|
+
when :read
|
170
|
+
cmd_read(chan)
|
171
|
+
when :write
|
172
|
+
cmd_write(chan)
|
173
|
+
else
|
174
|
+
# No mode, no service.
|
175
|
+
return true
|
147
176
|
end
|
148
177
|
end
|
149
178
|
|
@@ -239,17 +268,24 @@ class Console::CommandDispatcher::Core
|
|
239
268
|
print_status("Migration completed successfully.")
|
240
269
|
end
|
241
270
|
|
271
|
+
def cmd_load_help
|
272
|
+
print_line("Usage: load ext1 ext2 ext3 ...")
|
273
|
+
print_line
|
274
|
+
print_line "Loads a meterpreter extension module or modules."
|
275
|
+
print_line @@load_opts.usage
|
276
|
+
end
|
277
|
+
|
242
278
|
#
|
243
279
|
# Loads one or more meterpreter extensions.
|
244
280
|
#
|
245
|
-
def
|
281
|
+
def cmd_load(*args)
|
246
282
|
if (args.length == 0)
|
247
283
|
args.unshift("-h")
|
248
284
|
end
|
249
285
|
|
250
286
|
modules = nil
|
251
287
|
|
252
|
-
@@
|
288
|
+
@@load_opts.parse(args) { |opt, idx, val|
|
253
289
|
case opt
|
254
290
|
when "-l"
|
255
291
|
exts = []
|
@@ -263,10 +299,7 @@ class Console::CommandDispatcher::Core
|
|
263
299
|
|
264
300
|
return true
|
265
301
|
when "-h"
|
266
|
-
|
267
|
-
"Usage: use ext1 ext2 ext3 ...\n\n" +
|
268
|
-
"Loads a meterpreter extension module or modules.\n" +
|
269
|
-
@@use_opts.usage)
|
302
|
+
cmd_load_help
|
270
303
|
return true
|
271
304
|
end
|
272
305
|
}
|
@@ -299,7 +332,7 @@ class Console::CommandDispatcher::Core
|
|
299
332
|
return true
|
300
333
|
end
|
301
334
|
|
302
|
-
def
|
335
|
+
def cmd_load_tabs(str, words)
|
303
336
|
tabs = []
|
304
337
|
path = ::File.join(Msf::Config.install_root, 'data', 'meterpreter')
|
305
338
|
::Dir.entries(path).each { |f|
|
@@ -312,6 +345,13 @@ class Console::CommandDispatcher::Core
|
|
312
345
|
return tabs
|
313
346
|
end
|
314
347
|
|
348
|
+
def cmd_use(*args)
|
349
|
+
#print_error("Warning: The 'use' command is deprecated in favor of 'load'")
|
350
|
+
cmd_load(*args)
|
351
|
+
end
|
352
|
+
alias cmd_use_help cmd_load_help
|
353
|
+
alias cmd_use_tabs cmd_load_tabs
|
354
|
+
|
315
355
|
#
|
316
356
|
# Reads data from a channel.
|
317
357
|
#
|
@@ -487,6 +527,13 @@ class Console::CommandDispatcher::Core
|
|
487
527
|
end
|
488
528
|
end
|
489
529
|
|
530
|
+
def cmd_info_help
|
531
|
+
print_line 'Usage: info <module>'
|
532
|
+
print_line
|
533
|
+
print_line 'Prints information about a post-exploitation module'
|
534
|
+
print_line
|
535
|
+
end
|
536
|
+
|
490
537
|
#
|
491
538
|
# Show info for a given Post module.
|
492
539
|
#
|
@@ -495,8 +542,8 @@ class Console::CommandDispatcher::Core
|
|
495
542
|
def cmd_info(*args)
|
496
543
|
return unless msf_loaded?
|
497
544
|
|
498
|
-
if args.length != 1
|
499
|
-
|
545
|
+
if args.length != 1 or args.include?("-h")
|
546
|
+
cmd_info_help
|
500
547
|
return
|
501
548
|
end
|
502
549
|
|
@@ -524,9 +571,17 @@ class Console::CommandDispatcher::Core
|
|
524
571
|
"-f" => [ true, "Write the contents of a file on disk" ],
|
525
572
|
"-h" => [ false, "Help menu." ])
|
526
573
|
|
574
|
+
def cmd_write_help
|
575
|
+
print_line "Usage: write [options] channel_id"
|
576
|
+
print_line
|
577
|
+
print_line "Writes data to the supplied channel."
|
578
|
+
print_line @@write_opts.usage
|
579
|
+
end
|
580
|
+
|
527
581
|
def cmd_write(*args)
|
528
|
-
if (args.length == 0)
|
529
|
-
|
582
|
+
if (args.length == 0 or args.include?("-h"))
|
583
|
+
cmd_write_help
|
584
|
+
return
|
530
585
|
end
|
531
586
|
|
532
587
|
src_file = nil
|
@@ -534,12 +589,6 @@ class Console::CommandDispatcher::Core
|
|
534
589
|
|
535
590
|
@@write_opts.parse(args) { |opt, idx, val|
|
536
591
|
case opt
|
537
|
-
when "-h"
|
538
|
-
print(
|
539
|
-
"Usage: write [options] channel_id\n\n" +
|
540
|
-
"Writes data to the supplied channel.\n" +
|
541
|
-
@@write_opts.usage)
|
542
|
-
return true
|
543
592
|
when "-f"
|
544
593
|
src_file = val
|
545
594
|
else
|
@@ -225,10 +225,12 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|
225
225
|
if (stat.directory?)
|
226
226
|
client.fs.dir.download(dest, src, recursive, true) { |step, src, dst|
|
227
227
|
print_status("#{step.ljust(11)}: #{src} -> #{dst}")
|
228
|
+
client.framework.events.on_session_download(client, src, dest) if msf_loaded?
|
228
229
|
}
|
229
230
|
elsif (stat.file?)
|
230
231
|
client.fs.file.download(dest, src) { |step, src, dst|
|
231
232
|
print_status("#{step.ljust(11)}: #{src} -> #{dst}")
|
233
|
+
client.framework.events.on_session_download(client, src, dest) if msf_loaded?
|
232
234
|
}
|
233
235
|
end
|
234
236
|
}
|
@@ -417,10 +419,12 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|
417
419
|
if (stat.directory?)
|
418
420
|
client.fs.dir.upload(dest, src, recursive) { |step, src, dst|
|
419
421
|
print_status("#{step.ljust(11)}: #{src} -> #{dst}")
|
422
|
+
client.framework.events.on_session_upload(client, src, dest) if msf_loaded?
|
420
423
|
}
|
421
424
|
elsif (stat.file?)
|
422
425
|
client.fs.file.upload(dest, src) { |step, src, dst|
|
423
426
|
print_status("#{step.ljust(11)}: #{src} -> #{dst}")
|
427
|
+
client.framework.events.on_session_upload(client, src, dest) if msf_loaded?
|
424
428
|
}
|
425
429
|
end
|
426
430
|
}
|
@@ -51,7 +51,7 @@ class Console::CommandDispatcher::Stdapi::Sys
|
|
51
51
|
"execute" => "Execute a command",
|
52
52
|
"getpid" => "Get the current process identifier",
|
53
53
|
"getuid" => "Get the user that the server is running as",
|
54
|
-
"getprivs" => "
|
54
|
+
"getprivs" => "List all privileges available to the current process",
|
55
55
|
"kill" => "Terminate a process",
|
56
56
|
"ps" => "List running processes",
|
57
57
|
"reboot" => "Reboots the remote computer",
|
@@ -277,32 +277,7 @@ class Console::CommandDispatcher::Stdapi::Ui
|
|
277
277
|
def cmd_keyscan_dump(*args)
|
278
278
|
print_line("Dumping captured keystrokes...")
|
279
279
|
data = client.ui.keyscan_dump
|
280
|
-
|
281
|
-
data.unpack("n*").each do |inp|
|
282
|
-
fl = (inp & 0xff00) >> 8
|
283
|
-
vk = (inp & 0xff)
|
284
|
-
kc = VirtualKeyCodes[vk]
|
285
|
-
|
286
|
-
f_shift = fl & (1<<1)
|
287
|
-
f_ctrl = fl & (1<<2)
|
288
|
-
f_alt = fl & (1<<3)
|
289
|
-
|
290
|
-
if(kc)
|
291
|
-
name = ((f_shift != 0 and kc.length > 1) ? kc[1] : kc[0])
|
292
|
-
case name
|
293
|
-
when /^.$/
|
294
|
-
outp << name
|
295
|
-
when /shift|click/i
|
296
|
-
when 'Space'
|
297
|
-
outp << " "
|
298
|
-
else
|
299
|
-
outp << " <#{name}> "
|
300
|
-
end
|
301
|
-
else
|
302
|
-
outp << " <0x%.2x> " % vk
|
303
|
-
end
|
304
|
-
end
|
305
|
-
print_line(outp)
|
280
|
+
print_line(client.ui.keyscan_extract(data))
|
306
281
|
|
307
282
|
return true
|
308
283
|
end
|
@@ -68,6 +68,8 @@ module Console::InteractiveChannel
|
|
68
68
|
def _stream_read_local_write_remote(channel)
|
69
69
|
data = user_input.gets
|
70
70
|
return if not data
|
71
|
+
|
72
|
+
self.on_command_proc.call(data.strip) if self.on_command_proc
|
71
73
|
self.write(data)
|
72
74
|
end
|
73
75
|
|
@@ -77,6 +79,7 @@ module Console::InteractiveChannel
|
|
77
79
|
def _stream_read_remote_write_local(channel)
|
78
80
|
data = self.lsock.sysread(16384)
|
79
81
|
|
82
|
+
self.on_print_proc.call(data.strip) if self.on_print_proc
|
80
83
|
user_output.print(data)
|
81
84
|
end
|
82
85
|
|
@@ -226,7 +226,6 @@ class Socks4a
|
|
226
226
|
@rsock = nil
|
227
227
|
@client_thread = nil
|
228
228
|
@mutex = ::Mutex.new
|
229
|
-
@closed = false
|
230
229
|
end
|
231
230
|
|
232
231
|
#
|
@@ -248,8 +247,9 @@ class Socks4a
|
|
248
247
|
params = {
|
249
248
|
'PeerHost' => request.dest_ip,
|
250
249
|
'PeerPort' => request.dest_port,
|
251
|
-
'Comm' => @server.opts['Comm']
|
252
250
|
}
|
251
|
+
params['Context'] = @server.opts['Context'] if @server.opts.has_key?('Context')
|
252
|
+
|
253
253
|
@rsock = Rex::Socket::Tcp.create( params )
|
254
254
|
# and send back success to the client
|
255
255
|
response = Packet.new
|
@@ -262,8 +262,8 @@ class Socks4a
|
|
262
262
|
params = {
|
263
263
|
'LocalHost' => '0.0.0.0',
|
264
264
|
'LocalPort' => 0,
|
265
|
-
'Comm' => @server.opts['Comm']
|
266
265
|
}
|
266
|
+
params['Context'] = @server.opts['Context'] if @server.opts.has_key?('Context')
|
267
267
|
bsock = Rex::Socket::TcpServer.create( params )
|
268
268
|
# send back the bind success to the client
|
269
269
|
response = Packet.new
|
@@ -353,7 +353,7 @@ class Socks4a
|
|
353
353
|
# Create a new Socks4a server.
|
354
354
|
#
|
355
355
|
def initialize( opts={} )
|
356
|
-
@opts = { 'ServerHost' => '0.0.0.0', 'ServerPort' => 1080
|
356
|
+
@opts = { 'ServerHost' => '0.0.0.0', 'ServerPort' => 1080 }
|
357
357
|
@opts = @opts.merge( opts )
|
358
358
|
@server = nil
|
359
359
|
@clients = ::Array.new
|
@@ -373,7 +373,7 @@ class Socks4a
|
|
373
373
|
#
|
374
374
|
def start
|
375
375
|
begin
|
376
|
-
# create the servers main socket
|
376
|
+
# create the servers main socket (ignore the context here because we don't want a remote bind)
|
377
377
|
@server = Rex::Socket::TcpServer.create( 'LocalHost' => @opts['ServerHost'], 'LocalPort' => @opts['ServerPort'] )
|
378
378
|
# signal we are now running
|
379
379
|
@running = true
|
data/lib/rex/ui/interactive.rb
CHANGED
@@ -108,6 +108,9 @@ module Interactive
|
|
108
108
|
#
|
109
109
|
attr_accessor :completed
|
110
110
|
|
111
|
+
attr_accessor :on_print_proc
|
112
|
+
attr_accessor :on_command_proc
|
113
|
+
|
111
114
|
protected
|
112
115
|
|
113
116
|
#
|
@@ -148,6 +151,7 @@ protected
|
|
148
151
|
def _stream_read_remote_write_local(stream)
|
149
152
|
data = stream.get
|
150
153
|
|
154
|
+
self.on_print_proc.call(data) if self.on_print_proc
|
151
155
|
user_output.print(data)
|
152
156
|
end
|
153
157
|
|
@@ -157,6 +161,7 @@ protected
|
|
157
161
|
def _stream_read_local_write_remote(stream)
|
158
162
|
data = user_input.gets
|
159
163
|
|
164
|
+
self.on_command_proc.call(data) if self.on_command_proc
|
160
165
|
stream.put(data)
|
161
166
|
end
|
162
167
|
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: librex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.29
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Metasploit Development Team
|
@@ -11,11 +11,11 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2011-04-
|
14
|
+
date: 2011-04-19 00:00:00 -05:00
|
15
15
|
default_executable:
|
16
16
|
dependencies: []
|
17
17
|
|
18
|
-
description: Rex provides a variety of classes useful for security testing and exploit development. Based on SVN Revision
|
18
|
+
description: Rex provides a variety of classes useful for security testing and exploit development. Based on SVN Revision 12371
|
19
19
|
email:
|
20
20
|
- hdm@metasploit.com
|
21
21
|
- jacob.hammack@hammackj.com
|