Class: Rex::Proto::RFB::Client
- Inherits:
-
Object
- Object
- Rex::Proto::RFB::Client
show all
- Includes:
- Constants
- Defined in:
- lib/rex/proto/rfb/client.rb
Constant Summary
Constants included
from Constants
Rex::Proto::RFB::Constants::DefaultPort, Rex::Proto::RFB::Constants::MajorVersions
Instance Attribute Summary collapse
Instance Method Summary
collapse
Constructor Details
#initialize(sock, opts = {}) ⇒ Client
Returns a new instance of Client.
21
22
23
24
25
26
27
28
29
|
# File 'lib/rex/proto/rfb/client.rb', line 21
def initialize(sock, opts = {})
@sock = sock
@opts = opts
@banner = nil
@majver = -1
@minver = -1
@auth_types = []
end
|
Instance Attribute Details
#auth_types ⇒ Object
Returns the value of attribute auth_types.
252
253
254
|
# File 'lib/rex/proto/rfb/client.rb', line 252
def auth_types
@auth_types
end
|
#error ⇒ Object
Returns the value of attribute error.
252
253
254
|
# File 'lib/rex/proto/rfb/client.rb', line 252
def error
@error
end
|
#majver ⇒ Object
Returns the value of attribute majver.
252
253
254
|
# File 'lib/rex/proto/rfb/client.rb', line 252
def majver
@majver
end
|
#minver ⇒ Object
Returns the value of attribute minver.
252
253
254
|
# File 'lib/rex/proto/rfb/client.rb', line 252
def minver
@minver
end
|
#view_only ⇒ Object
Returns the value of attribute view_only.
252
253
254
|
# File 'lib/rex/proto/rfb/client.rb', line 252
def view_only
@view_only
end
|
Instance Method Details
#authenticate(password = nil) ⇒ Object
92
93
94
|
# File 'lib/rex/proto/rfb/client.rb', line 92
def authenticate(password = nil)
authenticate_with_user(nil, password)
end
|
#authenticate_with_type(type, username = nil, password = nil) ⇒ Object
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
# File 'lib/rex/proto/rfb/client.rb', line 101
def authenticate_with_type(type, username = nil, password = nil)
return false if !type
case type
when AuthType::None
when AuthType::VNC
return false if !negotiate_vnc_auth(password)
when AuthType::ARD
return false if !negotiate_ard_auth(username, password)
end
result = @sock.get_once(4)
if !result
@error = 'Unable to read auth result'
return false
end
result = result.unpack('N').first
case result
when 0
return true
when 1
if @minver >= 8
msg = read_error_message
@error = "Authentication failed: #{msg}"
else
@error = 'Authentication failed'
end
when 2
@error = 'Too many authentication attempts'
else
@error = "Unknown authentication result: #{result}"
end
false
end
|
#authenticate_with_user(username = nil, password = nil) ⇒ Object
96
97
98
99
|
# File 'lib/rex/proto/rfb/client.rb', line 96
def authenticate_with_user(username = nil, password = nil)
type = negotiate_authentication
authenticate_with_type(type, username, password)
end
|
#connect(password = nil) ⇒ Object
76
77
78
79
80
81
82
|
# File 'lib/rex/proto/rfb/client.rb', line 76
def connect(password = nil)
return false if !handshake
return false if !authenticate(password)
return false if !send_client_init
true
end
|
#handshake ⇒ Object
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
# File 'lib/rex/proto/rfb/client.rb', line 39
def handshake
@banner = @sock.get_once(12)
if !@banner
@error = 'Unable to obtain banner from server'
return false
end
if @banner =~ /RFB ([0-9]{3})\.([0-9]{3})/
@majver = Regexp.last_match(1).to_i
unless Constants::MajorVersions.include?(@majver)
@error = "Invalid major version number: #{@majver}"
return false
end
else
@error = "Invalid RFB banner: #{@banner}"
return false
end
@minver = Regexp.last_match(2).to_i
our_ver = format("RFB %03d.%03d\n", 3, @minver < 3 ? 8 : @minver)
@sock.put(our_ver)
true
end
|
#negotiate_ard_auth(username = nil, password = nil) ⇒ Object
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
|
# File 'lib/rex/proto/rfb/client.rb', line 219
def negotiate_ard_auth(username = nil, password = nil)
generator = @sock.get_once(2)
if !generator or generator.length != 2
@error = 'Unable to obtain ARD challenge: invalid generator value'
return false
end
generator = generator.unpack('n').first
key_length = @sock.get_once(2)
if !key_length or key_length.length != 2
@error = 'Unable to obtain ARD challenge: invalid key length'
return false
end
key_length = key_length.unpack('n').first
prime_modulus = @sock.get_once(key_length)
if !prime_modulus or prime_modulus.length != key_length
@error = 'Unable to obtain ARD challenge: invalid prime modulus'
return false
end
peer_public_key = @sock.get_once(key_length)
if !peer_public_key or peer_public_key.length != key_length
@error = 'Unable to obtain ARD challenge: invalid public key'
return false
end
response = Cipher.encrypt_ard(username, password, generator, key_length, prime_modulus, peer_public_key)
@sock.put(response)
true
end
|
#negotiate_authentication ⇒ Object
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
|
# File 'lib/rex/proto/rfb/client.rb', line 145
def negotiate_authentication
if @minver < 7
buf = @sock.get_once(4)
if !buf
@error = 'Unable to obtain requested authentication method'
return nil
end
@auth_types = buf.unpack('N')
if !@auth_types or @auth_types.first == 0
msg = read_error_message
@error = "No authentication types available: #{msg}"
return nil
end
else
buf = @sock.get_once(1)
if !buf
@error = 'Unable to obtain supported authentication method count'
return nil
end
num_types = buf.unpack('C').first
if (num_types == 0)
msg = read_error_message
@error = "No authentication types available: #{msg}"
return nil
end
buf = @sock.get_once(num_types)
if !buf or buf.length != num_types
@error = 'Unable to read authentication types'
return nil
end
@auth_types = buf.unpack('C*')
end
if !@auth_types or @auth_types.length < 1
@error = 'No authentication types found'
return nil
end
selected = nil
selected ||= AuthType::None if @opts[:allow_none] and @auth_types.include? AuthType::None
selected ||= AuthType::VNC if @auth_types.include? AuthType::VNC
selected ||= AuthType::ARD if @auth_types.include? AuthType::ARD
if !selected
auth_strings = @auth_types.map { |i| Rex::Proto::RFB::AuthType.to_s(i) }
@error = "No supported authentication method found. All available options: #{auth_strings.join(', ')}"
return nil
end
@sock.put([selected].pack('C')) if @minver >= 7
selected
end
|
#negotiate_vnc_auth(password = nil) ⇒ Object
206
207
208
209
210
211
212
213
214
215
216
217
|
# File 'lib/rex/proto/rfb/client.rb', line 206
def negotiate_vnc_auth(password = nil)
challenge = @sock.get_once(16)
if !challenge or challenge.length != 16
@error = 'Unable to obtain VNC challenge'
return false
end
response = Cipher.encrypt(challenge, password)
@sock.put(response)
true
end
|
#read_error_message ⇒ Object
31
32
33
34
35
36
37
|
# File 'lib/rex/proto/rfb/client.rb', line 31
def read_error_message
len = @sock.get_once(4)
return 'Unknown error' if !len or len.length != 4
len = len.unpack('N').first
@sock.get_once(len)
end
|
#send_client_init ⇒ Object
84
85
86
87
88
89
90
|
# File 'lib/rex/proto/rfb/client.rb', line 84
def send_client_init
if @opts[:exclusive]
@sock.put("\x00") else
@sock.put("\x01") end
end
|