CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/rex/proto/ntlm/utils.rb
Views: 11704
1
# -*- coding: binary -*-
2
3
module Rex::Proto::NTLM
4
class Utils
5
6
# duplicate from lib/rex/proto/smb/utils cause we only need this function from Rex::Proto::SMB::Utils
7
# Convert a unix timestamp to a 64-bit signed server time
8
def self.time_unix_to_smb(unix_time)
9
t64 = (unix_time + 11644473600) * 10000000
10
thi = (t64 & 0xffffffff00000000) >> 32
11
tlo = (t64 & 0x00000000ffffffff)
12
return [thi, tlo]
13
end
14
15
# Determine whether the password is a known hash format
16
def self.is_pass_ntlm_hash?(str)
17
str.downcase =~ /^[0-9a-f]{32}:[0-9a-f]{32}$/
18
end
19
20
#
21
# Prepends an ASN1 formatted length field to a piece of data
22
#
23
def self.asn1encode(str = '')
24
res = ''
25
26
# If the high bit of the first byte is 1, it contains the number of
27
# length bytes that follow
28
29
case str.length
30
when 0 .. 0x7F
31
res = [str.length].pack('C') + str
32
when 0x80 .. 0xFF
33
res = [0x81, str.length].pack('CC') + str
34
when 0x100 .. 0xFFFF
35
res = [0x82, str.length].pack('Cn') + str
36
when 0x10000 .. 0xffffff
37
res = [0x83, str.length >> 16, str.length & 0xFFFF].pack('CCn') + str
38
when 0x1000000 .. 0xffffffff
39
res = [0x84, str.length].pack('CN') + str
40
else
41
raise "ASN1 str too long"
42
end
43
return res
44
end
45
46
# GSS functions
47
48
# GSS BLOB useful for SMB_NEGOCIATE_RESPONSE message
49
# mechTypes: 2 items :
50
# -MechType: 1.3.6.1.4.1.311.2.2.30 (SNMPv2-SMI::enterprises.311.2.2.30)
51
# -MechType: 1.3.6.1.4.1.311.2.2.10 (NTLMSSP - Microsoft NTLM Security Support Provider)
52
#
53
# this is the default on Win7
54
def self.make_simple_negotiate_secblob_resp
55
blob =
56
"\x60" + self.asn1encode(
57
"\x06" + self.asn1encode(
58
"\x2b\x06\x01\x05\x05\x02"
59
) +
60
"\xa0" + self.asn1encode(
61
"\x30" + self.asn1encode(
62
"\xa0" + self.asn1encode(
63
"\x30" + self.asn1encode(
64
"\x06" + self.asn1encode(
65
"\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
66
)
67
)
68
)
69
)
70
)
71
)
72
73
return blob
74
end
75
76
# GSS BLOB useful for SMB_NEGOCIATE_RESPONSE message
77
# mechTypes: 4 items :
78
# MechType: 1.2.840.48018.1.2.2 (MS KRB5 - Microsoft Kerberos 5)
79
# MechType: 1.2.840.113554.1.2.2 (KRB5 - Kerberos 5)
80
# MechType: 1.2.840.113554.1.2.2.3 (KRB5 - Kerberos 5 - User to User)
81
# MechType: 1.3.6.1.4.1.311.2.2.10 (NTLMSSP - Microsoft NTLM Security Support Provider)
82
# mechListMIC:
83
# principal: account@domain
84
def self.make_negotiate_secblob_resp(account, domain)
85
blob =
86
"\x60" + self.asn1encode(
87
"\x06" + self.asn1encode(
88
"\x2b\x06\x01\x05\x05\x02"
89
) +
90
"\xa0" + self.asn1encode(
91
"\x30" + self.asn1encode(
92
"\xa0" + self.asn1encode(
93
"\x30" + self.asn1encode(
94
"\x06" + self.asn1encode(
95
"\x2a\x86\x48\x82\xf7\x12\x01\x02\x02"
96
) +
97
"\x06" + self.asn1encode(
98
"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"
99
) +
100
"\x06" + self.asn1encode(
101
"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x03"
102
) +
103
"\x06" + self.asn1encode(
104
"\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
105
)
106
)
107
) +
108
"\xa3" + self.asn1encode(
109
"\x30" + self.asn1encode(
110
"\xa0" + self.asn1encode(
111
"\x1b" + self.asn1encode(
112
account + '@' + domain
113
)
114
)
115
)
116
)
117
)
118
)
119
)
120
121
return blob
122
end
123
124
# BLOB without GSS useful for ntlmssp type 1 message
125
def self.make_ntlmssp_blob_init(domain = 'WORKGROUP', name = 'WORKSTATION', flags=0x80201)
126
blob = "NTLMSSP\x00" +
127
[1, flags].pack('VV') +
128
129
[
130
domain.length, #length
131
domain.length, #max length
132
32
133
].pack('vvV') +
134
135
[
136
name.length, #length
137
name.length, #max length
138
domain.length + 32
139
].pack('vvV') +
140
141
domain + name
142
return blob
143
end
144
145
# GSS BLOB useful for ntlmssp type 1 message
146
def self.make_ntlmssp_secblob_init(domain = 'WORKGROUP', name = 'WORKSTATION', flags=0x80201)
147
blob =
148
"\x60" + self.asn1encode(
149
"\x06" + self.asn1encode(
150
"\x2b\x06\x01\x05\x05\x02"
151
) +
152
"\xa0" + self.asn1encode(
153
"\x30" + self.asn1encode(
154
"\xa0" + self.asn1encode(
155
"\x30" + self.asn1encode(
156
"\x06" + self.asn1encode(
157
"\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
158
)
159
)
160
) +
161
"\xa2" + self.asn1encode(
162
"\x04" + self.asn1encode(
163
make_ntlmssp_blob_init(domain, name, flags)
164
)
165
)
166
)
167
)
168
)
169
170
return blob
171
end
172
173
174
# BLOB without GSS useful for ntlm type 2 message
175
def self.make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
176
177
addr_list = ''
178
addr_list << [2, win_domain.length].pack('vv') + win_domain
179
addr_list << [1, win_name.length].pack('vv') + win_name
180
addr_list << [4, dns_domain.length].pack('vv') + dns_domain
181
addr_list << [3, dns_name.length].pack('vv') + dns_name
182
addr_list << [0, 0].pack('vv')
183
184
ptr = 0
185
blob = "NTLMSSP\x00" +
186
[2].pack('V') +
187
[
188
win_domain.length, # length
189
win_domain.length, # max length
190
(ptr += 48) # offset
191
].pack('vvV') +
192
[ flags ].pack('V') +
193
chall +
194
"\x00\x00\x00\x00\x00\x00\x00\x00" +
195
[
196
addr_list.length, # length
197
addr_list.length, # max length
198
(ptr += win_domain.length)
199
].pack('vvV') +
200
win_domain +
201
addr_list
202
return blob
203
end
204
205
# GSS BLOB useful for ntlmssp type 2 message
206
def self.make_ntlmssp_secblob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
207
208
blob =
209
"\xa1" + self.asn1encode(
210
"\x30" + self.asn1encode(
211
"\xa0" + self.asn1encode(
212
"\x0a" + self.asn1encode(
213
"\x01"
214
)
215
) +
216
"\xa1" + self.asn1encode(
217
"\x06" + self.asn1encode(
218
"\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
219
)
220
) +
221
"\xa2" + self.asn1encode(
222
"\x04" + self.asn1encode(
223
make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
224
)
225
)
226
)
227
)
228
229
return blob
230
end
231
232
# BLOB without GSS Useful for ntlmssp type 3 message
233
def self.make_ntlmssp_blob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201)
234
lm ||= "\x00" * 24
235
ntlm ||= "\x00" * 24
236
237
domain_uni = Rex::Text.to_unicode(domain)
238
user_uni = Rex::Text.to_unicode(user)
239
name_uni = Rex::Text.to_unicode(name)
240
session = enc_session_key
241
242
ptr = 64
243
244
blob = "NTLMSSP\x00" +
245
[ 3 ].pack('V') +
246
247
[ # Lan Manager Response
248
lm.length,
249
lm.length,
250
(ptr)
251
].pack('vvV') +
252
253
[ # NTLM Manager Response
254
ntlm.length,
255
ntlm.length,
256
(ptr += lm.length)
257
].pack('vvV') +
258
259
[ # Domain Name
260
domain_uni.length,
261
domain_uni.length,
262
(ptr += ntlm.length)
263
].pack('vvV') +
264
265
[ # Username
266
user_uni.length,
267
user_uni.length,
268
(ptr += domain_uni.length)
269
].pack('vvV') +
270
271
[ # Hostname
272
name_uni.length,
273
name_uni.length,
274
(ptr += user_uni.length)
275
].pack('vvV') +
276
277
[ # Session Key (none)
278
session.length,
279
session.length,
280
(ptr += name_uni.length)
281
].pack('vvV') +
282
283
[ flags ].pack('V') +
284
285
lm +
286
ntlm +
287
domain_uni +
288
user_uni +
289
name_uni +
290
session + "\x00"
291
return blob
292
293
end
294
295
# GSS BLOB Useful for ntlmssp type 3 message
296
def self.make_ntlmssp_secblob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201)
297
298
blob =
299
"\xa1" + self.asn1encode(
300
"\x30" + self.asn1encode(
301
"\xa2" + self.asn1encode(
302
"\x04" + self.asn1encode(
303
make_ntlmssp_blob_auth(domain, name, user, lm, ntlm, enc_session_key, flags )
304
)
305
)
306
)
307
)
308
return blob
309
end
310
311
312
# GSS BLOB Useful for SMB Success
313
def self.make_ntlmv2_secblob_success
314
blob =
315
"\xa1" + self.asn1encode(
316
"\x30" + self.asn1encode(
317
"\xa0" + self.asn1encode(
318
"\x0a" + self.asn1encode(
319
"\x00"
320
)
321
)
322
)
323
)
324
return blob
325
end
326
327
# Return the correct ntlmflags upon the configuration
328
def self.make_ntlm_flags(opt = {})
329
330
signing = opt[:signing] != nil ? opt[:signing] : false
331
usentlm2_session = opt[:usentlm2_session] != nil ? opt[:usentlm2_session] : true
332
use_ntlmv2 = opt[:use_ntlmv2] != nil ? opt[:use_ntlmv2] : false
333
send_lm = opt[:send_lm] != nil ? opt[:send_lm] : true
334
send_ntlm = opt[:send_ntlm] != nil ? opt[:send_ntlm] : true
335
use_lanman_key = opt[:use_lanman_key] != nil ? opt[:use_lanman_key] : false
336
337
if signing
338
ntlmssp_flags = 0xe2088215
339
else
340
341
ntlmssp_flags = 0xa2080205
342
end
343
344
if usentlm2_session
345
if use_ntlmv2
346
#set Negotiate Target Info
347
ntlmssp_flags |= Rex::Proto::NTLM::Constants::NEGOTIATE_TARGET_INFO
348
end
349
350
else
351
#remove the ntlm2_session flag
352
ntlmssp_flags &= 0xfff7ffff
353
#set lanmanflag only when lm and ntlm are sent
354
if send_lm
355
ntlmssp_flags |= Rex::Proto::NTLM::Constants::NEGOTIATE_LMKEY if use_lanman_key
356
end
357
end
358
359
#we can also downgrade ntlm2_session when we send only lmv1
360
ntlmssp_flags &= 0xfff7ffff if usentlm2_session && (not use_ntlmv2) && (not send_ntlm)
361
362
return ntlmssp_flags
363
end
364
365
366
# Parse an ntlm type 2 challenge blob and return useful data
367
def self.parse_ntlm_type_2_blob(blob)
368
data = {}
369
# Extract the NTLM challenge key the lazy way
370
cidx = blob.index("NTLMSSP\x00\x02\x00\x00\x00")
371
372
if not cidx
373
raise Rex::Proto::NTLM::Exceptions::NTLMMissingChallenge
374
end
375
376
data[:challenge_key] = blob[cidx + 24, 8]
377
378
data[:server_ntlmssp_flags] = blob[cidx + 20, 4].unpack("V")[0]
379
380
# Extract the address list from the blob
381
alist_len,alist_mlen,alist_off = blob[cidx + 40, 8].unpack("vvV")
382
alist_buf = blob[cidx + alist_off, alist_len]
383
384
while(alist_buf.length > 0)
385
atype, alen = alist_buf.slice!(0,4).unpack('vv')
386
break if atype == 0x00
387
addr = alist_buf.slice!(0, alen)
388
case atype
389
when 1
390
#netbios name
391
temp_name = addr
392
temp_name.force_encoding("UTF-16LE")
393
data[:default_name] = temp_name.encode("UTF-8")
394
when 2
395
#netbios domain
396
temp_domain = addr
397
temp_domain.force_encoding("UTF-16LE")
398
data[:default_domain] = temp_domain.encode("UTF-8")
399
when 3
400
#dns name
401
temp_dns = addr
402
temp_dns.force_encoding("UTF-16LE")
403
data[:dns_host_name] = temp_dns.encode("UTF-8")
404
when 4
405
#dns domain
406
temp_dns_domain = addr
407
temp_dns_domain.force_encoding("UTF-16LE")
408
data[:dns_domain_name] = temp_dns_domain.encode("UTF-8")
409
when 5
410
#The FQDN of the forest.
411
when 6
412
#A 32-bit value indicating server or client configuration
413
when 7
414
#Client time
415
data[:chall_MsvAvTimestamp] = addr
416
when 8
417
#A Restriction_Encoding structure
418
when 9
419
#The SPN of the target server.
420
when 10
421
#A channel bindings hash.
422
end
423
end
424
return data
425
end
426
427
# This function return an ntlmv2 client challenge
428
# This is a partial implementation, full description is in [MS-NLMP].pdf around 3.1.5.2.1 :-/
429
def self.make_ntlmv2_clientchallenge(win_domain, win_name, dns_domain, dns_name,
430
client_challenge = nil, chall_MsvAvTimestamp = nil, spnopt = {})
431
432
client_challenge ||= Rex::Text.rand_text(8)
433
# We have to set the timestamps here to the one in the challenge message from server if present
434
# If we don't do that, recent server like Seven/2008 will send a STATUS_INVALID_PARAMETER error packet
435
timestamp = chall_MsvAvTimestamp != '' ? chall_MsvAvTimestamp : self.time_unix_to_smb(::Time.now.to_i).reverse.pack("VV")
436
# Make those values unicode as requested
437
win_domain = Rex::Text.to_unicode(win_domain)
438
win_name = Rex::Text.to_unicode(win_name)
439
dns_domain = Rex::Text.to_unicode(dns_domain)
440
dns_name = Rex::Text.to_unicode(dns_name)
441
# Make the AV_PAIRs
442
addr_list = ''
443
addr_list << [2, win_domain.length].pack('vv') + win_domain
444
addr_list << [1, win_name.length].pack('vv') + win_name
445
addr_list << [4, dns_domain.length].pack('vv') + dns_domain
446
addr_list << [3, dns_name.length].pack('vv') + dns_name
447
addr_list << [7, 8].pack('vv') + timestamp
448
449
# Windows Seven / 2008r2 Request this type if in local security policies,
450
# Microsoft network server : Server SPN target name validation level is set to <Required from client>
451
# otherwise it send an STATUS_ACCESS_DENIED packet
452
if spnopt[:use_spn]
453
spn= Rex::Text.to_unicode("cifs/#{spnopt[:name] || 'unknown'}")
454
addr_list << [9, spn.length].pack('vv') + spn
455
end
456
457
# MAY BE USEFUL FOR FUTURE
458
# Seven (client) add at least one more av that is of type MsAvRestrictions (8)
459
# maybe this will be useful with future windows OSs but has no use at all for the moment afaik
460
# restriction_encoding = [48,0,0,0].pack("VVV") + # Size, Z4, IntegrityLevel, SubjectIntegrityLevel
461
# Rex::Text.rand_text(32) # MachineId generated on startup on win7 and above
462
# addr_list << [8, restriction_encoding.length].pack('vv') + restriction_encoding
463
464
# Seven (client) and maybe others versions also add an av of type MsvChannelBindings (10) but the hash is "\x00" * 16
465
# addr_list << [10, 16].pack('vv') + "\x00" * 16
466
467
468
addr_list << [0, 0].pack('vv')
469
ntlm_clientchallenge = [1,1,0,0].pack("CCvV") + #RespType, HiRespType, Reserved1, Reserved2
470
timestamp + #Timestamp
471
client_challenge + #clientchallenge
472
[0].pack("V") + #Reserved3
473
addr_list + "\x00" * 4
474
475
end
476
477
# create lm/ntlm responses
478
def self.create_lm_ntlm_responses(user, pass, challenge_key, domain = '', default_name = '', default_domain = '',
479
dns_host_name = '', dns_domain_name = '', chall_MsvAvTimestamp = nil, spnopt = {}, opt = {} )
480
481
usentlm2_session = opt[:usentlm2_session] != nil ? opt[:usentlm2_session] : true
482
use_ntlmv2 = opt[:use_ntlmv2] != nil ? opt[:use_ntlmv2] : false
483
send_lm = opt[:send_lm] != nil ? opt[:send_lm] : true
484
send_ntlm = opt[:send_ntlm] != nil ? opt[:send_ntlm] : true
485
486
#calculate the lm/ntlm response
487
resp_lm = "\x00" * 24
488
resp_ntlm = "\x00" * 24
489
490
client_challenge = Rex::Text.rand_text(8)
491
ntlm_cli_challenge = ''
492
if send_ntlm #should be default
493
if usentlm2_session
494
if use_ntlmv2
495
ntlm_cli_challenge = self.make_ntlmv2_clientchallenge(
496
default_domain, default_name, dns_domain_name,
497
dns_host_name,client_challenge,
498
chall_MsvAvTimestamp, spnopt)
499
500
if self.is_pass_ntlm_hash?(pass)
501
argntlm = {
502
:ntlmv2_hash => Rex::Proto::NTLM::Crypt::ntlmv2_hash(
503
user,
504
[ pass.upcase()[33,65] ].pack('H32'),
505
domain,{:pass_is_hash => true}
506
),
507
:challenge => challenge_key
508
}
509
else
510
argntlm = {
511
:ntlmv2_hash => Rex::Proto::NTLM::Crypt::ntlmv2_hash(user, pass, domain),
512
:challenge => challenge_key
513
}
514
end
515
516
optntlm = { :nt_client_challenge => ntlm_cli_challenge}
517
ntlmv2_response = Rex::Proto::NTLM::Crypt::ntlmv2_response(argntlm,optntlm)
518
resp_ntlm = ntlmv2_response
519
520
if send_lm
521
if self.is_pass_ntlm_hash?(pass)
522
arglm = {
523
:ntlmv2_hash => Rex::Proto::NTLM::Crypt::ntlmv2_hash(
524
user,
525
[ pass.upcase()[33,65] ].pack('H32'),
526
domain,{:pass_is_hash => true}
527
),
528
:challenge => challenge_key
529
}
530
else
531
arglm = {
532
:ntlmv2_hash => Rex::Proto::NTLM::Crypt::ntlmv2_hash(user,pass, domain),
533
:challenge => challenge_key
534
}
535
end
536
537
optlm = { :client_challenge => client_challenge }
538
resp_lm = Rex::Proto::NTLM::Crypt::lmv2_response(arglm, optlm)
539
else
540
resp_lm = "\x00" * 24
541
end
542
543
else # ntlm2_session
544
if self.is_pass_ntlm_hash?(pass)
545
argntlm = {
546
:ntlm_hash => [ pass.upcase()[33,65] ].pack('H32'),
547
:challenge => challenge_key
548
}
549
else
550
argntlm = {
551
:ntlm_hash => Rex::Proto::NTLM::Crypt::ntlm_hash(pass),
552
:challenge => challenge_key
553
}
554
end
555
556
optntlm = { :client_challenge => client_challenge}
557
resp_ntlm = Rex::Proto::NTLM::Crypt::ntlm2_session(argntlm,optntlm).join[24,24]
558
559
# Generate the fake LANMAN hash
560
resp_lm = client_challenge + ("\x00" * 16)
561
end
562
563
else # we use lmv1/ntlmv1
564
if self.is_pass_ntlm_hash?(pass)
565
argntlm = {
566
:ntlm_hash => [ pass.upcase()[33,65] ].pack('H32'),
567
:challenge => challenge_key
568
}
569
else
570
argntlm = {
571
:ntlm_hash => Rex::Proto::NTLM::Crypt::ntlm_hash(pass),
572
:challenge => challenge_key
573
}
574
end
575
576
resp_ntlm = Rex::Proto::NTLM::Crypt::ntlm_response(argntlm)
577
if send_lm
578
if self.is_pass_ntlm_hash?(pass)
579
arglm = {
580
:lm_hash => [ pass.upcase()[0,32] ].pack('H32'),
581
:challenge => challenge_key
582
}
583
else
584
arglm = {
585
:lm_hash => Rex::Proto::NTLM::Crypt::lm_hash(pass),
586
:challenge => challenge_key
587
}
588
end
589
resp_lm = Rex::Proto::NTLM::Crypt::lm_response(arglm)
590
else
591
#when windows does not send lm in ntlmv1 type response,
592
# it gives lm response the same value as ntlm response
593
resp_lm = resp_ntlm
594
end
595
end
596
else #send_ntlm = false
597
#lmv2
598
if usentlm2_session && use_ntlmv2
599
if self.is_pass_ntlm_hash?(pass)
600
arglm = {
601
:ntlmv2_hash => Rex::Proto::NTLM::Crypt::ntlmv2_hash(
602
user,
603
[ pass.upcase()[33,65] ].pack('H32'),
604
domain,{:pass_is_hash => true}
605
),
606
:challenge => challenge_key
607
}
608
else
609
arglm = {
610
:ntlmv2_hash => Rex::Proto::NTLM::Crypt::ntlmv2_hash(user,pass, domain),
611
:challenge => challenge_key
612
}
613
end
614
optlm = { :client_challenge => client_challenge }
615
resp_lm = Rex::Proto::NTLM::Crypt::lmv2_response(arglm, optlm)
616
else
617
if self.is_pass_ntlm_hash?(pass)
618
arglm = {
619
:lm_hash => [ pass.upcase()[0,32] ].pack('H32'),
620
:challenge => challenge_key
621
}
622
else
623
arglm = {
624
:lm_hash => Rex::Proto::NTLM::Crypt::lm_hash(pass),
625
:challenge => challenge_key
626
}
627
end
628
resp_lm = Rex::Proto::NTLM::Crypt::lm_response(arglm)
629
end
630
resp_ntlm = ""
631
end
632
return resp_lm, resp_ntlm, client_challenge, ntlm_cli_challenge
633
end
634
635
# create the session key
636
def self.create_session_key(ntlmssp_flags, server_ntlmssp_flags, user, pass, domain, challenge_key,
637
client_challenge = '', ntlm_cli_challenge = '' , opt = {} )
638
639
usentlm2_session = opt[:usentlm2_session] != nil ? opt[:usentlm2_session] : true
640
use_ntlmv2 = opt[:use_ntlmv2] != nil ? opt[:use_ntlmv2] : false
641
send_lm = opt[:send_lm] != nil ? opt[:send_lm] : true
642
send_ntlm = opt[:send_ntlm] != nil ? opt[:send_ntlm] : true
643
use_lanman_key = opt[:use_lanman_key] != nil ? opt[:use_lanman_key] : false
644
645
# Create the sessionkey (aka signing key, aka mackey) and encrypted session key
646
# Server will decide for key_size and key_exchange
647
enc_session_key = ''
648
signing_key = ''
649
650
# Set default key size and key exchange values
651
key_size = 40
652
key_exchange = false
653
# Remove ntlmssp.negotiate56
654
ntlmssp_flags &= 0x7fffffff
655
# Remove ntlmssp.negotiatekeyexch
656
ntlmssp_flags &= 0xbfffffff
657
# Remove ntlmssp.negotiate128
658
ntlmssp_flags &= 0xdfffffff
659
# Check the keyexchange
660
if server_ntlmssp_flags & Rex::Proto::NTLM::Constants::NEGOTIATE_KEY_EXCH != 0 then
661
key_exchange = true
662
ntlmssp_flags |= Rex::Proto::NTLM::Constants::NEGOTIATE_KEY_EXCH
663
end
664
# Check 128bits
665
if server_ntlmssp_flags & Rex::Proto::NTLM::Constants::NEGOTIATE_128 != 0 then
666
key_size = 128
667
ntlmssp_flags |= Rex::Proto::NTLM::Constants::NEGOTIATE_128
668
ntlmssp_flags |= Rex::Proto::NTLM::Constants::NEGOTIATE_56
669
# Check 56bits
670
else
671
if server_ntlmssp_flags & Rex::Proto::NTLM::Constants::NEGOTIATE_56 != 0 then
672
key_size = 56
673
ntlmssp_flags |= Rex::Proto::NTLM::Constants::NEGOTIATE_56
674
end
675
end
676
# Generate the user session key
677
lanman_weak = false
678
if send_ntlm # Should be default
679
if usentlm2_session
680
if use_ntlmv2
681
if self.is_pass_ntlm_hash?(pass)
682
user_session_key = Rex::Proto::NTLM::Crypt::ntlmv2_user_session_key(user,
683
[ pass.upcase()[33,65] ].pack('H32'),
684
domain,
685
challenge_key, ntlm_cli_challenge,
686
{:pass_is_hash => true})
687
else
688
user_session_key = Rex::Proto::NTLM::Crypt::ntlmv2_user_session_key(user, pass, domain,
689
challenge_key, ntlm_cli_challenge)
690
end
691
else
692
if self.is_pass_ntlm_hash?(pass)
693
user_session_key = Rex::Proto::NTLM::Crypt::ntlm2_session_user_session_key([ pass.upcase()[33,65] ].pack('H32'),
694
challenge_key,
695
client_challenge,
696
{:pass_is_hash => true})
697
else
698
user_session_key = Rex::Proto::NTLM::Crypt::ntlm2_session_user_session_key(pass, challenge_key,
699
client_challenge)
700
end
701
end
702
else # lmv1/ntlmv1
703
# lanman_key may also be used without ntlm response but it is not so much used
704
# so we don't care about this feature
705
if send_lm && use_lanman_key
706
if self.is_pass_ntlm_hash?(pass)
707
user_session_key = Rex::Proto::NTLM::Crypt::lanman_session_key([ pass.upcase()[0,32] ].pack('H32'),
708
challenge_key,
709
{:pass_is_hash => true})
710
else
711
user_session_key = Rex::Proto::NTLM::Crypt::lanman_session_key(pass, challenge_key)
712
end
713
lanman_weak = true
714
715
716
else
717
if self.is_pass_ntlm_hash?(pass)
718
user_session_key = Rex::Proto::NTLM::Crypt::ntlmv1_user_session_key([ pass.upcase()[33,65] ].pack('H32'),
719
{:pass_is_hash => true})
720
else
721
user_session_key = Rex::Proto::NTLM::Crypt::ntlmv1_user_session_key(pass)
722
end
723
end
724
end
725
else
726
if usentlm2_session && use_ntlmv2
727
if self.is_pass_ntlm_hash?(pass)
728
user_session_key = Rex::Proto::NTLM::Crypt::lmv2_user_session_key(user, [ pass.upcase()[33,65] ].pack('H32'),
729
domain,
730
challenge_key, client_challenge,
731
{:pass_is_hash => true})
732
else
733
user_session_key = Rex::Proto::NTLM::Crypt::lmv2_user_session_key(user, pass, domain,
734
challenge_key, client_challenge)
735
end
736
else
737
if self.is_pass_ntlm_hash?(pass)
738
user_session_key = Rex::Proto::NTLM::Crypt::lmv1_user_session_key([ pass.upcase()[0,32] ].pack('H32'),
739
{:pass_is_hash => true})
740
else
741
user_session_key = Rex::Proto::NTLM::Crypt::lmv1_user_session_key(pass)
742
end
743
end
744
end
745
746
user_session_key = Rex::Proto::NTLM::Crypt::make_weak_sessionkey(user_session_key,key_size, lanman_weak)
747
748
# Sessionkey and encrypted session key
749
if key_exchange
750
signing_key = Rex::Text.rand_text(16)
751
enc_session_key = Rex::Proto::NTLM::Crypt::encrypt_sessionkey(signing_key, user_session_key)
752
else
753
signing_key = user_session_key
754
end
755
756
return signing_key, enc_session_key, ntlmssp_flags
757
end
758
end
759
end
760
761