librex 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +4 -0
- data/lib/rex/exploitation/cmdstager.rb +9 -133
- data/lib/rex/exploitation/cmdstager/base.rb +170 -0
- data/lib/rex/exploitation/cmdstager/debug_asm.rb +142 -0
- data/lib/rex/exploitation/cmdstager/debug_write.rb +136 -0
- data/lib/rex/exploitation/cmdstager/tftp.rb +63 -0
- data/lib/rex/exploitation/cmdstager/vbs.rb +128 -0
- data/lib/rex/io/stream.rb +2 -2
- data/lib/rex/io/stream_server.rb +1 -1
- data/lib/rex/job_container.rb +7 -6
- data/lib/rex/mime/header.rb +12 -10
- data/lib/rex/mime/message.rb +57 -26
- data/lib/rex/ole/directory.rb +5 -4
- data/lib/rex/ole/samples/create_ole.rb +0 -0
- data/lib/rex/ole/samples/dir.rb +0 -0
- data/lib/rex/ole/samples/dump_stream.rb +1 -1
- data/lib/rex/ole/samples/ole_info.rb +0 -0
- data/lib/rex/parser/nexpose_xml.rb +131 -0
- data/lib/rex/parser/nmap_xml.rb +1 -0
- data/lib/rex/peparsey/pe.rb +21 -3
- data/lib/rex/post/meterpreter/client.rb +6 -1
- data/lib/rex/post/meterpreter/client_core.rb +2 -2
- data/lib/rex/post/meterpreter/extensions/priv/priv.rb +19 -18
- data/lib/rex/post/meterpreter/packet.rb +68 -0
- data/lib/rex/post/meterpreter/packet_dispatcher.rb +2 -2
- data/lib/rex/post/meterpreter/packet_response_waiter.rb +5 -5
- data/lib/rex/post/meterpreter/ui/console.rb +2 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +5 -2
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +2 -2
- data/lib/rex/proto/dcerpc/client.rb.ut.rb +0 -0
- data/lib/rex/proto/http/client.rb +8 -3
- data/lib/rex/proto/http/packet.rb +11 -1
- data/lib/rex/proto/smb/client.rb +1 -1
- data/lib/rex/proto/smb/utils.rb +72 -24
- data/lib/rex/proto/tftp.rb +3 -0
- data/lib/rex/proto/tftp/constants.rb +37 -0
- data/lib/rex/proto/tftp/server.rb +249 -0
- data/lib/rex/proto/tftp/server.rb.ut.rb +28 -0
- data/lib/rex/script/meterpreter.rb +6 -0
- data/lib/rex/services/local_relay.rb +2 -2
- data/lib/rex/socket/ip.rb +9 -8
- data/lib/rex/socket/range_walker.rb +43 -5
- data/lib/rex/socket/udp.rb +11 -4
- data/lib/rex/text.rb +42 -19
- data/lib/rex/ui/interactive.rb +24 -22
- data/lib/rex/ui/text/irb_shell.rb +4 -2
- data/lib/rex/ui/text/output/file.rb +6 -0
- data/lib/rex/ui/text/shell.rb +14 -18
- data/lib/rex/zip/samples/comment.rb +0 -0
- data/lib/rex/zip/samples/mkwar.rb +0 -0
- data/lib/rex/zip/samples/mkzip.rb +0 -0
- data/lib/rex/zip/samples/recursive.rb +0 -0
- metadata +20 -5
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# $Revision: 9333 $
|
4
|
+
#
|
5
|
+
# $Id: server.rb.ut.rb 9333 2010-05-21 00:03:04Z jduck $
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'rex/compat'
|
9
|
+
require 'rex/proto/tftp'
|
10
|
+
|
11
|
+
content = nil
|
12
|
+
|
13
|
+
fn = ARGV.shift
|
14
|
+
if (fn and fn.length > 0)
|
15
|
+
File.open(fn, "rb") do |fd|
|
16
|
+
content = fd.read(fd.stat.size)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
content ||= "A" * (1024*1024)
|
21
|
+
|
22
|
+
|
23
|
+
tftp = Rex::Proto::TFTP::Server.new
|
24
|
+
tftp.register_file("poo", content)
|
25
|
+
tftp.start
|
26
|
+
|
27
|
+
#loop { break if not tftp.thread.alive? }
|
28
|
+
tftp.thread.join
|
@@ -370,7 +370,7 @@ protected
|
|
370
370
|
|
371
371
|
# Poll all the streams...
|
372
372
|
begin
|
373
|
-
socks = select(rfds, nil, nil, 0.25)
|
373
|
+
socks = Rex::ThreadSafe.select(rfds, nil, nil, 0.25)
|
374
374
|
rescue StreamClosedError => e
|
375
375
|
dlog("monitor_relays: closing stream #{e.stream}", 'rex', LEV_3)
|
376
376
|
|
@@ -384,7 +384,7 @@ protected
|
|
384
384
|
|
385
385
|
next
|
386
386
|
rescue
|
387
|
-
elog("Error in #{self} monitor_relays select: #{$!}", 'rex')
|
387
|
+
elog("Error in #{self} monitor_relays select: #{$!.class} #{$!}", 'rex')
|
388
388
|
return
|
389
389
|
end
|
390
390
|
|
data/lib/rex/socket/ip.rb
CHANGED
@@ -19,7 +19,7 @@ module Rex::Socket::Ip
|
|
19
19
|
# Creates the client using the supplied hash.
|
20
20
|
#
|
21
21
|
def self.create(hash = {})
|
22
|
-
hash['Proto'] = 'ip'
|
22
|
+
hash['Proto'] = 'ip'
|
23
23
|
self.create_param(Rex::Socket::Parameters.from_hash(hash))
|
24
24
|
end
|
25
25
|
|
@@ -65,7 +65,7 @@ module Rex::Socket::Ip
|
|
65
65
|
#
|
66
66
|
def sendto(gram, peerhost, flags = 0)
|
67
67
|
dest = ::Socket.pack_sockaddr_in(0, peerhost)
|
68
|
-
|
68
|
+
|
69
69
|
# Some BSDs require byteswap for len and offset
|
70
70
|
if(
|
71
71
|
Rex::Compat.is_freebsd or
|
@@ -82,8 +82,8 @@ module Rex::Socket::Ip
|
|
82
82
|
send(gram, flags, dest)
|
83
83
|
rescue ::Errno::EHOSTUNREACH,::Errno::ENETDOWN,::Errno::ENETUNREACH,::Errno::ENETRESET,::Errno::EHOSTDOWN,::Errno::EACCES,::Errno::EINVAL,::Errno::EADDRNOTAVAIL
|
84
84
|
return nil
|
85
|
-
end
|
86
|
-
|
85
|
+
end
|
86
|
+
|
87
87
|
end
|
88
88
|
|
89
89
|
#
|
@@ -92,7 +92,7 @@ module Rex::Socket::Ip
|
|
92
92
|
#
|
93
93
|
def recvfrom(length = 65535, timeout=def_read_timeout)
|
94
94
|
begin
|
95
|
-
if ((rv =
|
95
|
+
if ((rv = ::IO.select([ fd ], nil, nil, timeout)) and
|
96
96
|
(rv[0]) and (rv[0][0] == fd)
|
97
97
|
)
|
98
98
|
data, saddr = super(length)
|
@@ -106,7 +106,7 @@ module Rex::Socket::Ip
|
|
106
106
|
return [ '', nil ]
|
107
107
|
end
|
108
108
|
end
|
109
|
-
|
109
|
+
|
110
110
|
#
|
111
111
|
# Calls recvfrom and only returns the data
|
112
112
|
#
|
@@ -114,16 +114,17 @@ module Rex::Socket::Ip
|
|
114
114
|
data, saddr = recvfrom(65535, timeout)
|
115
115
|
return data
|
116
116
|
end
|
117
|
-
|
117
|
+
|
118
118
|
#
|
119
119
|
# The default number of seconds to wait for a read operation to timeout.
|
120
120
|
#
|
121
121
|
def def_read_timeout
|
122
122
|
10
|
123
|
-
end
|
123
|
+
end
|
124
124
|
|
125
125
|
def type?
|
126
126
|
return 'ip'
|
127
127
|
end
|
128
128
|
|
129
129
|
end
|
130
|
+
|
@@ -27,20 +27,46 @@ class RangeWalker
|
|
27
27
|
reset
|
28
28
|
end
|
29
29
|
|
30
|
+
#
|
31
|
+
# Calls the instance method
|
32
|
+
#
|
33
|
+
# This is basically only useful for determining if a range can be parsed
|
34
|
+
#
|
30
35
|
def self.parse(parseme)
|
31
36
|
self.new.parse(parseme)
|
32
37
|
end
|
33
38
|
|
39
|
+
#
|
40
|
+
# Turn a human-readable range string into ranges we can step through one address at a time.
|
41
|
+
#
|
42
|
+
# Allow the following formats:
|
43
|
+
# "a.b.c.d e.f.g.h"
|
44
|
+
# "a.b.c.d, e.f.g.h"
|
45
|
+
# where each chunk is CIDR notation, (e.g. '10.1.1.0/24') or a range in nmap format (see expand_nmap)
|
46
|
+
#
|
47
|
+
# OR this format
|
48
|
+
# "a.b.c.d-e.f.g.h"
|
49
|
+
# where a.b.c.d and e.f.g.h are single IPs and the second must be
|
50
|
+
# bigger than the first.
|
51
|
+
#
|
34
52
|
def parse(parseme)
|
35
53
|
return nil if not parseme
|
36
54
|
ranges = []
|
37
|
-
parseme.split(' ').each { |arg|
|
55
|
+
parseme.split(', ').map{ |a| a.split(' ') }.flatten.each { |arg|
|
38
56
|
if arg.include?("/")
|
39
57
|
# Then it's CIDR notation and needs special case
|
40
|
-
if arg =~ /[,-]/
|
41
|
-
|
42
|
-
|
58
|
+
return false if arg =~ /[,-]/ # Improper CIDR notation (can't mix with 1,3 or 1-3 style IP ranges)
|
59
|
+
return false if arg.scan("/").size > 1 # ..but there are too many slashes
|
60
|
+
ip_part,mask_part = arg.split("/")
|
61
|
+
return false if ip_part.nil? or ip_part.empty? or mask_part.nil? or mask_part.empty?
|
62
|
+
return false if mask_part !~ /^[0-9]{1,2}$/ # Illegal mask -- numerals only
|
63
|
+
return false if mask_part.to_i > 32 # This too -- between 0 and 32.
|
64
|
+
begin
|
65
|
+
Rex::Socket.addr_atoi(ip_part) # This allows for "www.metasploit.com/24" which is fun.
|
66
|
+
rescue Resolv::ResolvError
|
67
|
+
return false # Can't resolve the ip_part, so bail.
|
43
68
|
end
|
69
|
+
|
44
70
|
expanded = expand_cidr(arg)
|
45
71
|
if expanded
|
46
72
|
ranges += expanded
|
@@ -58,6 +84,16 @@ class RangeWalker
|
|
58
84
|
# unmolested to force a DNS lookup.
|
59
85
|
addr = Rex::Socket.addr_atoi(arg)
|
60
86
|
ranges.push [addr, addr]
|
87
|
+
elsif arg =~ /^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)-([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$/
|
88
|
+
# Then it's in the format of 1.2.3.4-5.6.7.8
|
89
|
+
# Note, this will /not/ deal with DNS names, or the fancy/obscure 10...1-10...2
|
90
|
+
begin
|
91
|
+
addrs = [Rex::Socket.addr_atoi($1), Rex::Socket.addr_atoi($2)]
|
92
|
+
return false if addrs[0] > addrs[1] # The end is greater than the beginning.
|
93
|
+
ranges.push [addrs[0], addrs[1]]
|
94
|
+
rescue Resolv::ResolvError # Something's broken, forget it.
|
95
|
+
return false
|
96
|
+
end
|
61
97
|
else
|
62
98
|
expanded = expand_nmap(arg)
|
63
99
|
if expanded
|
@@ -274,14 +310,16 @@ class RangeWalker
|
|
274
310
|
#
|
275
311
|
# The total number of IPs within the range
|
276
312
|
#
|
277
|
-
attr_reader :ranges
|
278
313
|
attr_reader :length
|
279
314
|
|
280
315
|
# for backwards compatibility
|
281
316
|
alias :num_ips :length
|
282
317
|
|
318
|
+
attr_reader :ranges
|
319
|
+
|
283
320
|
end
|
284
321
|
|
322
|
+
# :nodoc:
|
285
323
|
class Range < Array
|
286
324
|
def start; self[0]; end
|
287
325
|
def stop; self[1]; end
|
data/lib/rex/socket/udp.rb
CHANGED
@@ -72,7 +72,7 @@ module Rex::Socket::Udp
|
|
72
72
|
#
|
73
73
|
def timed_read(length = 65535, timeout=def_read_timeout)
|
74
74
|
begin
|
75
|
-
if ((rv =
|
75
|
+
if ((rv = ::IO.select([ fd ], nil, nil, timeout)) and
|
76
76
|
(rv[0]) and (rv[0][0] == fd)
|
77
77
|
)
|
78
78
|
return read(length)
|
@@ -101,7 +101,10 @@ module Rex::Socket::Udp
|
|
101
101
|
# Catch unconnected IPv6 sockets talking to IPv4 addresses
|
102
102
|
peer = Rex::Socket.resolv_nbo(peerhost)
|
103
103
|
if (peer.length == 4 and self.ipv == 6)
|
104
|
-
peerhost =
|
104
|
+
peerhost = Rex::Socket.getaddress(peerhost)
|
105
|
+
if peerhost[0,7].downcase != '::ffff:'
|
106
|
+
peerhost = '::ffff:' + peerhost
|
107
|
+
end
|
105
108
|
end
|
106
109
|
|
107
110
|
begin
|
@@ -119,7 +122,7 @@ module Rex::Socket::Udp
|
|
119
122
|
def recvfrom(length = 65535, timeout=def_read_timeout)
|
120
123
|
|
121
124
|
begin
|
122
|
-
if ((rv =
|
125
|
+
if ((rv = ::IO.select([ fd ], nil, nil, timeout)) and
|
123
126
|
(rv[0]) and (rv[0][0] == fd)
|
124
127
|
)
|
125
128
|
data, saddr = recvfrom_nonblock(length)
|
@@ -129,7 +132,11 @@ module Rex::Socket::Udp
|
|
129
132
|
else
|
130
133
|
return [ '', nil, nil ]
|
131
134
|
end
|
132
|
-
rescue
|
135
|
+
rescue ::Timeout::Error
|
136
|
+
return [ '', nil, nil ]
|
137
|
+
rescue ::Interrupt
|
138
|
+
raise $!
|
139
|
+
rescue ::Exception
|
133
140
|
return [ '', nil, nil ]
|
134
141
|
end
|
135
142
|
end
|
data/lib/rex/text.rb
CHANGED
@@ -39,6 +39,10 @@ module Text
|
|
39
39
|
AllChars = [*(0x00 .. 0xff)].pack("C*")
|
40
40
|
|
41
41
|
DefaultPatternSets = [ Rex::Text::UpperAlpha, Rex::Text::LowerAlpha, Rex::Text::Numerals ]
|
42
|
+
|
43
|
+
# In case Iconv isn't loaded
|
44
|
+
Iconv_EBCDIC = ["\x00", "\x01", "\x02", "\x03", "7", "-", ".", "/", "\x16", "\x05", "%", "\v", "\f", "\r", "\x0E", "\x0F", "\x10", "\x11", "\x12", "\x13", "<", "=", "2", "&", "\x18", "\x19", "?", "'", "\x1C", "\x1D", "\x1E", "\x1F", "@", "Z", "\x7F", "{", "[", "l", "P", "}", "M", "]", "\\", "N", "k", "`", "K", "a", "\xF0", "\xF1", "\xF2", "\xF3", "\xF4", "\xF5", "\xF6", "\xF7", "\xF8", "\xF9", "z", "^", "L", "~", "n", "o", "|", "\xC1", "\xC2", "\xC3", "\xC4", "\xC5", "\xC6", "\xC7", "\xC8", "\xC9", "\xD1", "\xD2", "\xD3", "\xD4", "\xD5", "\xD6", "\xD7", "\xD8", "\xD9", "\xE2", "\xE3", "\xE4", "\xE5", "\xE6", "\xE7", "\xE8", "\xE9", nil, "\xE0", nil, nil, "m", "y", "\x81", "\x82", "\x83", "\x84", "\x85", "\x86", "\x87", "\x88", "\x89", "\x91", "\x92", "\x93", "\x94", "\x95", "\x96", "\x97", "\x98", "\x99", "\xA2", "\xA3", "\xA4", "\xA5", "\xA6", "\xA7", "\xA8", "\xA9", "\xC0", "O", "\xD0", "\xA1", "\a", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]
|
45
|
+
Iconv_ASCII = ["\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\a", "\b", "\t", "\n", "\v", "\f", "\r", "\x0E", "\x0F", "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17", "\x18", "\x19", "\x1A", "\e", "\x1C", "\x1D", "\x1E", "\x1F", " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", nil, "\\", nil, nil, "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "\x7F", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]
|
42
46
|
|
43
47
|
##
|
44
48
|
#
|
@@ -139,13 +143,43 @@ module Text
|
|
139
143
|
#
|
140
144
|
# Converts ASCII to EBCDIC
|
141
145
|
#
|
146
|
+
class IllegalSequence < ArgumentError; end
|
147
|
+
|
148
|
+
# A native implementation of the ASCII->EBCDIC table, used to fall back from using
|
149
|
+
# Iconv
|
150
|
+
def self.to_ebcdic_rex(str)
|
151
|
+
new_str = []
|
152
|
+
str.each_byte do |x|
|
153
|
+
if Iconv_ASCII.index(x.chr)
|
154
|
+
new_str << Iconv_EBCDIC[Iconv_ASCII.index(x.chr)]
|
155
|
+
else
|
156
|
+
raise Rex::Text::IllegalSequence, ("\\x%x" % x)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
new_str.join
|
160
|
+
end
|
161
|
+
|
162
|
+
# A native implementation of the EBCDIC->ASCII table, used to fall back from using
|
163
|
+
# Iconv
|
164
|
+
def self.from_ebcdic_rex(str)
|
165
|
+
new_str = []
|
166
|
+
str.each_byte do |x|
|
167
|
+
if Iconv_EBCDIC.index(x.chr)
|
168
|
+
new_str << Iconv_ASCII[Iconv_EBCDIC.index(x.chr)]
|
169
|
+
else
|
170
|
+
raise Rex::Text::IllegalSequence, ("\\x%x" % x)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
new_str.join
|
174
|
+
end
|
175
|
+
|
142
176
|
def self.to_ebcdic(str)
|
143
177
|
begin
|
144
178
|
Iconv.iconv("EBCDIC-US", "ASCII", str).first
|
145
179
|
rescue ::Iconv::IllegalSequence => e
|
146
180
|
raise e
|
147
181
|
rescue
|
148
|
-
|
182
|
+
self.to_ebcdic_rex(str)
|
149
183
|
end
|
150
184
|
end
|
151
185
|
|
@@ -158,7 +192,7 @@ module Text
|
|
158
192
|
rescue ::Iconv::IllegalSequence => e
|
159
193
|
raise e
|
160
194
|
rescue
|
161
|
-
|
195
|
+
self.from_ebcdic_rex(str)
|
162
196
|
end
|
163
197
|
end
|
164
198
|
|
@@ -463,7 +497,7 @@ module Text
|
|
463
497
|
coords = []
|
464
498
|
(1 << str.size).times { |i| coords << ("%0#{str.size}b" % i) }
|
465
499
|
mixed = []
|
466
|
-
coords.each do |coord|
|
500
|
+
coords.each do |coord|
|
467
501
|
c = coord.scan(/./).map {|x| x.to_i}
|
468
502
|
this_str = ""
|
469
503
|
c.each_with_index { |d,i| this_str << letters[i][d] }
|
@@ -626,22 +660,11 @@ module Text
|
|
626
660
|
|
627
661
|
# Base text generator method
|
628
662
|
def self.rand_base(len, bad, *foo)
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
buff = ""
|
636
|
-
|
637
|
-
# Generate a buffer from the remaining bytes
|
638
|
-
if foo.length >= 256
|
639
|
-
len.times { buff << Kernel.rand(256) }
|
640
|
-
else
|
641
|
-
len.times { buff << foo[ rand(foo.length) ] }
|
642
|
-
end
|
643
|
-
|
644
|
-
return buff
|
663
|
+
cset = (foo.join.unpack("C*") - bad.to_s.unpack("C*")).uniq
|
664
|
+
return if cset.length == 0
|
665
|
+
outp = []
|
666
|
+
len.times { outp << cset[rand(cset.length)] }
|
667
|
+
outp.pack("C*")
|
645
668
|
end
|
646
669
|
|
647
670
|
# Generate random bytes of data
|
data/lib/rex/ui/interactive.rb
CHANGED
@@ -16,12 +16,12 @@ module Interactive
|
|
16
16
|
include Rex::Ui::Subscriber
|
17
17
|
|
18
18
|
#
|
19
|
-
# Starts interacting with the session at the most raw level, simply
|
19
|
+
# Starts interacting with the session at the most raw level, simply
|
20
20
|
# forwarding input from user_input to rstream and forwarding input from
|
21
21
|
# rstream to user_output.
|
22
22
|
#
|
23
23
|
def interact(user_input, user_output)
|
24
|
-
|
24
|
+
|
25
25
|
# Detach from any existing console
|
26
26
|
if(self.interacting)
|
27
27
|
detach()
|
@@ -34,13 +34,13 @@ module Interactive
|
|
34
34
|
|
35
35
|
eof = false
|
36
36
|
|
37
|
-
# Start the readline stdin monitor
|
37
|
+
# Start the readline stdin monitor
|
38
38
|
# XXX disabled
|
39
39
|
# user_input.readline_start() if user_input.supports_readline
|
40
|
-
|
40
|
+
|
41
41
|
# Handle suspend notifications
|
42
42
|
handle_suspend
|
43
|
-
|
43
|
+
|
44
44
|
# As long as we're interacting...
|
45
45
|
while (self.interacting == true)
|
46
46
|
|
@@ -52,18 +52,18 @@ module Interactive
|
|
52
52
|
# abort the interaction. If they do, then we return out of
|
53
53
|
# the interact function and call it a day.
|
54
54
|
eof = true if (_interrupt)
|
55
|
-
|
55
|
+
|
56
56
|
rescue EOFError, Errno::ECONNRESET, IOError
|
57
57
|
# If we reach EOF or the connection is reset...
|
58
58
|
eof = true
|
59
|
-
|
59
|
+
|
60
60
|
end
|
61
61
|
|
62
62
|
break if eof
|
63
63
|
end
|
64
64
|
|
65
65
|
begin
|
66
|
-
|
66
|
+
|
67
67
|
# Restore the suspend handler
|
68
68
|
restore_suspend
|
69
69
|
|
@@ -73,10 +73,10 @@ module Interactive
|
|
73
73
|
# Shutdown the readline thread
|
74
74
|
# XXX disabled
|
75
75
|
# user_input.readline_stop() if user_input.supports_readline
|
76
|
-
|
76
|
+
|
77
77
|
# Detach from the input/output handles
|
78
78
|
reset_ui()
|
79
|
-
|
79
|
+
|
80
80
|
ensure
|
81
81
|
# Mark this as completed
|
82
82
|
self.completed = true
|
@@ -93,7 +93,7 @@ module Interactive
|
|
93
93
|
if (self.interacting)
|
94
94
|
self.interacting = false
|
95
95
|
while(not self.completed)
|
96
|
-
select(nil, nil, nil, 0.25)
|
96
|
+
::IO.select(nil, nil, nil, 0.25)
|
97
97
|
end
|
98
98
|
end
|
99
99
|
end
|
@@ -102,14 +102,14 @@ module Interactive
|
|
102
102
|
# Whether or not the session is currently being interacted with
|
103
103
|
#
|
104
104
|
attr_accessor :interacting
|
105
|
-
|
105
|
+
|
106
106
|
#
|
107
107
|
# Whether or not the session has completed interaction
|
108
108
|
#
|
109
109
|
attr_accessor :completed
|
110
110
|
|
111
111
|
protected
|
112
|
-
|
112
|
+
|
113
113
|
#
|
114
114
|
# The original suspend proc.
|
115
115
|
#
|
@@ -156,7 +156,7 @@ protected
|
|
156
156
|
#
|
157
157
|
def _stream_read_local_write_remote(stream)
|
158
158
|
data = user_input.gets
|
159
|
-
|
159
|
+
|
160
160
|
stream.put(data)
|
161
161
|
end
|
162
162
|
|
@@ -180,10 +180,10 @@ protected
|
|
180
180
|
#
|
181
181
|
def interact_stream(stream)
|
182
182
|
while self.interacting
|
183
|
-
|
183
|
+
|
184
184
|
# Select input and rstream
|
185
185
|
sd = Rex::ThreadSafe.select([ _local_fd, _remote_fd(stream) ], nil, nil, 0.25)
|
186
|
-
|
186
|
+
|
187
187
|
# Cycle through the items that have data
|
188
188
|
# From the stream? Write to user_output.
|
189
189
|
sd[0].each { |s|
|
@@ -194,7 +194,7 @@ protected
|
|
194
194
|
_stream_read_local_write_remote(stream)
|
195
195
|
end
|
196
196
|
} if (sd)
|
197
|
-
|
197
|
+
|
198
198
|
Thread.pass
|
199
199
|
end
|
200
200
|
end
|
@@ -218,13 +218,14 @@ protected
|
|
218
218
|
# notifications.
|
219
219
|
#
|
220
220
|
def restore_suspend
|
221
|
-
|
222
|
-
|
221
|
+
begin
|
222
|
+
if (orig_suspend)
|
223
223
|
Signal.trap("TSTP", orig_suspend)
|
224
|
-
|
224
|
+
else
|
225
|
+
Signal.trap("TSTP", "DEFAULT")
|
225
226
|
end
|
226
|
-
|
227
227
|
self.orig_suspend = nil
|
228
|
+
rescue
|
228
229
|
end
|
229
230
|
end
|
230
231
|
|
@@ -238,7 +239,7 @@ protected
|
|
238
239
|
user_input.sysread(2)
|
239
240
|
end
|
240
241
|
end
|
241
|
-
|
242
|
+
|
242
243
|
#
|
243
244
|
# Check the return value of a yes/no prompt
|
244
245
|
#
|
@@ -250,3 +251,4 @@ end
|
|
250
251
|
|
251
252
|
end
|
252
253
|
end
|
254
|
+
|