rex-socket 0.1.0
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 +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/README.md +32 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/rex/socket.rb +798 -0
- data/lib/rex/socket/comm.rb +120 -0
- data/lib/rex/socket/comm/local.rb +529 -0
- data/lib/rex/socket/ip.rb +132 -0
- data/lib/rex/socket/parameters.rb +372 -0
- data/lib/rex/socket/range_walker.rb +470 -0
- data/lib/rex/socket/ssh_factory.rb +46 -0
- data/lib/rex/socket/ssl_tcp.rb +374 -0
- data/lib/rex/socket/ssl_tcp_server.rb +220 -0
- data/lib/rex/socket/subnet_walker.rb +76 -0
- data/lib/rex/socket/switch_board.rb +289 -0
- data/lib/rex/socket/tcp.rb +79 -0
- data/lib/rex/socket/tcp_server.rb +70 -0
- data/lib/rex/socket/udp.rb +165 -0
- data/lib/rex/socket/version.rb +5 -0
- data/lib/rex/socket/x509_certificate.rb +92 -0
- data/rex-socket.gemspec +30 -0
- metadata +205 -0
- metadata.gz.sig +2 -0
@@ -0,0 +1,132 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
require 'rex/socket'
|
3
|
+
|
4
|
+
###
|
5
|
+
#
|
6
|
+
# This class provides methods for interacting with a IP socket.
|
7
|
+
#
|
8
|
+
###
|
9
|
+
module Rex::Socket::Ip
|
10
|
+
|
11
|
+
include Rex::Socket
|
12
|
+
|
13
|
+
##
|
14
|
+
#
|
15
|
+
# Factory
|
16
|
+
#
|
17
|
+
##
|
18
|
+
|
19
|
+
#
|
20
|
+
# Creates the client using the supplied hash.
|
21
|
+
#
|
22
|
+
def self.create(hash = {})
|
23
|
+
hash['Proto'] = 'ip'
|
24
|
+
self.create_param(Rex::Socket::Parameters.from_hash(hash))
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# Wrapper around the base socket class' creation method that automatically
|
29
|
+
# sets the parameter's protocol to IP.
|
30
|
+
#
|
31
|
+
def self.create_param(param)
|
32
|
+
param.proto = 'ip'
|
33
|
+
Rex::Socket.create_param(param)
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
#
|
38
|
+
# IP connected state methods
|
39
|
+
#
|
40
|
+
##
|
41
|
+
|
42
|
+
#
|
43
|
+
# Write the supplied datagram to the connected IP socket.
|
44
|
+
#
|
45
|
+
def write(gram)
|
46
|
+
raise RuntimeError, "IP sockets must use sendto(), not write()"
|
47
|
+
end
|
48
|
+
|
49
|
+
alias put write
|
50
|
+
|
51
|
+
#
|
52
|
+
# Read a datagram from the IP socket.
|
53
|
+
#
|
54
|
+
def read(length = 65535)
|
55
|
+
raise RuntimeError, "IP sockets must use recvfrom(), not read()"
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
#
|
60
|
+
# IP non-connected state methods
|
61
|
+
#
|
62
|
+
##
|
63
|
+
|
64
|
+
#
|
65
|
+
# Sends a datagram to the supplied host:port with optional flags.
|
66
|
+
#
|
67
|
+
def sendto(gram, peerhost, flags = 0)
|
68
|
+
dest = ::Socket.pack_sockaddr_in(0, peerhost)
|
69
|
+
|
70
|
+
# Some BSDs require byteswap for len and offset
|
71
|
+
if(
|
72
|
+
Rex::Compat.is_freebsd or
|
73
|
+
Rex::Compat.is_netbsd or
|
74
|
+
Rex::Compat.is_bsdi or
|
75
|
+
Rex::Compat.is_macosx
|
76
|
+
)
|
77
|
+
gram=gram.dup
|
78
|
+
# Note that these are *intentionally* host order for BSD support
|
79
|
+
gram[2,2]=gram[2,2].unpack("n").pack("s")
|
80
|
+
gram[6,2]=gram[6,2].unpack("n").pack("s")
|
81
|
+
end
|
82
|
+
|
83
|
+
begin
|
84
|
+
send(gram, flags, dest)
|
85
|
+
rescue ::Errno::EHOSTUNREACH,::Errno::ENETDOWN,::Errno::ENETUNREACH,::Errno::ENETRESET,::Errno::EHOSTDOWN,::Errno::EACCES,::Errno::EINVAL,::Errno::EADDRNOTAVAIL
|
86
|
+
return nil
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# Receives a datagram and returns the data and host of the requestor
|
93
|
+
# as [ data, host ].
|
94
|
+
#
|
95
|
+
def recvfrom(length = 65535, timeout=def_read_timeout)
|
96
|
+
begin
|
97
|
+
if ((rv = ::IO.select([ fd ], nil, nil, timeout)) and
|
98
|
+
(rv[0]) and (rv[0][0] == fd)
|
99
|
+
)
|
100
|
+
data, saddr = super(length)
|
101
|
+
af, host = Rex::Socket.from_sockaddr(saddr)
|
102
|
+
|
103
|
+
return [ data, host ]
|
104
|
+
else
|
105
|
+
return [ '', nil ]
|
106
|
+
end
|
107
|
+
rescue Exception
|
108
|
+
return [ '', nil ]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
#
|
113
|
+
# Calls recvfrom and only returns the data
|
114
|
+
#
|
115
|
+
def get(timeout=nil)
|
116
|
+
data, saddr = recvfrom(65535, timeout)
|
117
|
+
return data
|
118
|
+
end
|
119
|
+
|
120
|
+
#
|
121
|
+
# The default number of seconds to wait for a read operation to timeout.
|
122
|
+
#
|
123
|
+
def def_read_timeout
|
124
|
+
10
|
125
|
+
end
|
126
|
+
|
127
|
+
def type?
|
128
|
+
return 'ip'
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
@@ -0,0 +1,372 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
require 'rex/socket'
|
3
|
+
|
4
|
+
###
|
5
|
+
#
|
6
|
+
# This class represents the set of parameters that are used to create
|
7
|
+
# a socket, whether it be a server or client socket.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# nsock = Rex::Socket::Tcp.create(
|
11
|
+
# 'PeerHost' => opts['RHOST'] || rhost,
|
12
|
+
# 'PeerPort' => (opts['RPORT'] || rport).to_i,
|
13
|
+
# 'LocalHost' => opts['CHOST'] || chost || "0.0.0.0",
|
14
|
+
# 'LocalPort' => (opts['CPORT'] || cport || 0).to_i,
|
15
|
+
# 'SSL' => dossl,
|
16
|
+
# 'SSLVersion'=> opts['SSLVersion'] || ssl_version,
|
17
|
+
# 'Proxies' => proxies,
|
18
|
+
# 'Timeout' => (opts['ConnectTimeout'] || connect_timeout || 10).to_i,
|
19
|
+
# 'Context' =>
|
20
|
+
# {
|
21
|
+
# 'Msf' => framework,
|
22
|
+
# 'MsfExploit' => self,
|
23
|
+
# })
|
24
|
+
#
|
25
|
+
###
|
26
|
+
class Rex::Socket::Parameters
|
27
|
+
|
28
|
+
##
|
29
|
+
#
|
30
|
+
# Factory
|
31
|
+
#
|
32
|
+
##
|
33
|
+
|
34
|
+
#
|
35
|
+
# Creates an instance of the Parameters class using the supplied hash.
|
36
|
+
#
|
37
|
+
def self.from_hash(hash)
|
38
|
+
return self.new(hash)
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
#
|
43
|
+
# Constructor
|
44
|
+
#
|
45
|
+
##
|
46
|
+
|
47
|
+
#
|
48
|
+
# Initializes the attributes from the supplied hash. The following hash
|
49
|
+
# keys can be specified.
|
50
|
+
#
|
51
|
+
# @option hash [String] 'PeerHost' The remote host to connect to
|
52
|
+
# @option hash [String] 'PeerAddr' (alias for 'PeerHost')
|
53
|
+
# @option hash [Fixnum] 'PeerPort' The remote port to connect to
|
54
|
+
# @option hash [String] 'LocalHost' The local host to communicate from, if any
|
55
|
+
# @option hash [String] 'LocalPort' The local port to communicate from, if any
|
56
|
+
# @option hash [Bool] 'Bool' Create a bare socket
|
57
|
+
# @option hash [Bool] 'Server' Whether or not this should be a server
|
58
|
+
# @option hash [Bool] 'SSL' Whether or not SSL should be used
|
59
|
+
# @option hash [OpenSSL::SSL::SSLContext] 'SSLContext' Use a pregenerated SSL Context
|
60
|
+
# @option hash [String] 'SSLVersion' Specify Auto, SSL2, SSL3, or TLS1 (Auto is
|
61
|
+
# default)
|
62
|
+
# @option hash [String] 'SSLCert' A file containing an SSL certificate (for
|
63
|
+
# server sockets)
|
64
|
+
# @option hash [String] 'SSLCipher' see {#ssl_cipher}
|
65
|
+
# @option hash [Bool] 'SSLCompression' enable SSL-level compression where available
|
66
|
+
# @option hash [String] 'SSLVerifyMode' SSL certificate verification
|
67
|
+
# mechanism. One of 'NONE' (default), 'CLIENT_ONCE', 'FAIL_IF_NO_PEER_CERT ', 'PEER'
|
68
|
+
# @option hash [String] 'Proxies' List of proxies to use.
|
69
|
+
# @option hash [String] 'Proto' The underlying protocol to use.
|
70
|
+
# @option hash [String] 'IPv6' Force the use of IPv6.
|
71
|
+
# @option hash [String] 'Comm' The underlying {Comm} object to use to create
|
72
|
+
# the socket for this parameter set.
|
73
|
+
# @option hash [Hash] 'Context' A context hash that can allow users of
|
74
|
+
# this parameter class instance to determine who is responsible for
|
75
|
+
# requesting that a socket be created.
|
76
|
+
# @option hash [String] 'Retries' The number of times a connection should be
|
77
|
+
# retried.
|
78
|
+
# @option hash [Fixnum] 'Timeout' The number of seconds before a connection
|
79
|
+
# should time out
|
80
|
+
def initialize(hash)
|
81
|
+
if (hash['PeerHost'])
|
82
|
+
self.peerhost = hash['PeerHost']
|
83
|
+
elsif (hash['PeerAddr'])
|
84
|
+
self.peerhost = hash['PeerAddr']
|
85
|
+
else
|
86
|
+
self.peerhost = nil
|
87
|
+
end
|
88
|
+
|
89
|
+
if (hash['LocalHost'])
|
90
|
+
self.localhost = hash['LocalHost']
|
91
|
+
elsif (hash['LocalAddr'])
|
92
|
+
self.localhost = hash['LocalAddr']
|
93
|
+
else
|
94
|
+
self.localhost = '0.0.0.0'
|
95
|
+
end
|
96
|
+
|
97
|
+
if (hash['PeerPort'])
|
98
|
+
self.peerport = hash['PeerPort'].to_i
|
99
|
+
else
|
100
|
+
self.peerport = 0
|
101
|
+
end
|
102
|
+
|
103
|
+
if (hash['LocalPort'])
|
104
|
+
self.localport = hash['LocalPort'].to_i
|
105
|
+
else
|
106
|
+
self.localport = 0
|
107
|
+
end
|
108
|
+
|
109
|
+
if (hash['Bare'])
|
110
|
+
self.bare = hash['Bare']
|
111
|
+
else
|
112
|
+
self.bare = false
|
113
|
+
end
|
114
|
+
|
115
|
+
if (hash['SSL'] and hash['SSL'].to_s =~ /^(t|y|1)/i)
|
116
|
+
self.ssl = true
|
117
|
+
else
|
118
|
+
self.ssl = false
|
119
|
+
end
|
120
|
+
|
121
|
+
if hash['SSLContext']
|
122
|
+
self.sslctx = hash['SSLContext']
|
123
|
+
end
|
124
|
+
|
125
|
+
supported_ssl_versions = ['Auto', 'SSL2', 'SSL23', 'TLS1', 'SSL3', :Auto, :SSLv2, :SSLv3, :SSLv23, :TLSv1]
|
126
|
+
if (hash['SSLVersion'] and supported_ssl_versions.include? hash['SSLVersion'])
|
127
|
+
self.ssl_version = hash['SSLVersion']
|
128
|
+
end
|
129
|
+
|
130
|
+
supported_ssl_verifiers = %W{CLIENT_ONCE FAIL_IF_NO_PEER_CERT NONE PEER}
|
131
|
+
if (hash['SSLVerifyMode'] and supported_ssl_verifiers.include? hash['SSLVerifyMode'])
|
132
|
+
self.ssl_verify_mode = hash['SSLVerifyMode']
|
133
|
+
end
|
134
|
+
|
135
|
+
if hash['SSLCompression']
|
136
|
+
self.ssl_compression = hash['SSLCompression']
|
137
|
+
end
|
138
|
+
|
139
|
+
if (hash['SSLCipher'])
|
140
|
+
self.ssl_cipher = hash['SSLCipher']
|
141
|
+
end
|
142
|
+
|
143
|
+
if (hash['SSLCert'] and ::File.file?(hash['SSLCert']))
|
144
|
+
begin
|
145
|
+
self.ssl_cert = ::File.read(hash['SSLCert'])
|
146
|
+
rescue ::Exception => e
|
147
|
+
elog("Failed to read cert: #{e.class}: #{e}", LogSource)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
if hash['Proxies']
|
152
|
+
self.proxies = hash['Proxies'].split('-').map{|a| a.strip}.map{|a| a.split(':').map{|b| b.strip}}
|
153
|
+
end
|
154
|
+
|
155
|
+
# The protocol this socket will be using
|
156
|
+
if (hash['Proto'])
|
157
|
+
self.proto = hash['Proto'].downcase
|
158
|
+
else
|
159
|
+
self.proto = 'tcp'
|
160
|
+
end
|
161
|
+
|
162
|
+
# Whether or not the socket should be a server
|
163
|
+
self.server = hash['Server'] || false
|
164
|
+
|
165
|
+
# The communication subsystem to use to create the socket
|
166
|
+
self.comm = hash['Comm']
|
167
|
+
|
168
|
+
# The context that was passed in, if any.
|
169
|
+
self.context = hash['Context'] || {}
|
170
|
+
|
171
|
+
# If no comm was supplied, try to use the comm that is best fit to
|
172
|
+
# handle the provided host based on the current routing table.
|
173
|
+
if( self.server )
|
174
|
+
if (self.comm == nil and self.localhost)
|
175
|
+
self.comm = Rex::Socket::SwitchBoard.best_comm(self.localhost)
|
176
|
+
end
|
177
|
+
else
|
178
|
+
if (self.comm == nil and self.peerhost)
|
179
|
+
self.comm = Rex::Socket::SwitchBoard.best_comm(self.peerhost)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
# If we still haven't found a comm, we default to the local comm.
|
184
|
+
self.comm = Rex::Socket::Comm::Local if (self.comm == nil)
|
185
|
+
|
186
|
+
# If we are a UDP server, turn off the server flag as it was only set when
|
187
|
+
# creating the UDP socket in order to avail of the switch board above.
|
188
|
+
if( self.server and self.proto == 'udp' )
|
189
|
+
self.server = false
|
190
|
+
end
|
191
|
+
|
192
|
+
# The number of connection retries to make (client only)
|
193
|
+
if hash['Retries']
|
194
|
+
self.retries = hash['Retries'].to_i
|
195
|
+
else
|
196
|
+
self.retries = 0
|
197
|
+
end
|
198
|
+
|
199
|
+
# The number of seconds before a connect attempt times out (client only)
|
200
|
+
if hash['Timeout']
|
201
|
+
self.timeout = hash['Timeout'].to_i
|
202
|
+
else
|
203
|
+
self.timeout = 5
|
204
|
+
end
|
205
|
+
|
206
|
+
# Whether to force IPv6 addressing
|
207
|
+
self.v6 = hash['IPv6'] || false
|
208
|
+
end
|
209
|
+
|
210
|
+
##
|
211
|
+
#
|
212
|
+
# Conditionals
|
213
|
+
#
|
214
|
+
##
|
215
|
+
|
216
|
+
#
|
217
|
+
# Returns true if this represents parameters for a server.
|
218
|
+
#
|
219
|
+
def server?
|
220
|
+
return (server == true)
|
221
|
+
end
|
222
|
+
|
223
|
+
#
|
224
|
+
# Returns true if this represents parameters for a client.
|
225
|
+
#
|
226
|
+
def client?
|
227
|
+
return (server == false)
|
228
|
+
end
|
229
|
+
|
230
|
+
#
|
231
|
+
# Returns true if the protocol for the parameters is TCP.
|
232
|
+
#
|
233
|
+
def tcp?
|
234
|
+
return (proto == 'tcp')
|
235
|
+
end
|
236
|
+
|
237
|
+
#
|
238
|
+
# Returns true if the protocol for the parameters is UDP.
|
239
|
+
#
|
240
|
+
def udp?
|
241
|
+
return (proto == 'udp')
|
242
|
+
end
|
243
|
+
|
244
|
+
#
|
245
|
+
# Returns true if the protocol for the parameters is IP.
|
246
|
+
#
|
247
|
+
def ip?
|
248
|
+
return (proto == 'ip')
|
249
|
+
end
|
250
|
+
|
251
|
+
#
|
252
|
+
# Returns true if the socket is a bare socket that does not inherit from
|
253
|
+
# any extended Rex classes.
|
254
|
+
#
|
255
|
+
def bare?
|
256
|
+
return (bare == true)
|
257
|
+
end
|
258
|
+
|
259
|
+
#
|
260
|
+
# Returns true if SSL has been requested.
|
261
|
+
#
|
262
|
+
def ssl?
|
263
|
+
return ssl
|
264
|
+
end
|
265
|
+
|
266
|
+
#
|
267
|
+
# Returns true if IPv6 has been enabled
|
268
|
+
#
|
269
|
+
def v6?
|
270
|
+
return v6
|
271
|
+
end
|
272
|
+
|
273
|
+
|
274
|
+
##
|
275
|
+
#
|
276
|
+
# Attributes
|
277
|
+
#
|
278
|
+
##
|
279
|
+
|
280
|
+
# The remote host information, equivalent to the PeerHost parameter hash
|
281
|
+
# key.
|
282
|
+
# @return [String]
|
283
|
+
attr_accessor :peerhost
|
284
|
+
|
285
|
+
# The remote port. Equivalent to the PeerPort parameter hash key.
|
286
|
+
# @return [Fixnum]
|
287
|
+
attr_accessor :peerport
|
288
|
+
|
289
|
+
# The local host. Equivalent to the LocalHost parameter hash key.
|
290
|
+
# @return [String]
|
291
|
+
attr_accessor :localhost
|
292
|
+
|
293
|
+
# The local port. Equivalent to the LocalPort parameter hash key.
|
294
|
+
# @return [Fixnum]
|
295
|
+
attr_accessor :localport
|
296
|
+
|
297
|
+
# The protocol to to use, such as TCP. Equivalent to the Proto parameter
|
298
|
+
# hash key.
|
299
|
+
# @return [String]
|
300
|
+
attr_accessor :proto
|
301
|
+
|
302
|
+
# Whether or not this is a server. Equivalent to the Server parameter
|
303
|
+
# hash key.
|
304
|
+
# @return [Bool]
|
305
|
+
attr_accessor :server
|
306
|
+
|
307
|
+
# The {Comm} instance that should be used to create the underlying socket.
|
308
|
+
# @return [Comm]
|
309
|
+
attr_accessor :comm
|
310
|
+
|
311
|
+
# The context hash that was passed in to the structure. (default: {})
|
312
|
+
# @return [Hash]
|
313
|
+
attr_accessor :context
|
314
|
+
|
315
|
+
# The number of attempts that should be made.
|
316
|
+
# @return [Fixnum]
|
317
|
+
attr_accessor :retries
|
318
|
+
|
319
|
+
# The number of seconds before a connection attempt should time out.
|
320
|
+
# @return [Fixnum]
|
321
|
+
attr_accessor :timeout
|
322
|
+
|
323
|
+
# Whether or not this is a bare (non-extended) socket instance that should
|
324
|
+
# be created.
|
325
|
+
# @return [Bool]
|
326
|
+
attr_accessor :bare
|
327
|
+
|
328
|
+
# Whether or not SSL should be used to wrap the connection.
|
329
|
+
# @return [Bool]
|
330
|
+
attr_accessor :ssl
|
331
|
+
|
332
|
+
# Pre configured SSL Context to use
|
333
|
+
# @return [OpenSSL::SSL::SSLContext]
|
334
|
+
attr_accessor :sslctx
|
335
|
+
|
336
|
+
# What version of SSL to use (Auto, SSL2, SSL3, SSL23, TLS1)
|
337
|
+
# @return [String,Symbol]
|
338
|
+
attr_accessor :ssl_version
|
339
|
+
|
340
|
+
# What specific SSL Cipher(s) to use, may be a string containing the cipher
|
341
|
+
# name or an array of strings containing cipher names e.g.
|
342
|
+
# ["DHE-RSA-AES256-SHA", "DHE-DSS-AES256-SHA"]
|
343
|
+
# @return [String,Array]
|
344
|
+
attr_accessor :ssl_cipher
|
345
|
+
|
346
|
+
# The SSL certificate, in pem format, stored as a string. See
|
347
|
+
# {Rex::Socket::SslTcpServer#makessl}
|
348
|
+
# @return [String]
|
349
|
+
attr_accessor :ssl_cert
|
350
|
+
|
351
|
+
# Enables SSL/TLS-level compression
|
352
|
+
# @return [Bool]
|
353
|
+
attr_accessor :ssl_compression
|
354
|
+
|
355
|
+
#
|
356
|
+
# The SSL context verification mechanism
|
357
|
+
#
|
358
|
+
attr_accessor :ssl_verify_mode
|
359
|
+
|
360
|
+
#
|
361
|
+
# Whether we should use IPv6
|
362
|
+
# @return [Bool]
|
363
|
+
attr_accessor :v6
|
364
|
+
|
365
|
+
|
366
|
+
# List of proxies to use
|
367
|
+
# @return [String]
|
368
|
+
attr_accessor :proxies
|
369
|
+
|
370
|
+
alias peeraddr peerhost
|
371
|
+
alias localaddr localhost
|
372
|
+
end
|