rex-core 0.1.1 → 0.1.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d87573fa044f8ef47e4077c871ffed4fd951947d
4
- data.tar.gz: 81c929507834cb718d47433d7c63d2e86d364062
3
+ metadata.gz: 63a58cfcf3d6b9062c2bdca3eefca305eca585c7
4
+ data.tar.gz: 4185786772da9b7207faac16ad71fc808914ca83
5
5
  SHA512:
6
- metadata.gz: 5906b4a8e2d4468d0b1ff364c054480c287b5a6ffe61c6a6ddb4080306e81c9c26d67fad47a67846d9b830c21fe964173bc68f25de04ea16114df3087da993a8
7
- data.tar.gz: 6eb4511807ab5a2425591993c30c0e8fe98aad0732117cd365b7f28f2c5346c81f9260285e395d136f719ef6878b4b9c78ce8d059477d81350e7a29932df7ee8
6
+ metadata.gz: a0a38f7fd810b004bec6aca74ed6101fd01c3d2473256c1c510acd840047e8887560a4c6cca8c0f7d03650a2e33d6b2eae39cf588704cb6ff177da0282b50b46
7
+ data.tar.gz: e977b465922469f9682a6c91065ce5fc2c0cf50a356f0f643a986166689dea6499e96e6421cb752df62b644c1797d9c633e54ecb1d32c379ded339a66fed92ba
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
@@ -1,2 +1,3 @@
1
- _����9P�qD�=!�/���XpY(9F��8�J�U����rb�jV��K纮GD�#�be�3*:k"M�� ��J ��:x�����E�X���~����$�
2
- ��#�^��(�}�������UF�bW�H�g�Eͣ�6��_#kXg�T�e�q��KJ0�8Oj�m�a�e{I�H,#������{ܽ����?_5�{�b��L�L����h��{Kj4� "���C��ֈg�Tק�!��&�u
1
+ �+�^e�L��Ĺ��_�� kjN迒�T$Rr3]t�36x "DJ*��%B���b���O���æh��R*YS�|�r�����<��r
2
+ �-^��`��n��`f�{�-K}��P�]���B� \FtBD5���z��M�)�X�l�����\�N'Q��
3
+ P���)46�P1 N⮏�V�h���B
@@ -1,5 +1,5 @@
1
1
  module Rex
2
2
  module Core
3
- VERSION = "0.1.1"
3
+ VERSION = "0.1.2"
4
4
  end
5
5
  end
