rex-core 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +3 -2
- data/lib/rex/core/version.rb +1 -1
- data/lib/rex/exceptions.rb +307 -0
- data/lib/rex/io/datagram_abstraction.rb +26 -0
- data/lib/rex/io/ring_buffer.rb +369 -0
- data/lib/rex/io/socket_abstraction.rb +205 -0
- data/lib/rex/io/stream.rb +312 -0
- data/lib/rex/io/stream_abstraction.rb +32 -0
- data/lib/rex/io/stream_server.rb +221 -0
- data/lib/rex/sync.rb +6 -0
- data/lib/rex/sync/event.rb +85 -0
- data/lib/rex/sync/read_write_lock.rb +177 -0
- data/lib/rex/sync/ref.rb +58 -0
- data/lib/rex/sync/thread_safe.rb +83 -0
- metadata +14 -2
- metadata.gz.sig +0 -0
@@ -0,0 +1,205 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
require 'fcntl'
|
5
|
+
|
6
|
+
module Rex
|
7
|
+
module IO
|
8
|
+
|
9
|
+
###
|
10
|
+
#
|
11
|
+
# This class provides an abstraction to a stream based
|
12
|
+
# connection through the use of a streaming socketpair.
|
13
|
+
#
|
14
|
+
###
|
15
|
+
module SocketAbstraction
|
16
|
+
|
17
|
+
###
|
18
|
+
#
|
19
|
+
# Extension information for required Stream interface.
|
20
|
+
#
|
21
|
+
###
|
22
|
+
module Ext
|
23
|
+
|
24
|
+
#
|
25
|
+
# Initializes peer information.
|
26
|
+
#
|
27
|
+
def initinfo(peer,local)
|
28
|
+
@peer = peer
|
29
|
+
@local = local
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# Symbolic peer information.
|
34
|
+
#
|
35
|
+
def peerinfo
|
36
|
+
(@peer || "Remote Pipe")
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# Symbolic local information.
|
41
|
+
#
|
42
|
+
def localinfo
|
43
|
+
(@local || "Local Pipe")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Override this method to init the abstraction
|
49
|
+
#
|
50
|
+
def initialize_abstraction
|
51
|
+
self.lsock, self.rsock = Rex::Compat.pipe
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# This method cleans up the abstraction layer.
|
56
|
+
#
|
57
|
+
def cleanup_abstraction
|
58
|
+
self.lsock.close if (self.lsock and !self.lsock.closed?)
|
59
|
+
self.rsock.close if (self.rsock and !self.rsock.closed?)
|
60
|
+
|
61
|
+
self.lsock = nil
|
62
|
+
self.rsock = nil
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# Low-level write to the local side.
|
67
|
+
#
|
68
|
+
def syswrite(buffer)
|
69
|
+
lsock.syswrite(buffer)
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Low-level read from the local side.
|
74
|
+
#
|
75
|
+
def sysread(length)
|
76
|
+
lsock.sysread(length)
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
# Shuts down the local side of the stream abstraction.
|
81
|
+
#
|
82
|
+
def shutdown(how)
|
83
|
+
lsock.shutdown(how)
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# Closes both sides of the stream abstraction.
|
88
|
+
#
|
89
|
+
def close
|
90
|
+
cleanup_abstraction
|
91
|
+
super
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# Symbolic peer information.
|
96
|
+
#
|
97
|
+
def peerinfo
|
98
|
+
"Remote-side of Pipe"
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Symbolic local information.
|
103
|
+
#
|
104
|
+
def localinfo
|
105
|
+
"Local-side of Pipe"
|
106
|
+
end
|
107
|
+
|
108
|
+
#
|
109
|
+
# The left side of the stream.
|
110
|
+
#
|
111
|
+
attr_reader :lsock
|
112
|
+
#
|
113
|
+
# The right side of the stream.
|
114
|
+
#
|
115
|
+
attr_reader :rsock
|
116
|
+
|
117
|
+
protected
|
118
|
+
|
119
|
+
def monitor_rsock(threadname = "SocketMonitorRemote")
|
120
|
+
self.monitor_thread = Rex::ThreadFactory.spawn(threadname, false) {
|
121
|
+
loop do
|
122
|
+
closed = false
|
123
|
+
buf = nil
|
124
|
+
|
125
|
+
if not self.rsock
|
126
|
+
wlog("monitor_rsock: the remote socket is nil, exiting loop")
|
127
|
+
break
|
128
|
+
end
|
129
|
+
|
130
|
+
begin
|
131
|
+
s = Rex::ThreadSafe.select( [ self.rsock ], nil, nil, 0.2 )
|
132
|
+
if( s == nil || s[0] == nil )
|
133
|
+
next
|
134
|
+
end
|
135
|
+
rescue Exception => e
|
136
|
+
wlog("monitor_rsock: exception during select: #{e.class} #{e}")
|
137
|
+
closed = true
|
138
|
+
end
|
139
|
+
|
140
|
+
if( closed == false )
|
141
|
+
begin
|
142
|
+
buf = self.rsock.sysread( 32768 )
|
143
|
+
if buf == nil
|
144
|
+
closed = true
|
145
|
+
wlog("monitor_rsock: closed remote socket due to nil read")
|
146
|
+
end
|
147
|
+
rescue EOFError => e
|
148
|
+
closed = true
|
149
|
+
dlog("monitor_rsock: EOF in rsock")
|
150
|
+
rescue ::Exception => e
|
151
|
+
closed = true
|
152
|
+
wlog("monitor_rsock: exception during read: #{e.class} #{e}")
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
if( closed == false )
|
157
|
+
total_sent = 0
|
158
|
+
total_length = buf.length
|
159
|
+
while( total_sent < total_length )
|
160
|
+
begin
|
161
|
+
data = buf[total_sent, buf.length]
|
162
|
+
|
163
|
+
# Note that this must be write() NOT syswrite() or put() or anything like it.
|
164
|
+
# Using syswrite() breaks SSL streams.
|
165
|
+
sent = self.write( data )
|
166
|
+
|
167
|
+
# sf: Only remove the data off the queue is write was successfull.
|
168
|
+
# This way we naturally perform a resend if a failure occured.
|
169
|
+
# Catches an edge case with meterpreter TCP channels where remote send
|
170
|
+
# failes gracefully and a resend is required.
|
171
|
+
if (sent.nil?)
|
172
|
+
closed = true
|
173
|
+
wlog("monitor_rsock: failed writing, socket must be dead")
|
174
|
+
break
|
175
|
+
elsif (sent > 0)
|
176
|
+
total_sent += sent
|
177
|
+
end
|
178
|
+
rescue ::IOError, ::EOFError => e
|
179
|
+
closed = true
|
180
|
+
wlog("monitor_rsock: exception during write: #{e.class} #{e}")
|
181
|
+
break
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
if( closed )
|
187
|
+
begin
|
188
|
+
self.close_write if self.respond_to?('close_write')
|
189
|
+
rescue IOError
|
190
|
+
end
|
191
|
+
break
|
192
|
+
end
|
193
|
+
end
|
194
|
+
}
|
195
|
+
end
|
196
|
+
|
197
|
+
protected
|
198
|
+
attr_accessor :monitor_thread
|
199
|
+
attr_writer :lsock
|
200
|
+
attr_writer :rsock
|
201
|
+
|
202
|
+
end
|
203
|
+
|
204
|
+
end; end
|
205
|
+
|
@@ -0,0 +1,312 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
require 'rex/sync/thread_safe'
|
3
|
+
|
4
|
+
module Rex
|
5
|
+
module IO
|
6
|
+
|
7
|
+
###
|
8
|
+
#
|
9
|
+
# This mixin is an abstract representation of a streaming connection. Streams
|
10
|
+
# extend classes that must implement the following methods:
|
11
|
+
#
|
12
|
+
# syswrite(buffer)
|
13
|
+
# sysread(length)
|
14
|
+
# shutdown(how)
|
15
|
+
# close
|
16
|
+
# peerinfo
|
17
|
+
# localinfo
|
18
|
+
#
|
19
|
+
###
|
20
|
+
module Stream
|
21
|
+
|
22
|
+
##
|
23
|
+
#
|
24
|
+
# Abstract methods
|
25
|
+
#
|
26
|
+
##
|
27
|
+
|
28
|
+
#
|
29
|
+
# This method writes the supplied buffer to the stream. This method
|
30
|
+
# intelligent reduces the size of supplied buffers so that ruby doesn't get
|
31
|
+
# into a potential global thread blocking state when used on blocking
|
32
|
+
# sockets. That is, this method will send the supplied buffer in chunks
|
33
|
+
# of, at most, 32768 bytes.
|
34
|
+
#
|
35
|
+
def write(buf, opts = {})
|
36
|
+
total_sent = 0
|
37
|
+
total_length = buf.length
|
38
|
+
block_size = 32768
|
39
|
+
|
40
|
+
begin
|
41
|
+
while( total_sent < total_length )
|
42
|
+
s = Rex::ThreadSafe.select( nil, [ fd ], nil, 0.2 )
|
43
|
+
if( s == nil || s[0] == nil )
|
44
|
+
next
|
45
|
+
end
|
46
|
+
data = buf[total_sent, block_size]
|
47
|
+
sent = fd.write_nonblock( data )
|
48
|
+
if sent > 0
|
49
|
+
total_sent += sent
|
50
|
+
end
|
51
|
+
end
|
52
|
+
rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
|
53
|
+
# Sleep for a half a second, or until we can write again
|
54
|
+
Rex::ThreadSafe.select( nil, [ fd ], nil, 0.5 )
|
55
|
+
# Decrement the block size to handle full sendQs better
|
56
|
+
block_size = 1024
|
57
|
+
# Try to write the data again
|
58
|
+
retry
|
59
|
+
rescue ::IOError, ::Errno::EPIPE
|
60
|
+
return nil
|
61
|
+
end
|
62
|
+
|
63
|
+
total_sent
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# This method reads data of the supplied length from the stream.
|
68
|
+
#
|
69
|
+
def read(length = nil, opts = {})
|
70
|
+
|
71
|
+
begin
|
72
|
+
return fd.read_nonblock( length )
|
73
|
+
rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
|
74
|
+
# Sleep for a half a second, or until we can read again
|
75
|
+
Rex::ThreadSafe.select( [ fd ], nil, nil, 0.5 )
|
76
|
+
# Decrement the block size to handle full sendQs better
|
77
|
+
retry
|
78
|
+
rescue ::IOError, ::Errno::EPIPE
|
79
|
+
return nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# Polls the stream to see if there is any read data available. Returns
|
85
|
+
# true if data is available for reading, otherwise false is returned.
|
86
|
+
#
|
87
|
+
def has_read_data?(timeout = nil)
|
88
|
+
|
89
|
+
# Allow a timeout of "0" that waits almost indefinitely for input, this
|
90
|
+
# mimics the behavior of Rex::ThreadSafe.select() and fixes some corner
|
91
|
+
# cases of unintentional no-wait timeouts.
|
92
|
+
timeout = 3600 if (timeout and timeout == 0)
|
93
|
+
|
94
|
+
begin
|
95
|
+
if ((rv = ::IO.select([ fd ], nil, nil, timeout)) and
|
96
|
+
(rv[0]) and
|
97
|
+
(rv[0][0] == fd))
|
98
|
+
true
|
99
|
+
else
|
100
|
+
false
|
101
|
+
end
|
102
|
+
rescue ::Errno::EBADF, ::Errno::ENOTSOCK
|
103
|
+
raise ::EOFError
|
104
|
+
rescue StreamClosedError, ::IOError, ::EOFError, ::Errno::EPIPE
|
105
|
+
# Return false if the socket is dead
|
106
|
+
return false
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
#
|
111
|
+
# This method returns the selectable file descriptor, or self by default.
|
112
|
+
#
|
113
|
+
def fd
|
114
|
+
self
|
115
|
+
end
|
116
|
+
|
117
|
+
##
|
118
|
+
#
|
119
|
+
# Common methods
|
120
|
+
#
|
121
|
+
##
|
122
|
+
|
123
|
+
#
|
124
|
+
# This method writes the supplied buffer to the stream by calling the write
|
125
|
+
# routine.
|
126
|
+
#
|
127
|
+
def <<(buf)
|
128
|
+
return write(buf.to_s)
|
129
|
+
end
|
130
|
+
|
131
|
+
#
|
132
|
+
# This method calls get_once() to read pending data from the socket
|
133
|
+
#
|
134
|
+
def >>
|
135
|
+
get_once
|
136
|
+
end
|
137
|
+
|
138
|
+
#
|
139
|
+
# This method writes to the stream, optionally timing out after a period of
|
140
|
+
# time.
|
141
|
+
#
|
142
|
+
def timed_write(buf, wait = def_write_timeout, opts = {})
|
143
|
+
if (wait and wait > 0)
|
144
|
+
Timeout.timeout(wait) {
|
145
|
+
return write(buf, opts)
|
146
|
+
}
|
147
|
+
else
|
148
|
+
return write(buf, opts)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
#
|
153
|
+
# This method reads from the stream, optionally timing out after a period
|
154
|
+
# of time.
|
155
|
+
#
|
156
|
+
def timed_read(length = nil, wait = def_read_timeout, opts = {})
|
157
|
+
if (wait and wait > 0)
|
158
|
+
Timeout.timeout(wait) {
|
159
|
+
return read(length, opts)
|
160
|
+
}
|
161
|
+
else
|
162
|
+
return read(length, opts)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
#
|
167
|
+
# This method writes the full contents of the supplied buffer, optionally
|
168
|
+
# with a timeout.
|
169
|
+
#
|
170
|
+
def put(buf, opts = {})
|
171
|
+
return 0 if (buf == nil or buf.length == 0)
|
172
|
+
|
173
|
+
send_len = buf.length
|
174
|
+
send_idx = 0
|
175
|
+
wait = opts['Timeout'] || 0
|
176
|
+
|
177
|
+
# Keep writing until our send length drops to zero
|
178
|
+
while (send_idx < send_len)
|
179
|
+
curr_len = timed_write(buf[send_idx, buf.length-send_idx], wait, opts)
|
180
|
+
|
181
|
+
# If the write operation failed due to an IOError, then we fail.
|
182
|
+
return buf.length - send_len if (curr_len == nil)
|
183
|
+
|
184
|
+
send_len -= curr_len
|
185
|
+
send_idx += curr_len
|
186
|
+
end
|
187
|
+
|
188
|
+
return buf.length - send_len
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
#
|
193
|
+
# This method emulates the behavior of Pex::Socket::Recv in MSF2
|
194
|
+
#
|
195
|
+
def get_once(length = -1, timeout = def_read_timeout)
|
196
|
+
|
197
|
+
if (has_read_data?(timeout) == false)
|
198
|
+
return nil
|
199
|
+
end
|
200
|
+
|
201
|
+
bsize = (length == -1) ? def_block_size : length
|
202
|
+
data = read(bsize)
|
203
|
+
raise EOFError if data.nil?
|
204
|
+
data
|
205
|
+
end
|
206
|
+
|
207
|
+
#
|
208
|
+
# This method reads as much data as it can from the wire given a maximum
|
209
|
+
# timeout.
|
210
|
+
#
|
211
|
+
def get(timeout = nil, ltimeout = def_read_loop_timeout, opts = {})
|
212
|
+
# For those people who are used to being able to use a negative timeout!
|
213
|
+
if (timeout and timeout.to_i < 0)
|
214
|
+
timeout = nil
|
215
|
+
end
|
216
|
+
|
217
|
+
# No data in the first place? bust.
|
218
|
+
if (has_read_data?(timeout) == false)
|
219
|
+
return nil
|
220
|
+
end
|
221
|
+
|
222
|
+
buf = ""
|
223
|
+
lps = 0
|
224
|
+
eof = false
|
225
|
+
|
226
|
+
# Keep looping until there is no more data to be gotten..
|
227
|
+
while (has_read_data?(ltimeout) == true)
|
228
|
+
# Catch EOF errors so that we can handle them properly.
|
229
|
+
begin
|
230
|
+
temp = read(def_block_size)
|
231
|
+
rescue EOFError
|
232
|
+
eof = true
|
233
|
+
end
|
234
|
+
|
235
|
+
# If we read zero bytes and we had data, then we've hit EOF
|
236
|
+
if (temp and temp.length == 0)
|
237
|
+
eof = true
|
238
|
+
end
|
239
|
+
|
240
|
+
# If we reached EOF and there are no bytes in the buffer we've been
|
241
|
+
# reading into, then throw an EOF error.
|
242
|
+
if (eof)
|
243
|
+
# If we've already read at least some data, then it's time to
|
244
|
+
# break out and let it be processed before throwing an EOFError.
|
245
|
+
if (buf.length > 0)
|
246
|
+
break
|
247
|
+
else
|
248
|
+
raise EOFError
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
break if (temp == nil or temp.empty? == true)
|
253
|
+
|
254
|
+
buf += temp
|
255
|
+
lps += 1
|
256
|
+
|
257
|
+
break if (lps >= def_max_loops)
|
258
|
+
end
|
259
|
+
|
260
|
+
# Return the entire buffer we read in
|
261
|
+
return buf
|
262
|
+
end
|
263
|
+
|
264
|
+
##
|
265
|
+
#
|
266
|
+
# Defaults
|
267
|
+
#
|
268
|
+
##
|
269
|
+
|
270
|
+
#
|
271
|
+
# The default number of seconds to wait for a write operation to timeout.
|
272
|
+
#
|
273
|
+
def def_write_timeout
|
274
|
+
10
|
275
|
+
end
|
276
|
+
|
277
|
+
#
|
278
|
+
# The default number of seconds to wait for a read operation to timeout.
|
279
|
+
#
|
280
|
+
def def_read_timeout
|
281
|
+
10
|
282
|
+
end
|
283
|
+
|
284
|
+
#
|
285
|
+
# The default number of seconds to wait while in a read loop after read
|
286
|
+
# data has been found.
|
287
|
+
#
|
288
|
+
def def_read_loop_timeout
|
289
|
+
0.1
|
290
|
+
end
|
291
|
+
|
292
|
+
#
|
293
|
+
# The maximum number of read loops to perform before returning to the
|
294
|
+
# caller.
|
295
|
+
#
|
296
|
+
def def_max_loops
|
297
|
+
1024
|
298
|
+
end
|
299
|
+
|
300
|
+
#
|
301
|
+
# The default block size to read in chunks from the wire.
|
302
|
+
#
|
303
|
+
def def_block_size
|
304
|
+
16384
|
305
|
+
end
|
306
|
+
|
307
|
+
protected
|
308
|
+
|
309
|
+
end
|
310
|
+
|
311
|
+
end end
|
312
|
+
|