CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/h323/h323_version.rb
Views: 1904
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Exploit::Remote::Tcp
8
include Msf::Auxiliary::Scanner
9
include Msf::Auxiliary::Report
10
11
def initialize
12
super(
13
'Name' => 'H.323 Version Scanner',
14
'Description' => 'Detect H.323 Version.',
15
'Author' => 'hdm',
16
'License' => MSF_LICENSE
17
)
18
19
register_options(
20
[
21
Opt::RPORT(1720),
22
])
23
end
24
25
def run_host(ip)
26
27
remote_display = nil
28
remote_product_id = nil
29
remote_version_id = nil
30
remote_vendor_id = nil
31
remote_protocol = nil
32
33
begin
34
35
# Wrap this in a timeout to prevent dead services from
36
# hanging this thread.
37
Timeout.timeout( call_timeout) do
38
39
connect
40
41
caller_name = "SYSTEM\x00"
42
h323_id = Rex::Text.rand_text_alpha(3)
43
vendor_id = Rex::Text.rand_text_alpha(32)
44
caller_host = Rex::Socket.source_address( ip )
45
caller_port = rand( 32768 ) + 30000
46
callee_host = rhost
47
callee_port = rport
48
conf_guid = Rex::Text.rand_text(16)
49
call_guid = Rex::Text.rand_text(16)
50
51
pkt_setup = h323_setup_call({
52
:caller_name => caller_name,
53
:h323_id => h323_id,
54
:vendor_id => vendor_id,
55
:callee_host => callee_host,
56
:callee_port => callee_port,
57
:caller_host => caller_host,
58
:caller_port => caller_port,
59
:conf_guid => conf_guid,
60
:call_guid => call_guid
61
})
62
63
res = sock.put(pkt_setup) rescue nil
64
if not res
65
disconnect
66
return
67
end
68
69
cnt = 0
70
while( true )
71
info = read_packet
72
break if not info
73
74
# The remote side of the call disconnected us
75
break if info[:type] == @@H323_STATUS_RELEASE_COMPLETE
76
77
remote_display = info[40].strip if info[40]
78
remote_product_id = info[:product_id].strip if info[:product_id]
79
remote_version_id = info[:version_id].strip if info[:version_id]
80
remote_protocol = info[:protocol_version].strip if info[:protocol_version]
81
82
if info[:vendor_id] and [nil, "Unknown"].include?( remote_vendor_id )
83
remote_vendor_id = info[:vendor_id].strip
84
end
85
86
# Diagnostics
87
# print_status("Host: #{rhost}:#{rport} => #{info.inspect}")
88
89
# The remote side of the call was connected (kill it)
90
break if info[:type] == @@H323_STATUS_CONNECT
91
92
# Exit if we already received 5 packets from the server
93
break if (cnt +=1) > 5
94
95
end
96
97
# Make sure the call was shut down cleanly
98
pkt_release = h323_release_call({
99
:caller_name => caller_name,
100
:call_guid => call_guid
101
})
102
sock.put(pkt_release) rescue nil
103
104
# End timeout block
105
end
106
107
rescue ::Timeout::Error
108
rescue ::Interrupt
109
raise $!
110
rescue ::Rex::ConnectionError, ::IOError, ::Errno::ECONNRESET, ::Errno::ENOPROTOOPT
111
rescue ::Exception
112
print_error("#{rhost}:#{rport} #{$!.class} #{$!} #{$!.backtrace}")
113
ensure
114
disconnect
115
end
116
117
if remote_vendor_id
118
remote_product_id = remote_product_id.to_s.gsub(/[^\x20-\x7e]/, '')
119
remote_version_id = remote_version_id.to_s.gsub(/[^\x20-\x7e]/, '')
120
121
banner = "Protocol: #{ remote_protocol } VendorID: #{ remote_vendor_id } "
122
123
if remote_version_id and remote_version_id.length > 0
124
banner << "VersionID: #{ remote_version_id } "
125
end
126
127
if remote_product_id and remote_product_id.length > 0
128
banner << "ProductID: #{ remote_product_id } "
129
end
130
131
if remote_display and remote_display.length > 0
132
remote_display = remote_display.to_s.gsub(/[^\x20-\x7e]/, '')
133
banner << "DisplayName: #{ remote_display }"
134
end
135
136
print_good("#{rhost}:#{rport} #{banner}")
137
report_service(:host => rhost, :port => rport, :name => "h323", :info => banner)
138
end
139
140
end
141
142
def read_packet
143
begin
144
::Timeout.timeout( read_timeout ) do
145
ver = sock.read(2)
146
return if not (ver and ver == "\x03\x00")
147
148
bin = sock.read(2)
149
return if not bin
150
151
len = [ bin.unpack("n")[0] - 4, 0 ].max
152
return if len == 0
153
154
bin = sock.read(len)
155
return if not bin
156
157
f_desc, cref_len = bin.unpack("CC")
158
cref_val = bin[2, cref_len]
159
f_type = bin[2 + cref_len, 1].unpack("C")[0]
160
161
return { :type => f_type, :call_ref => cref_val }.merge( read_ies(f_type, bin[ 2 + cref_len + 1, bin.length] ) )
162
end
163
rescue ::Timeout::Error
164
end
165
nil
166
end
167
168
def read_ies(mtype, data)
169
r = { }
170
i = 0
171
172
while( i < (data.length - 1) )
173
ie_type = data[i, 1].unpack("C")[0]
174
break if not ie_type
175
176
ie_len = 0
177
ie_data = ""
178
179
case ie_type
180
when @@H225_IE_USER_USER
181
ie_len = data[i+1, 2].unpack("n")[0]
182
break if not ie_len
183
184
ie_data = data[i+3, ie_len]
185
break if not ie_data
186
187
i = i + 3 + ie_len
188
else
189
ie_len = data[i+1, 1].unpack("C")[0]
190
break if not ie_len
191
192
ie_data = data[i+2, ie_len]
193
break if not ie_data
194
195
i = i + 2 + ie_len
196
end
197
198
r[ ie_type ] = ie_data
199
200
if ie_type == @@H225_IE_USER_USER
201
r.merge!( ( read_user_user(mtype, ie_data) rescue {} ) )
202
end
203
end
204
r
205
end
206
207
208
# This provides a weak method of decoding USER-USER PDUs. These are
209
# actually PER-encoded ASN.1, but we take a few shortcuts since PER
210
# encoding is such a pain.
211
def read_user_user(mtype, data)
212
r = {}
213
214
# Identify the embedded version (2/3/4/5/6 commonly found)
215
i = data.index("\x00\x08\x91\x4a\x00")
216
return r if not i
217
218
# Store the protocol version
219
pver = data[i + 5, 1].unpack("C")[0]
220
221
r[:protocol_version] = pver.to_s
222
223
# Bump the index over the version
224
i+= 6
225
226
# print_line( Rex::Text.to_hex_dump( data[i, 32] ) )
227
228
# Set a placeholder VendorID so this system will be reported
229
r[:vendor_id] = "Unknown"
230
231
# We use the version offset to identify the destination block location
232
# This changes slightly based on the type of packet we receive
233
case mtype
234
when @@H323_STATUS_ALERTING, @@H323_STATUS_PROCEEDING
235
236
if pver == 2 and data[i, 2] == "\x20\x00"
237
r[ :vendor_id ] = "0x%.8x" % ( data[i + 2, 4].unpack("N")[0] rescue 0 )
238
return r
239
end
240
241
# Find the offset to the VendorID
242
if data[i + 1, 1] != "\xc0"
243
i+= 7
244
end
245
246
# Stop processing if we can't identify a VendorID
247
return r if data[i + 1, 1] != "\xc0"
248
249
# Otherwise just add 2 to the offset of the version
250
i += 2
251
252
when @@H323_STATUS_CONNECT
253
254
# Bail early in some corner cases
255
return r if data[i, 1] == "\x00"
256
257
# Find the offset to the VendorID
258
if data[i + 1, 1] != "\xc0"
259
i+= 7
260
end
261
262
# Stop processing if we can't identify a VendorID
263
return r if data[i + 1, 1] != "\xc0"
264
265
i += 2
266
267
return r
268
else
269
return r
270
end
271
272
# Extract the manufacturer ID
273
r[ :vendor_id ] = "0x%.8x" % ( data[i, 4].unpack("N")[0] rescue 0 )
274
i+= 4
275
276
# No Product ID / Version ID in versions less than 3 (unless special cased above)
277
return r if pver < 3
278
279
# Get the product_id length (-1)
280
product_id_length = data[i, 1].unpack("C")[0] + 1
281
i+= 1
282
283
# Extract the product ID
284
r[ :product_id ] = data[i, product_id_length]
285
i+= product_id_length
286
287
# Get the version ID length (-1)
288
version_id_length = data[i, 1].unpack("C")[0] + 1
289
i+= 1
290
291
# Extract the version ID
292
r[ :version_id ] = data[i, version_id_length]
293
294
# Thats it for now
295
296
r
297
end
298
299
def read_timeout
300
10
301
end
302
303
def call_timeout
304
30
305
end
306
307
308
@@H225_IE_BEARER_CAP = 0x04
309
@@H225_IE_DISPLAY = 0x28
310
@@H225_IE_USER_USER = 0x7e # Yes, really User-user
311
312
313
@@H323_STATUS_ALERTING = 0x01
314
@@H323_STATUS_PROCEEDING = 0x02
315
@@H323_STATUS_SETUP = 0x05
316
@@H323_STATUS_SETUP_ACK = 0x0D
317
@@H323_STATUS_CONNECT = 0x07
318
@@H323_STATUS_RELEASE_COMPLETE = 0x5a
319
@@H323_STATUS_FACILITY = 0x62
320
321
322
def encap_tpkt(ver,data)
323
[ ver, 0, data.length + 4 ].pack("CCn") + data
324
end
325
326
def encap_q225(desc, cref_value, msg_type, data)
327
[ desc, cref_value.length, cref_value, msg_type].pack("CCA*C") + data
328
end
329
330
def encap_q225_standard(msg_type, data)
331
encap_q225(0x08, [0x733f].pack("n"), msg_type, data)
332
end
333
334
def encap_q225_setup(data)
335
encap_q225_standard(0x05, data)
336
end
337
338
def encap_q225_release(data)
339
encap_q225_standard(0x5a, data)
340
end
341
342
def create_ie_byte(ie_type, data)
343
[ie_type, data.length].pack("CC") + data
344
end
345
346
def create_ie_short(ie_type, data)
347
[ie_type, data.length].pack("Cn") + data
348
end
349
350
def create_ie_bearer_capability(cap = 0x00038893)
351
create_ie_byte( @@H225_IE_BEARER_CAP, [cap].pack("N")[0,3] )
352
end
353
354
def create_ie_display(name = "DEBUG\x00")
355
create_ie_byte( @@H225_IE_DISPLAY, name )
356
end
357
358
def create_ie_user_user(data)
359
create_ie_short( @@H225_IE_USER_USER, data )
360
end
361
362
#
363
# This is ugly. Doing it properly requires a PER capable ASN.1 encoder, which is overkill for this task
364
#
365
def create_user_info(opts = {})
366
h323_id = opts[:h323_id]
367
vendor_id = opts[:vendor_id]
368
callee_host = opts[:callee_host]
369
callee_port = opts[:callee_port]
370
caller_host = opts[:caller_host]
371
caller_port = opts[:caller_port]
372
conf_guid = opts[:conf_guid]
373
call_guid = opts[:call_guid]
374
375
buff = "\x05" # Protocol descriminator: X.208/X.209 coded user information
376
377
buff << "\x20\xa8\x06\x00\x08\x91\x4a\x00\x06\x01\x40\x02"
378
379
# H323-ID
380
buff << h323_id.unpack("C*").pack("n*")
381
382
buff << "\x22\xc0\x09\x00\x00\x3d\x02\x00\x00\x00\x21"
383
384
# VENDOR: 32 + 2 null bytes
385
buff << [vendor_id].pack("Z32") + "\x00\x00"
386
387
buff << "\x00"
388
389
# Remote IP + Remote Port
390
buff << ( ::Rex::Socket.addr_aton( callee_host ) + [ callee_port.to_i ].pack("n") )
391
392
buff << "\x00"
393
394
# Conference GUID
395
buff << conf_guid
396
397
buff << "\x00\xc5\x1d\x80\x04\x07\x00"
398
399
# Local IP + Port
400
buff << ( ::Rex::Socket.addr_aton( caller_host ) + [ caller_port.to_i ].pack("n") )
401
402
buff << "\x11\x00"
403
404
# Call GUID
405
buff << call_guid
406
407
buff <<
408
"\x82\x49\x10\x47\x40\x00\x00\x06\x04\x01\x00\x4c\x10\xb5" +
409
"\x00\x00\x26\x25\x73\x70\x65\x65\x78\x20\x73\x72\x3d\x31" +
410
"\x36\x30\x30\x30\x3b\x6d\x6f\x64\x65\x3d\x36\x3b\x76\x62" +
411
"\x72\x3d\x6f\x66\x66\x3b\x63\x6e\x67\x3d\x6f\x66\x66\x80" +
412
"\x12\x1c\x40\x01\x00" +
413
414
Rex::Socket.addr_aton( caller_host ) +
415
416
"\x13\xc6\x00" +
417
418
Rex::Socket.addr_aton( caller_host ) +
419
420
"\x13\xc7\x90\x3c\x00\x00\x64\x0c\x10\xb5\x00\x00\x26\x25" +
421
"\x73\x70\x65\x65\x78\x20\x73\x72\x3d\x31\x36\x30\x30\x30" +
422
"\x3b\x6d\x6f\x64\x65\x3d\x36\x3b\x76\x62\x72\x3d\x6f\x66" +
423
"\x66\x3b\x63\x6e\x67\x3d\x6f\x66\x66\x80\x0b\x0d\x40\x01" +
424
"\x00" +
425
426
Rex::Socket.addr_aton( caller_host ) +
427
428
"\x13\xc7\x48\x31\x40\x00\x00\x06\x04\x01\x00\x4c\x10\x09" +
429
"\x00\x00\x3d\x0f\x53\x70\x65\x65\x78\x20\x62\x73\x34\x20" +
430
"\x57\x69\x64\x65\x36\x80\x12\x1c\x40\x01\x00" +
431
432
Rex::Socket.addr_aton( caller_host ) +
433
434
"\x13\xc6\x00" +
435
436
Rex::Socket.addr_aton( caller_host ) +
437
438
"\x13\xc7\xa0\x26\x00\x00\x65\x0c\x10\x09\x00\x00\x3d\x0f" +
439
"\x53\x70\x65\x65\x78\x20\x62\x73\x34\x20\x57\x69\x64\x65" +
440
"\x36\x80\x0b\x0d\x40\x01\x00" +
441
442
Rex::Socket.addr_aton( caller_host ) +
443
444
"\x13\xc7\x50\x1d\x40\x00\x00\x06\x04\x01\x00\x4c\x60\x13" +
445
"\x80\x11\x1c\x00\x01\x00" +
446
447
Rex::Socket.addr_aton( caller_host ) +
448
449
"\x13\xc6\x00" +
450
451
Rex::Socket.addr_aton( caller_host ) +
452
453
"\x13\xc7\x13\x00\x00\x66\x0c\x60\x13\x80\x0b\x0d\x00\x01" +
454
"\x00" +
455
456
Rex::Socket.addr_aton( caller_host ) +
457
458
"\x13\xc7\x00\x1d\x40\x00\x00\x06\x04\x01\x00\x4c\x20\x13" +
459
"\x80\x11\x1c\x00\x01\x00" +
460
461
Rex::Socket.addr_aton( caller_host ) +
462
463
"\x13\xc6\x00" +
464
465
Rex::Socket.addr_aton( caller_host ) +
466
467
"\x13\xc7\x13\x00\x00\x67\x0c\x20\x13\x80\x0b\x0d\x00\x01" +
468
"\x00" +
469
470
Rex::Socket.addr_aton( caller_host ) +
471
472
"\x13\xc7\x00\x23\x40\x00\x00\x06\x04\x01\x00\x48\x78\x00" +
473
"\x4a\xff\x00\x80\x01\x00\x80\x11\x1c\x00\x02\x00" +
474
475
Rex::Socket.addr_aton( caller_host ) +
476
477
"\x13\xc8\x00" +
478
479
Rex::Socket.addr_aton( caller_host ) +
480
481
"\x13\xc9\x19\x00\x00\x68\x08\x78\x00\x4a\xff\x00\x80\x01" +
482
"\x00\x80\x0b\x0d\x00\x02\x00" +
483
484
Rex::Socket.addr_aton( caller_host ) +
485
486
"\x13\xc9\x00\x22\x40\x00\x00\x06\x04\x01\x00\x48\x68\x4a" +
487
"\xff\x00\x80\x01\x00\x80\x11\x1c\x00\x02\x00" +
488
489
Rex::Socket.addr_aton( caller_host ) +
490
491
"\x13\xc8\x00" +
492
493
Rex::Socket.addr_aton( caller_host ) +
494
495
"\x13\xc9\x18\x00\x00\x69\x08\x68\x4a\xff\x00\x80\x01\x00" +
496
"\x80\x0b\x0d\x00\x02\x00" +
497
498
Rex::Socket.addr_aton( caller_host ) +
499
500
"\x13\xc9\x00\x22\x40\x00\x00\x06\x04\x01\x00\x48\x70\x4a" +
501
"\xff\x00\x80\x01\x00\x80\x11\x1c\x00\x02\x00" +
502
503
Rex::Socket.addr_aton( caller_host ) +
504
505
"\x13\xc8\x00" +
506
507
Rex::Socket.addr_aton( caller_host ) +
508
509
"\x13\xc9\x18\x00\x00\x6a\x08\x70\x4a\xff\x00\x80\x01\x00" +
510
"\x80\x0b\x0d\x00\x02\x00" +
511
512
Rex::Socket.addr_aton( caller_host ) +
513
514
"\x13\xc9\x00\x2c\x40\x00\x00\x06\x04\x01\x00\x48\xee\x00" +
515
"\x00\x20\x9f\xff\x20\x50\x40\x01\x00\x80\x17\x1c\x20\x02" +
516
"\x00" +
517
518
Rex::Socket.addr_aton( caller_host ) +
519
520
"\x13\xc8\x00" +
521
522
Rex::Socket.addr_aton( caller_host ) +
523
524
"\x13\xc9\x80\x04\x48\x08\x8d\x44\x22\x00\x00\x6b\x08\xee" +
525
"\x00\x00\x20\x9f\xff\x20\x50\x40\x01\x00\x80\x11\x0d\x20" +
526
"\x02\x00" +
527
528
Rex::Socket.addr_aton( caller_host ) +
529
530
"\x13\xc9\x40\x00\x04\x48\x08\x8d\x44\x01\x00\x01\x00\x01" +
531
"\x00\x01\x00\x80\xfa\x02\x80\xef\x02\x70\x01\x06\x00\x08" +
532
"\x81\x75\x00\x0d\x80\x1a\x80\x01\xf4\x00\x01\x00\x00\x01" +
533
"\x00\x00\x01\x00\x04\x02\x05\x00\x48\x08\x8d\x44\x06\x60" +
534
"\x01\x00\x01\x80\x0b\x80\x00\x00\x20\x20\xb5\x00\x00\x26" +
535
"\x25\x73\x70\x65\x65\x78\x20\x73\x72\x3d\x31\x36\x30\x30" +
536
"\x30\x3b\x6d\x6f\x64\x65\x3d\x36\x3b\x76\x62\x72\x3d\x6f" +
537
"\x66\x66\x3b\x63\x6e\x67\x3d\x6f\x66\x66\x80\x00\x01\x20" +
538
"\x20\x09\x00\x00\x3d\x0f\x53\x70\x65\x65\x78\x20\x62\x73" +
539
"\x34\x20\x57\x69\x64\x65\x36\x80\x00\x02\x20\xc0\xef\x80" +
540
"\x00\x03\x20\x40\xef\x80\x00\x04\x08\xf0\x00\x4a\xff\x00" +
541
"\x80\x01\x00\x80\x00\x05\x08\xd0\x4a\xff\x00\x80\x01\x00" +
542
"\x80\x00\x06\x08\xe0\x4a\xff\x00\x80\x01\x00\x80\x00\x07" +
543
"\x09\xdc\x00\x00\x40\x9f\xff\x20\x50\x40\x01\x00\x80\x00" +
544
"\x08\x83\x01\x50\x80\x00\x09\x83\x01\x10\x80\x00\x0a\x83" +
545
"\x01\x40\x80\x00\x0b\x8a\x0c\x14\x0a\x30\x2d\x31\x36\x2c" +
546
"\x33\x32\x2c\x33\x36\x00\x80\x01\x03\x03\x00\x00\x00\x01" +
547
"\x00\x02\x00\x03\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00" +
548
"\x00\x08\x02\x00\x09\x00\x0a\x00\x0b\x07\x01\x00\x32\x80" +
549
"\x96\x61\x41\x02\x80\x01\x80"
550
551
buff
552
end
553
554
def create_user_release_info(call_guid)
555
"\x05" +
556
"\x25\x80\x06\x00\x08\x91\x4a\x00\x05\x01\x11\x00" +
557
call_guid +
558
"\x02\x80\x01\x00"
559
end
560
561
def h323_release_call(opts = {})
562
caller_name = opts[:caller_name]
563
call_guid = opts[:call_guid]
564
565
encap_tpkt(3,
566
encap_q225_release(
567
create_ie_display(caller_name) +
568
create_ie_user_user(
569
create_user_release_info(call_guid )
570
)
571
)
572
)
573
end
574
575
def h323_setup_call(opts = {})
576
caller_name = opts[:caller_name]
577
h323_id = opts[:h323_id]
578
vendor_id = opts[:vendor_id]
579
callee_host = opts[:callee_host]
580
callee_port = opts[:callee_port]
581
caller_host = opts[:caller_host]
582
caller_port = opts[:caller_port]
583
conf_guid = opts[:conf_guid]
584
call_guid = opts[:call_guid]
585
586
encap_tpkt(3,
587
encap_q225_setup(
588
create_ie_bearer_capability() +
589
create_ie_display(caller_name) +
590
create_ie_user_user(
591
create_user_info({
592
:h323_id => h323_id,
593
:vendor_id => vendor_id,
594
:callee_host => callee_host,
595
:callee_port => callee_port,
596
:caller_host => caller_host,
597
:caller_port => caller_port,
598
:conf_guid => conf_guid,
599
:call_guid => call_guid
600
})
601
)
602
)
603
)
604
end
605
end
606
607