@@ -0,0 +1,307 @@
1
+ # -*- coding: binary -*-
2
+
3
+ module Rex
4
+
5
+ ###
6
+ #
7
+ # Base mixin for all exceptions that can be thrown from inside Rex.
8
+ #
9
+ ###
10
+ module Exception
11
+ end
12
+
13
+ ###
14
+ #
15
+ # This exception is raised when a timeout occurs.
16
+ #
17
+ ###
18
+ class TimeoutError < Interrupt
19
+ include Exception
20
+
21
+ def to_s
22
+ "Operation timed out."
23
+ end
24
+ end
25
+
26
+ ###
27
+ #
28
+ # This exception is raised when a method is called or a feature is used that
29
+ # is not implemented.
30
+ #
31
+ ###
32
+ class NotImplementedError < ::NotImplementedError
33
+ include Exception
34
+
35
+ def to_s
36
+ "The requested method is not implemented."
37
+ end
38
+ end
39
+
40
+ ###
41
+ #
42
+ # This exception is raised when a generalized runtime error occurs.
43
+ #
44
+ ###
45
+ class RuntimeError < ::RuntimeError
46
+ include Exception
47
+ end
48
+
49
+ ###
50
+ #
51
+ # This exception is raised when an invalid argument is supplied to a method.
52
+ #
53
+ ###
54
+ class ArgumentError < ::ArgumentError
55
+ include Exception
56
+
57
+ def initialize(message = nil)
58
+ @message = message
59
+ end
60
+
61
+ def to_s
62
+ str = 'An invalid argument was specified.'
63
+ if @message
64
+ str << " #{@message}"
65
+ end
66
+ str
67
+ end
68
+ end
69
+
70
+ ###
71
+ #
72
+ # This exception is raised when an argument that was supplied to a method
73
+ # could not be parsed correctly.
74
+ #
75
+ ###
76
+ class ArgumentParseError < ::ArgumentError
77
+ include Exception
78
+
79
+ def to_s
80
+ "The argument could not be parsed correctly."
81
+ end
82
+ end
83
+
84
+ ###
85
+ #
86
+ # This exception is raised when an argument is ambiguous.
87
+ #
88
+ ###
89
+ class AmbiguousArgumentError < ::RuntimeError
90
+ include Exception
91
+
92
+ def initialize(name = nil)
93
+ @name = name
94
+ end
95
+
96
+ def to_s
97
+ "The name #{@name} is ambiguous."
98
+ end
99
+ end
100
+
101
+ ###
102
+ #
103
+ # This error is thrown when a stream is detected as being closed.
104
+ #
105
+ ###
106
+ class StreamClosedError < ::IOError
107
+ include Exception
108
+
109
+ def initialize(stream)
110
+ @stream = stream
111
+ end
112
+
113
+ def stream
114
+ @stream
115
+ end
116
+
117
+ def to_s
118
+ "Stream #{@stream} is closed."
119
+ end
120
+ end
121
+
122
+ ##
123
+ #
124
+ # Socket exceptions
125
+ #
126
+ ##
127
+
128
+ ###
129
+ #
130
+ # This exception is raised when a general socket error occurs.
131
+ #
132
+ ###
133
+ module SocketError
134
+ include Exception
135
+
136
+ def to_s
137
+ "A socket error occurred."
138
+ end
139
+ end
140
+
141
+ ###
142
+ #
143
+ # This exception is raised when there is some kind of error related to
144
+ # communication with a host.
145
+ #
146
+ ###
147
+ module HostCommunicationError
148
+ def initialize(addr = nil, port = nil)
149
+ self.host = addr
150
+ self.port = port
151
+ end
152
+
153
+ #
154
+ # This method returns a printable address and optional port associated
155
+ # with the host that triggered the exception.
156
+ #
157
+ def addr_to_s
158
+ if host and port
159
+ "(#{host}:#{port})"
160
+ elsif host
161
+ "(#{host})"
162
+ else
163
+ ""
164
+ end
165
+ end
166
+
167
+ attr_accessor :host, :port
168
+ end
169
+
170
+
171
+ ###
172
+ #
173
+ # This is a generic exception for errors that cause a connection to fail.
174
+ #
175
+ ###
176
+ class ConnectionError < ::IOError
177
+ include SocketError
178
+ include HostCommunicationError
179
+ end
180
+
181
+ ###
182
+ #
183
+ # This exception is raised when a connection attempt fails because the remote
184
+ # side refused the connection.
185
+ #
186
+ ###
187
+ class ConnectionRefused < ConnectionError
188
+ def to_s
189
+ "The connection was refused by the remote host #{addr_to_s}."
190
+ end
191
+ end
192
+
193
+ ###
194
+ #
195
+ # This exception is raised when a connection attempt fails because the remote
196
+ # side is unreachable.
197
+ #
198
+ ###
199
+ class HostUnreachable < ConnectionError
200
+ def to_s
201
+ "The host #{addr_to_s} was unreachable."
202
+ end
203
+ end
204
+
205
+ ###
206
+ #
207
+ # This exception is raised when a connection attempt times out.
208
+ #
209
+ ###
210
+ class ConnectionTimeout < ConnectionError
211
+ def to_s
212
+ "The connection timed out #{addr_to_s}."
213
+ end
214
+ end
215
+
216
+ ###
217
+ #
218
+ # This connection error is raised when an attempt is made to connect
219
+ # to a broadcast or network address.
220
+ #
221
+ ###
222
+ class InvalidDestination < ConnectionError
223
+ include SocketError
224
+ include HostCommunicationError
225
+
226
+ def to_s
227
+ "The destination is invalid: #{addr_to_s}."
228
+ end
229
+ end
230
+
231
+ ###
232
+ #
233
+ # This exception is raised when an attempt to use an address or port that is
234
+ # already in use or onot available occurs. such as binding to a host on a
235
+ # given port that is already in use, or when a bind address is specified that
236
+ # is not available to the host.
237
+ #
238
+ ###
239
+ class BindFailed < ::ArgumentError
240
+ include SocketError
241
+ include HostCommunicationError
242
+
243
+ def to_s
244
+ "The address is already in use or unavailable: #{addr_to_s}."
245
+ end
246
+ end
247
+
248
+ ##
249
+ #
250
+ # This exception is listed for backwards compatibility. We had been
251
+ # using AddressInUse as the exception for both bind errors and connection
252
+ # errors triggered by connection attempts to broadcast and network addresses.
253
+ # The two classes above have split this into their respective sources, but
254
+ # callers may still expect the old behavior.
255
+ #
256
+ ##
257
+ class AddressInUse < ConnectionError
258
+ include SocketError
259
+ include HostCommunicationError
260
+
261
+ def to_s
262
+ "The address is already in use or unavailable: #{addr_to_s}."
263
+ end
264
+ end
265
+
266
+
267
+ ###
268
+ #
269
+ # This exception is raised when an unsupported internet protocol is specified.
270
+ #
271
+ ###
272
+ class UnsupportedProtocol < ::ArgumentError
273
+ include SocketError
274
+
275
+ def initialize(proto = nil)
276
+ self.proto = proto
277
+ end
278
+
279
+ def to_s
280
+ "The protocol #{proto} is not supported."
281
+ end
282
+
283
+ attr_accessor :proto
284
+ end
285
+
286
+
287
+ ###
288
+ #
289
+ # This exception is raised when a proxy fails to pass a connection
290
+ #
291
+ ###
292
+ class ConnectionProxyError < ConnectionError
293
+ def initialize(host,port,ptype,reason)
294
+ super(host,port)
295
+ self.ptype = ptype
296
+ self.reason = reason
297
+ end
298
+
299
+ def to_s
300
+ self.ptype + ": " + self.reason
301
+ end
302
+
303
+ attr_accessor :ptype, :reason
304
+ end
305
+
306
+ end
307
+
@@ -0,0 +1,26 @@
1
+ # -*- coding: binary -*-
2
+
3
+ require 'rex/io/socket_abstraction'
4
+
5
+ module Rex
6
+ module IO
7
+
8
+ ###
9
+ #
10
+ # This class provides an abstraction to a datagram based
11
+ # connection through the use of a datagram socketpair.
12
+ #
13
+ ###
14
+ module DatagramAbstraction
15
+ include Rex::IO::SocketAbstraction
16
+
17
+ #
18
+ # Creates a streaming socket pair
19
+ #
20
+ def initialize_abstraction
21
+ self.lsock, self.rsock = Rex::Socket.udp_socket_pair
22
+ end
23
+
24
+ end
25
+
26
+ end; end
@@ -0,0 +1,369 @@
1
+ # -*- coding: binary -*-
2
+ #
3
+ # This class implements a ring buffer with "cursors" in the form of sequence numbers.
4
+ # To use this class, pass in a file descriptor and a ring size, the class will read
5
+ # data from the file descriptor and store it in the ring. If the ring becomes full,
6
+ # the oldest item will be overwritten. To emulate a stream interface, call read_data
7
+ # to grab the last sequence number and any buffered data, call read_data again,
8
+ # passing in the sequence number and all data newer than that sequence will be
9
+ # returned, along with a new sequence to read from.
10
+ #
11
+
12
+ require 'rex/socket'
13
+
14
+ module Rex
15
+ module IO
16
+
17
+ class RingBuffer
18
+
19
+ attr_accessor :queue # The data queue, essentially an array of two-element arrays, containing a sequence and data buffer
20
+ attr_accessor :seq # The next available sequence number
21
+ attr_accessor :fd # The associated socket or IO object for this ring buffer
22
+ attr_accessor :size # The number of available slots in the queue
23
+ attr_accessor :mutex # The mutex locking access to the queue
24
+ attr_accessor :beg # The index of the earliest data fragment in the ring
25
+ attr_accessor :cur # The sequence number of the earliest data fragment in the ring
26
+ attr_accessor :monitor # The thread handle of the built-in monitor when used
27
+ attr_accessor :monitor_thread_error # :nodoc: #
28
+
29
+ #
30
+ # Create a new ring buffer
31
+ #
32
+ def initialize(socket, opts={})
33
+ self.size = opts[:size] || (1024 * 4)
34
+ self.fd = socket
35
+ self.seq = 0
36
+ self.beg = 0
37
+ self.cur = 0
38
+ self.queue = Array.new( self.size )
39
+ self.mutex = Mutex.new
40
+ end
41
+
42
+ def inspect
43
+ "#<Rex::IO::RingBuffer @size=#{size} @fd=#{fd} @seq=#{seq} @beg=#{beg} @cur=#{cur}>"
44
+ end
45
+
46
+ #
47
+ # Start the built-in monitor, not called when used in a larger framework
48
+ #
49
+ def start_monitor
50
+ self.monitor = monitor_thread if not self.monitor
51
+ end
52
+
53
+ #
54
+ # Stop the built-in monitor
55
+ #
56
+ def stop_monitor
57
+ self.monitor.kill if self.monitor
58
+ self.monitor = nil
59
+ end
60
+
61
+ #
62
+ # The built-in monitor thread (normally unused with Metasploit)
63
+ #
64
+ def monitor_thread
65
+ Thread.new do
66
+ begin
67
+ while self.fd
68
+ buff = self.fd.get_once(-1, 1.0)
69
+ next if not buff
70
+ store_data(buff)
71
+ end
72
+ rescue ::Exception => e
73
+ self.monitor_thread_error = e
74
+ end
75
+ end
76
+ end
77
+
78
+ #
79
+ # Push data back into the associated stream socket. Logging must occur
80
+ # elsewhere, this function is simply a passthrough.
81
+ #
82
+ def put(data, opts={})
83
+ self.fd.put(data, opts={})
84
+ end
85
+
86
+ #
87
+ # The clear_data method wipes the ring buffer
88
+ #
89
+ def clear_data
90
+ self.mutex.synchronize do
91
+ self.seq = 0
92
+ self.beg = 0
93
+ self.cur = 0
94
+ self.queue = Array.new( self.size )
95
+ end
96
+ end
97
+
98
+ #
99
+ # The store_data method is used to insert data into the ring buffer.
100
+ #
101
+ def store_data(data)
102
+ self.mutex.synchronize do
103
+ # self.cur points to the array index of queue containing the last item
104
+ # adding data will result in cur + 1 being used to store said data
105
+ # if cur is larger than size - 1, it will wrap back around. If cur
106
+ # is *smaller* beg, beg is increemnted to cur + 1 (and wrapped if
107
+ # necessary
108
+
109
+ loc = 0
110
+ if self.seq > 0
111
+ loc = ( self.cur + 1 ) % self.size
112
+
113
+ if loc <= self.beg
114
+ self.beg = (self.beg + 1) % self.size
115
+ end
116
+ end
117
+
118
+ self.queue[loc] = [self.seq += 1, data]
119
+ self.cur = loc
120
+ end
121
+ end
122
+
123
+ #
124
+ # The read_data method returns a two element array with the new reader cursor (a sequence number)
125
+ # and the returned data buffer (if any). A result of nil/nil indicates that no data is available
126
+ #
127
+ def read_data(ptr=nil)
128
+ self.mutex.synchronize do
129
+
130
+ # Verify that there is data in the queue
131
+ return [nil,nil] if not self.queue[self.beg]
132
+
133
+ # Configure the beginning read pointer (sequence number, not index)
134
+ ptr ||= self.queue[self.beg][0]
135
+ return [nil,nil] if not ptr
136
+
137
+ # If the pointer is below our baseline, we lost some data, so jump forward
138
+ if ptr < self.queue[self.beg][0]
139
+ ptr = self.queue[self.beg][0]
140
+ end
141
+
142
+ # Calculate how many blocks exist between the current sequence number
143
+ # and the requested pointer, this becomes the number of blocks we will
144
+ # need to read to satisfy the result. Due to the mutex block, we do
145
+ # not need to scan to find the sequence of the starting block or
146
+ # check the sequence of the ending block.
147
+ dis = self.seq - ptr
148
+
149
+ # If the requested sequnce number is less than our base pointer, it means
150
+ # that no new data is available and we should return empty.
151
+ return [nil,nil] if dis < 0
152
+
153
+ # Calculate the beginning block index and number of blocks to read
154
+ off = ptr - self.queue[self.beg][0]
155
+ set = (self.beg + off) % self.size
156
+
157
+
158
+ # Build the buffer by reading forward by the number of blocks needed
159
+ # and return the last read sequence number, plus one, as the new read
160
+ # pointer.
161
+ buff = ""
162
+ cnt = 0
163
+ lst = ptr
164
+ ptr.upto(self.seq) do |i|
165
+ block = self.queue[ (set + cnt) % self.size ]
166
+ lst,data = block[0],block[1]
167
+ buff += data
168
+ cnt += 1
169
+ end
170
+
171
+ return [lst + 1, buff]
172
+
173
+ end
174
+ end
175
+
176
+ #
177
+ # The base_sequence method returns the earliest sequence number in the queue. This is zero until
178
+ # all slots are filled and the ring rotates.
179
+ #
180
+ def base_sequence
181
+ self.mutex.synchronize do
182
+ return 0 if not self.queue[self.beg]
183
+ return self.queue[self.beg][0]
184
+ end
185
+ end
186
+
187
+ #
188
+ # The last_sequence method returns the "next" sequence number where new data will be
189
+ # available.
190
+ #
191
+ def last_sequence
192
+ self.seq
193
+ end
194
+
195
+ #
196
+ # The create_steam method assigns a IO::Socket compatible object to the ringer buffer
197
+ #
198
+ def create_stream
199
+ Stream.new(self)
200
+ end
201
+
202
+ #
203
+ # The select method returns when there is a chance of new data
204
+ # XXX: This is mostly useless and requires a rewrite to use a
205
+ # real select or notify mechanism
206
+ #
207
+ def select
208
+ ::IO.select([ self.fd ], nil, [ self.fd ], 0.10)
209
+ end
210
+
211
+ #
212
+ # The wait method blocks until new data is available
213
+ #
214
+ def wait(seq)
215
+ nseq = nil
216
+ while not nseq
217
+ nseq,data = read_data(seq)
218
+ select
219
+ end
220
+ end
221
+
222
+ #
223
+ # The wait_for method blocks until new data is available or the timeout is reached
224
+ #
225
+ def wait_for(seq,timeout=1)
226
+ begin
227
+ ::Timeout.timeout(timeout) do
228
+ wait(seq)
229
+ end
230
+ rescue ::Timeout::Error
231
+ end
232
+ end
233
+
234
+ #
235
+ # This class provides a backwards compatible "stream" socket that uses
236
+ # the parents ring buffer.
237
+ #
238
+ class Stream
239
+ attr_accessor :ring
240
+ attr_accessor :seq
241
+ attr_accessor :buff
242
+
243
+ def initialize(ring)
244
+ self.ring = ring
245
+ self.seq = ring.base_sequence
246
+ self.buff = ''
247
+ end
248
+
249
+ def read(len=nil)
250
+ if len and self.buff.length >= len
251
+ data = self.buff.slice!(0,len)
252
+ return data
253
+ end
254
+
255
+ while true
256
+ lseq, data = self.ring.read_data( self.seq )
257
+ return if not lseq
258
+
259
+ self.seq = lseq
260
+ self.buff << data
261
+ if len
262
+ if self.buff.length >= len
263
+ return self.buff.slice!(0,len)
264
+ else
265
+ IO.select(nil, nil, nil, 0.25)
266
+ next
267
+ end
268
+ end
269
+
270
+ data = self.buff
271
+ self.buff = ''
272
+
273
+ return data
274
+
275
+ # Not reached
276
+ break
277
+ end
278
+
279
+ end
280
+
281
+ def write(data)
282
+ self.ring.write(data)
283
+ end
284
+ end
285
+
286
+ end
287
+
288
+ end
289
+ end
290
+
291
+ =begin
292
+
293
+ server = Rex::Socket.create_tcp_server('LocalPort' => 0)
294
+ lport = server.getsockname[2]
295
+ client = Rex::Socket.create_tcp('PeerHost' => '127.0.0.1', 'PeerPort' => lport)
296
+ conn = server.accept
297
+
298
+ r = Rex::IO::RingBuffer.new(conn, {:size => 1024*1024})
299
+ client.put("1")
300
+ client.put("2")
301
+ client.put("3")
302
+
303
+ s,d = r.read_data
304
+
305
+ client.put("4")
306
+ client.put("5")
307
+ client.put("6")
308
+ s,d = r.read_data(s)
309
+
310
+ client.put("7")
311
+ client.put("8")
312
+ client.put("9")
313
+ s,d = r.read_data(s)
314
+
315
+ client.put("0")
316
+ s,d = r.read_data(s)
317
+
318
+ test_counter = 11
319
+ 1.upto(100) do
320
+ client.put( "X" )
321
+ test_counter += 1
322
+ end
323
+
324
+ sleep(1)
325
+
326
+ s,d = r.read_data
327
+ p s
328
+ p d
329
+
330
+ fdata = ''
331
+ File.open("/bin/ls", "rb") do |fd|
332
+ fdata = fd.read(fd.stat.size)
333
+ fdata = fdata * 10
334
+ client.put(fdata)
335
+ end
336
+
337
+ sleep(1)
338
+
339
+ s,vdata = r.read_data(s)
340
+
341
+ if vdata != fdata
342
+ puts "DATA FAILED"
343
+ else
344
+ puts "DATA VERIFIED"
345
+ end
346
+
347
+ r.clear_data
348
+
349
+ a = r.create_stream
350
+ b = r.create_stream
351
+
352
+ client.put("ABC123")
353
+ sleep(1)
354
+
355
+ p a.read
356
+ p b.read
357
+
358
+ client.put("$$$$$$")
359
+ sleep(1)
360
+
361
+ p a.read
362
+ p b.read
363
+
364
+ c = r.create_stream
365
+ p c.read
366
+
367
+ =end
368
+
369
+