rex-socket 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,76 @@
1
+ # -*- coding: binary -*-
2
+ require 'rex/socket'
3
+
4
+ module Rex
5
+ module Socket
6
+
7
+ ###
8
+ #
9
+ # This class provides an interface to enumerating a subnet with a supplied
10
+ # netmask.
11
+ #
12
+ ###
13
+ class SubnetWalker
14
+
15
+ #
16
+ # Initializes a subnet walker instance using the supplied subnet
17
+ # information.
18
+ #
19
+ def initialize(subnet, netmask)
20
+ self.subnet = Socket.resolv_to_dotted(subnet)
21
+ self.netmask = Socket.resolv_to_dotted(netmask)
22
+
23
+ reset
24
+ end
25
+
26
+ #
27
+ # Resets the subnet walker back to its original state.
28
+ #
29
+ def reset
30
+ self.curr_ip = self.subnet.split('.')
31
+ self.num_ips = (1 << (32 - Socket.net2bitmask(self.netmask).to_i))
32
+ self.curr_ip_idx = 0
33
+ end
34
+
35
+ #
36
+ # Returns the next IP address.
37
+ #
38
+ def next_ip
39
+ if (curr_ip_idx >= num_ips)
40
+ return nil
41
+ end
42
+
43
+ if (curr_ip_idx > 0)
44
+ self.curr_ip[3] = (curr_ip[3].to_i + 1) % 256
45
+ self.curr_ip[2] = (curr_ip[2].to_i + 1) % 256 if (curr_ip[3] == 0)
46
+ self.curr_ip[1] = (curr_ip[1].to_i + 1) % 256 if (curr_ip[2] == 0)
47
+ self.curr_ip[0] = (curr_ip[0].to_i + 1) % 256 if (curr_ip[1] == 0)
48
+ end
49
+
50
+ self.curr_ip_idx += 1
51
+
52
+ self.curr_ip.join('.')
53
+ end
54
+
55
+ #
56
+ # The subnet that is being enumerated.
57
+ #
58
+ attr_reader :subnet
59
+ #
60
+ # The netmask of the subnet.
61
+ #
62
+ attr_reader :netmask
63
+ #
64
+ # The total number of IPs within the subnet.
65
+ #
66
+ attr_reader :num_ips
67
+
68
+ protected
69
+
70
+ attr_writer :subnet, :netmask, :num_ips # :nodoc:
71
+ attr_accessor :curr_ip, :curr_ip_idx # :nodoc:
72
+
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,289 @@
1
+ # -*- coding: binary -*-
2
+ require 'singleton'
3
+ require 'thread'
4
+ require 'rex/socket'
5
+
6
+ module Rex
7
+ module Socket
8
+
9
+ ###
10
+ #
11
+ # This class provides a global routing table that associates subnets with Comm
12
+ # classes. Comm classes are used to instantiate objects that are tied to
13
+ # remote network entities. For example, the Local Comm class is used to
14
+ # building network connections directly from the local machine whereas, for
15
+ # instance, a Meterpreter Comm would build a local socket pair that is
16
+ # associated with a connection established by a remote entity. This can be
17
+ # seen as a uniform way of communicating with hosts through arbitrary
18
+ # channels.
19
+ #
20
+ ###
21
+ class SwitchBoard
22
+
23
+ include Singleton
24
+ include Enumerable
25
+
26
+ def initialize
27
+ @_initialized = false
28
+ end
29
+
30
+ ###
31
+ #
32
+ # This class represents a logical switch board route.
33
+ # TODO: Enable this to work with IPv6 addresses
34
+ #
35
+ ###
36
+ class Route
37
+ def initialize(subnet, netmask, comm)
38
+ self.subnet = subnet
39
+ self.netmask = netmask
40
+ self.comm = comm
41
+ self.subnet_nbo = Socket.resolv_nbo_i(subnet)
42
+ self.netmask_nbo = Socket.resolv_nbo_i(netmask)
43
+ end
44
+
45
+ #
46
+ # Sort according to bitmask
47
+ #
48
+ def <=>(other)
49
+ self.bitmask <=> other.bitmask
50
+ end
51
+
52
+ #
53
+ # Convert the netmask to a bitmask and cache it.
54
+ #
55
+ def bitmask
56
+ @_bitmask = Socket.net2bitmask(self.netmask) if (@_bitmask == nil)
57
+ @_bitmask
58
+ end
59
+
60
+ attr_reader :subnet, :netmask, :comm
61
+ attr_reader :subnet_nbo, :netmask_nbo
62
+ protected
63
+ attr_writer :subnet, :netmask, :comm
64
+ attr_writer :subnet_nbo, :netmask_nbo
65
+ end
66
+
67
+ ##
68
+ #
69
+ # Class method wrappers
70
+ #
71
+ ##
72
+
73
+ #
74
+ # Adds a route to the switch board routing table using the supplied Comm
75
+ # instance.
76
+ #
77
+ def self.add_route(subnet, mask, comm)
78
+ ret = self.instance.add_route(subnet, mask, comm)
79
+ if ret && comm.respond_to?(:routes) && comm.routes.kind_of?(Array)
80
+ comm.routes << "#{subnet}/#{mask}"
81
+ end
82
+ ret
83
+ end
84
+
85
+ #
86
+ # Removes a route from the switch board routing table for the supplied
87
+ # subnet routing through the supplied Comm instance.
88
+ #
89
+ def self.remove_route(subnet, mask, comm)
90
+ ret = self.instance.remove_route(subnet, mask, comm)
91
+ if ret && comm.respond_to?(:routes) && comm.routes.kind_of?(Array)
92
+ comm.routes.delete "#{subnet}/#{mask}"
93
+ end
94
+ ret
95
+ end
96
+
97
+ #
98
+ # Flush all the routes from the switch board routing table.
99
+ #
100
+ def self.flush_routes
101
+ ret = self.instance.flush_routes
102
+ end
103
+
104
+ #
105
+ # Enumerate each route in the routing table.
106
+ #
107
+ def self.each(&block)
108
+ self.instance.each(&block)
109
+ end
110
+
111
+ #
112
+ # Returns the array of routes.
113
+ #
114
+ def self.routes
115
+ self.instance.routes
116
+ end
117
+
118
+ def self.route_exists?(subnet, mask)
119
+ self.instance.route_exists?(subnet, mask)
120
+ end
121
+
122
+ #
123
+ # Returns the Comm instance that should be used for the supplied address.
124
+ # If no comm can be found, the default Local Comm is returned.
125
+ #
126
+ def self.best_comm(addr)
127
+ self.instance.best_comm(addr)
128
+ end
129
+
130
+ #
131
+ # Removes all routes that go through the supplied Comm.
132
+ #
133
+ def self.remove_by_comm(comm)
134
+ self.instance.remove_by_comm(comm)
135
+ end
136
+
137
+ ##
138
+ #
139
+ # Instance methods
140
+ #
141
+ ##
142
+
143
+ #
144
+ # Adds a route for a given subnet and netmask destined through a given comm
145
+ # instance.
146
+ #
147
+ def add_route(subnet, mask, comm)
148
+ # If a bitmask was supplied, convert it.
149
+ netmask = (mask.to_s =~ /^\d+$/) ? Rex::Socket.bit2netmask(mask.to_i) : mask
150
+ rv = true
151
+
152
+ _init
153
+
154
+ mutex.synchronize {
155
+ # If the route already exists, return false to the caller.
156
+ if (route_exists?(subnet, netmask) == false)
157
+ self.routes << Route.new(subnet, netmask, comm)
158
+ else
159
+ rv = false
160
+ end
161
+ }
162
+
163
+ rv
164
+ end
165
+
166
+ #
167
+ # Removes a route for a given subnet and netmask destined through a given
168
+ # comm instance.
169
+ #
170
+ def remove_route(subnet, mask, comm)
171
+ # If a bitmask was supplied, convert it.
172
+ netmask = (mask.to_s =~ /^\d+$/) ? Rex::Socket.bit2netmask(mask.to_i) : mask
173
+ rv = false
174
+
175
+ _init
176
+
177
+ mutex.synchronize {
178
+ self.routes.delete_if { |route|
179
+ if (route.subnet == subnet and route.netmask == netmask and route.comm == comm)
180
+ rv = true
181
+ else
182
+ false
183
+ end
184
+ }
185
+ }
186
+
187
+ rv
188
+ end
189
+
190
+ #
191
+ # Flushes all established routes.
192
+ #
193
+ def flush_routes
194
+ _init
195
+
196
+ # Remove each of the individual routes so the comms don't think they're
197
+ # still routing after a flush.
198
+ self.routes.each { |r|
199
+ if r.comm.respond_to? :routes
200
+ r.comm.routes.delete("#{r.subnet}/#{r.netmask}")
201
+ end
202
+ }
203
+ # Re-initialize to an empty array
204
+ self.routes = Array.new
205
+ end
206
+
207
+ #
208
+ # Checks to see if a route already exists for the supplied subnet and
209
+ # netmask.
210
+ #
211
+ def route_exists?(subnet, netmask)
212
+ each { |route|
213
+ return true if (route.subnet == subnet and route.netmask == netmask)
214
+ }
215
+
216
+ false
217
+ end
218
+
219
+ #
220
+ # Enumerates each entry in the routing table.
221
+ #
222
+ def each(&block)
223
+ _init
224
+
225
+ routes.each(&block)
226
+ end
227
+
228
+ #
229
+ # Finds the best possible comm for the supplied target address.
230
+ #
231
+ def best_comm(addr)
232
+
233
+ addr_nbo = Socket.resolv_nbo_i(addr)
234
+ comm = nil
235
+ msb = 0
236
+
237
+ each { |route|
238
+ if ((route.subnet_nbo & route.netmask_nbo) ==
239
+ (addr_nbo & route.netmask_nbo))
240
+ if (route.bitmask >= msb)
241
+ comm = route.comm
242
+ msb = route.bitmask
243
+ end
244
+ end
245
+ }
246
+
247
+ comm
248
+ end
249
+
250
+ #
251
+ # Remove all routes that go through the supplied comm.
252
+ #
253
+ def remove_by_comm(comm)
254
+ _init
255
+ mutex.synchronize {
256
+ routes.delete_if { |route|
257
+ route.comm == comm
258
+ }
259
+ }
260
+ end
261
+
262
+ #
263
+ # The routes array.
264
+ #
265
+ attr_reader :routes
266
+ #
267
+ # The mutex protecting the routes array.
268
+ #
269
+ attr_reader :mutex
270
+
271
+ protected
272
+
273
+ attr_writer :routes, :mutex # :nodoc:
274
+
275
+ #
276
+ # Initializes the underlying stuff.
277
+ #
278
+ def _init
279
+ if (@_initialized != true)
280
+ @_initialized = true
281
+ self.routes = Array.new
282
+ self.mutex = Mutex.new
283
+ end
284
+ end
285
+
286
+ end
287
+
288
+ end
289
+ end
@@ -0,0 +1,79 @@
1
+ # -*- coding: binary -*-
2
+ require 'rex/socket'
3
+ require 'rex/io/stream'
4
+
5
+ ###
6
+ #
7
+ # This class provides methods for interacting with a TCP client connection.
8
+ #
9
+ ###
10
+ module Rex::Socket::Tcp
11
+
12
+ include Rex::Socket
13
+ include Rex::IO::Stream
14
+
15
+ ##
16
+ #
17
+ # Factory
18
+ #
19
+ ##
20
+
21
+ #
22
+ # Creates the client using the supplied hash.
23
+ #
24
+ # @see create_param
25
+ # @see Rex::Socket::Parameters.from_hash
26
+ def self.create(hash = {})
27
+ hash['Proto'] = 'tcp'
28
+ self.create_param(Rex::Socket::Parameters.from_hash(hash))
29
+ end
30
+
31
+ #
32
+ # Wrapper around the base socket class' creation method that automatically
33
+ # sets the parameter's protocol to TCP.
34
+ #
35
+ def self.create_param(param)
36
+ param.proto = 'tcp'
37
+ Rex::Socket.create_param(param)
38
+ end
39
+
40
+ ##
41
+ #
42
+ # Stream mixin implementations
43
+ #
44
+ ##
45
+
46
+ #
47
+ # Calls shutdown on the TCP connection.
48
+ #
49
+ def shutdown(how = ::Socket::SHUT_RDWR)
50
+ begin
51
+ return (super(how) == 0)
52
+ rescue ::Exception
53
+ end
54
+ end
55
+
56
+ #
57
+ # Returns peer information (host + port) in host:port format.
58
+ #
59
+ def peerinfo
60
+ if (pi = getpeername_as_array)
61
+ return pi[1] + ':' + pi[2].to_s
62
+ end
63
+ end
64
+
65
+ #
66
+ # Returns local information (host + port) in host:port format.
67
+ #
68
+ def localinfo
69
+ if (pi = getlocalname)
70
+ return pi[1] + ':' + pi[2].to_s
71
+ end
72
+ end
73
+
74
+ # returns socket type
75
+ def type?
76
+ return 'tcp'
77
+ end
78
+
79
+ end
@@ -0,0 +1,70 @@
1
+ # -*- coding: binary -*-
2
+ require 'rex/socket'
3
+ require 'rex/socket/tcp'
4
+ require 'rex/io/stream_server'
5
+
6
+ ###
7
+ #
8
+ # This class provides methods for interacting with a TCP server. It
9
+ # implements the Rex::IO::StreamServer interface.
10
+ #
11
+ ###
12
+ module Rex::Socket::TcpServer
13
+
14
+ include Rex::Socket
15
+ include Rex::IO::StreamServer
16
+
17
+ ##
18
+ #
19
+ # Factory
20
+ #
21
+ ##
22
+
23
+ #
24
+ # Creates the server using the supplied hash.
25
+ #
26
+ def self.create(hash = {})
27
+ hash['Proto'] = 'tcp'
28
+ hash['Server'] = true
29
+ self.create_param(Rex::Socket::Parameters.from_hash(hash))
30
+ end
31
+
32
+ #
33
+ # Wrapper around the base class' creation method that automatically sets
34
+ # the parameter's protocol to TCP and sets the server flag to true.
35
+ #
36
+ def self.create_param(param)
37
+ param.proto = 'tcp'
38
+ param.server = true
39
+ Rex::Socket.create_param(param)
40
+ end
41
+
42
+ #
43
+ # Accepts a child connection.
44
+ #
45
+ def accept(opts = {})
46
+ t = super()
47
+
48
+ # jRuby compatibility
49
+ if t.respond_to?('[]')
50
+ t = t[0]
51
+ end
52
+
53
+ if (t)
54
+ t.extend(Rex::Socket::Tcp)
55
+ t.context = self.context
56
+
57
+ pn = t.getpeername_as_array
58
+
59
+ # We hit a "getpeername(2)" from Ruby
60
+ return nil unless pn
61
+
62
+ t.peerhost = pn[1]
63
+ t.peerport = pn[2]
64
+ end
65
+
66
+ t
67
+ end
68
+
69
+ end
70
+