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