librex 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. data/README.markdown +1 -1
  2. data/Rakefile +1 -1
  3. data/lib/rex/io/stream.rb +1 -1
  4. data/lib/rex/parser/nmap_xml.rb +4 -1
  5. data/lib/rex/post/meterpreter/extensions/stdapi/railgun.rb.ts.rb +6 -0
  6. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb.ut.rb +31 -0
  7. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/buffer_item.rb +47 -0
  8. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/buffer_item.rb.ut.rb +36 -0
  9. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/{model.rb → dll.rb} +4 -226
  10. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb +100 -0
  11. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb.ut.rb +42 -0
  12. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb +148 -0
  13. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb.ut.rb +127 -0
  14. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/multicall.rb +2 -1
  15. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb +3 -2
  16. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/util.rb +1 -1
  17. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb +75 -0
  18. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb.ut.rb +103 -0
  19. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +44 -0
  20. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +2 -2
  21. data/lib/rex/proto/dhcp/server.rb +7 -6
  22. data/lib/rex/proto/ntlm/utils.rb +505 -100
  23. data/lib/rex/proto/rfb/cipher.rb +6 -0
  24. data/lib/rex/proto/smb/client.rb +40 -332
  25. data/lib/rex/proto/smb/simpleclient.rb +3 -1
  26. data/lib/rex/proto/smb/utils.rb +0 -4
  27. metadata +14 -4
@@ -63,6 +63,7 @@ class Console::CommandDispatcher::Core
63
63
  "migrate" => "Migrate the server to another process",
64
64
  "use" => "Load a one or more meterpreter extensions",
65
65
  "quit" => "Terminate the meterpreter session",
66
+ "resource" => "Run the commands stored in a file",
66
67
  "read" => "Reads data from a channel",
67
68
  "run" => "Executes a meterpreter script or Post module",
68
69
  "bgrun" => "Executes a meterpreter script as a background thread",
@@ -598,6 +599,49 @@ class Console::CommandDispatcher::Core
598
599
  return true
599
600
  end
600
601
 
602
+ def cmd_resource_tabs(str, words)
603
+ return [] if words.length > 1
604
+
605
+ tab_complete_filenames(str, words)
606
+ end
607
+
608
+ def cmd_resource(*args)
609
+ if args.empty?
610
+ print(
611
+ "Usage: resource path1 path2" +
612
+ "Run the commands stored in the supplied files.\n")
613
+ return false
614
+ end
615
+ args.each do |glob|
616
+ files = ::Dir.glob(::File.expand_path(glob))
617
+ if files.empty?
618
+ print_error("No such file #{glob}")
619
+ next
620
+ end
621
+ files.each do |filename|
622
+ print_status("Reading #{filename}")
623
+ if (not ::File.readable?(filename))
624
+ print_error("Could not read file #{filename}")
625
+ next
626
+ else
627
+ ::File.open(filename, "r").each_line do |line|
628
+ next if line.strip.length < 1
629
+ next if line[0,1] == "#"
630
+ begin
631
+ print_status("Running #{line}")
632
+ client.console.run_single(line)
633
+ rescue ::Exception => e
634
+ print_error("Error Running Command #{line}: #{e.class} #{e}")
635
+ end
636
+
637
+ end
638
+ end
639
+ end
640
+ end
641
+ end
642
+
643
+
644
+
601
645
  @@client_extension_search_paths = [ ::File.join(Rex::Root, "post", "meterpreter", "ui", "console", "command_dispatcher") ]
602
646
 
603
647
  def self.add_client_extension_search_path(path)
@@ -457,8 +457,8 @@ class Console::CommandDispatcher::Stdapi::Sys
457
457
  #
458
458
  def cmd_sysinfo(*args)
459
459
  info = client.sys.config.sysinfo
460
- width = 0
461
- info.keys.each { |k| width = k.length if k.length > width }
460
+ width = "Meterpreter".length
461
+ info.keys.each { |k| width = k.length if k.length > width and info[k] }
462
462
 
463
463
  info.each_pair do |key, value|
464
464
  print_line("#{key.ljust(width+1)}: #{value}") if value
@@ -1,4 +1,4 @@
1
- # $Id: server.rb 11745 2011-02-12 22:25:02Z jduck $
1
+ # $Id: server.rb 12030 2011-03-20 00:33:02Z scriptjunkie $
2
2
 
3
3
  require 'rex/socket'
4
4
  require 'rex/proto/dhcp'
@@ -236,11 +236,12 @@ protected
236
236
  pkt << buf[1..7] #hwtype, hwlen, hops, txid
237
237
  pkt << "\x00\x00\x00\x00" #elapsed, flags
238
238
  pkt << clientip
239
-
240
- # give next ip address (not super reliable high volume but it should work for a basic server)
241
- self.current_ip += 1
242
- if self.current_ip > self.end_ip
243
- self.current_ip = self.start_ip
239
+ if messageType == DHCPDiscover
240
+ # give next ip address (not super reliable high volume but it should work for a basic server)
241
+ self.current_ip += 1
242
+ if self.current_ip > self.end_ip
243
+ self.current_ip = self.start_ip
244
+ end
244
245
  end
245
246
  pkt << Rex::Socket.addr_iton(self.current_ip)
246
247
  pkt << self.ipstring #next server ip
@@ -1,8 +1,14 @@
1
+ require 'rex/proto/ntlm/constants'
2
+ require 'rex/proto/ntlm/crypt'
3
+
1
4
  module Rex
2
5
  module Proto
3
6
  module NTLM
4
7
  class Utils
5
8
 
9
+ CONST = Rex::Proto::NTLM::Constants
10
+ CRYPT = Rex::Proto::NTLM::Crypt
11
+
6
12
  #duplicate from lib/rex/proto/smb/utils cause we only need this fonction from Rex::Proto::SMB::Utils
7
13
  # Convert a unix timestamp to a 64-bit signed server time
8
14
  def self.time_unix_to_smb(unix_time)
@@ -12,6 +18,11 @@ class Utils
12
18
  return [thi, tlo]
13
19
  end
14
20
 
21
+ # Determine whether the password is a known hash format
22
+ def self.is_pass_ntlm_hash?(str)
23
+ str.downcase =~ /^[0-9a-f]{32}:[0-9a-f]{32}$/
24
+ end
25
+
15
26
  #
16
27
  # Prepends an ASN1 formatted length field to a piece of data
17
28
  #
@@ -116,6 +127,26 @@ class Utils
116
127
  return blob
117
128
  end
118
129
 
130
+ # BLOB without GSS usefull for ntlmssp type 1 message
131
+ def self.make_ntlmssp_blob_init(domain = 'WORKGROUP', name = 'WORKSTATION', flags=0x80201)
132
+ blob = "NTLMSSP\x00" +
133
+ [1, flags].pack('VV') +
134
+
135
+ [
136
+ domain.length, #length
137
+ domain.length, #max length
138
+ 32
139
+ ].pack('vvV') +
140
+
141
+ [
142
+ name.length, #length
143
+ name.length, #max length
144
+ domain.length + 32
145
+ ].pack('vvV') +
146
+
147
+ domain + name
148
+ return blob
149
+ end
119
150
 
120
151
  # GSS BLOB usefull for ntlmssp type 1 message
121
152
  def self.make_ntlmssp_secblob_init(domain = 'WORKGROUP', name = 'WORKSTATION', flags=0x80201)
@@ -135,22 +166,7 @@ class Utils
135
166
  ) +
136
167
  "\xa2" + self.asn1encode(
137
168
  "\x04" + self.asn1encode(
138
- "NTLMSSP\x00" +
139
- [1, flags].pack('VV') +
140
-
141
- [
142
- domain.length, #length
143
- domain.length, #max length
144
- 32
145
- ].pack('vvV') +
146
-
147
- [
148
- name.length, #length
149
- name.length, #max length
150
- domain.length + 32
151
- ].pack('vvV') +
152
-
153
- domain + name
169
+ make_ntlmssp_blob_init(domain, name, flags)
154
170
  )
155
171
  )
156
172
  )
@@ -161,33 +177,6 @@ class Utils
161
177
  end
162
178
 
163
179
 
164
- # GSS BLOB usefull for ntlmssp type 2 message
165
- def self.make_ntlmssp_secblob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
166
-
167
- blob =
168
- "\xa1" + self.asn1encode(
169
- "\x30" + self.asn1encode(
170
- "\xa0" + self.asn1encode(
171
- "\x0a" + self.asn1encode(
172
- "\x01"
173
- )
174
- ) +
175
- "\xa1" + self.asn1encode(
176
- "\x06" + self.asn1encode(
177
- "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
178
- )
179
- ) +
180
- "\xa2" + self.asn1encode(
181
- "\x04" + self.asn1encode(
182
- make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
183
- )
184
- )
185
- )
186
- )
187
-
188
- return blob
189
- end
190
-
191
180
  # BLOB without GSS usefull for ntlm type 2 message
192
181
  def self.make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
193
182
 
@@ -219,10 +208,35 @@ class Utils
219
208
  return blob
220
209
  end
221
210
 
211
+ # GSS BLOB usefull for ntlmssp type 2 message
212
+ def self.make_ntlmssp_secblob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
213
+
214
+ blob =
215
+ "\xa1" + self.asn1encode(
216
+ "\x30" + self.asn1encode(
217
+ "\xa0" + self.asn1encode(
218
+ "\x0a" + self.asn1encode(
219
+ "\x01"
220
+ )
221
+ ) +
222
+ "\xa1" + self.asn1encode(
223
+ "\x06" + self.asn1encode(
224
+ "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
225
+ )
226
+ ) +
227
+ "\xa2" + self.asn1encode(
228
+ "\x04" + self.asn1encode(
229
+ make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
230
+ )
231
+ )
232
+ )
233
+ )
222
234
 
223
- # GSS BLOB Usefull for ntlmssp type 3 message
224
- def self.make_ntlmssp_secblob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201)
235
+ return blob
236
+ end
225
237
 
238
+ # BLOB without GSS Usefull for ntlmssp type 3 message
239
+ def self.make_ntlmssp_blob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201)
226
240
  lm ||= "\x00" * 24
227
241
  ntlm ||= "\x00" * 24
228
242
 
@@ -232,59 +246,67 @@ class Utils
232
246
  session = enc_session_key
233
247
 
234
248
  ptr = 64
249
+
250
+ blob = "NTLMSSP\x00" +
251
+ [ 3 ].pack('V') +
252
+
253
+ [ # Lan Manager Response
254
+ lm.length,
255
+ lm.length,
256
+ (ptr)
257
+ ].pack('vvV') +
258
+
259
+ [ # NTLM Manager Response
260
+ ntlm.length,
261
+ ntlm.length,
262
+ (ptr += lm.length)
263
+ ].pack('vvV') +
264
+
265
+ [ # Domain Name
266
+ domain_uni.length,
267
+ domain_uni.length,
268
+ (ptr += ntlm.length)
269
+ ].pack('vvV') +
270
+
271
+ [ # Username
272
+ user_uni.length,
273
+ user_uni.length,
274
+ (ptr += domain_uni.length)
275
+ ].pack('vvV') +
276
+
277
+ [ # Hostname
278
+ name_uni.length,
279
+ name_uni.length,
280
+ (ptr += user_uni.length)
281
+ ].pack('vvV') +
282
+
283
+ [ # Session Key (none)
284
+ session.length,
285
+ session.length,
286
+ (ptr += name_uni.length)
287
+ ].pack('vvV') +
288
+
289
+ [ flags ].pack('V') +
290
+
291
+ lm +
292
+ ntlm +
293
+ domain_uni +
294
+ user_uni +
295
+ name_uni +
296
+ session + "\x00"
297
+ return blob
298
+
299
+ end
300
+
301
+ # GSS BLOB Usefull for ntlmssp type 3 message
302
+ def self.make_ntlmssp_secblob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201)
303
+
235
304
  blob =
236
305
  "\xa1" + self.asn1encode(
237
306
  "\x30" + self.asn1encode(
238
307
  "\xa2" + self.asn1encode(
239
308
  "\x04" + self.asn1encode(
240
-
241
- "NTLMSSP\x00" +
242
- [ 3 ].pack('V') +
243
-
244
- [ # Lan Manager Response
245
- lm.length,
246
- lm.length,
247
- (ptr)
248
- ].pack('vvV') +
249
-
250
- [ # NTLM Manager Response
251
- ntlm.length,
252
- ntlm.length,
253
- (ptr += lm.length)
254
- ].pack('vvV') +
255
-
256
- [ # Domain Name
257
- domain_uni.length,
258
- domain_uni.length,
259
- (ptr += ntlm.length)
260
- ].pack('vvV') +
261
-
262
- [ # Username
263
- user_uni.length,
264
- user_uni.length,
265
- (ptr += domain_uni.length)
266
- ].pack('vvV') +
267
-
268
- [ # Hostname
269
- name_uni.length,
270
- name_uni.length,
271
- (ptr += user_uni.length)
272
- ].pack('vvV') +
273
-
274
- [ # Session Key (none)
275
- session.length,
276
- session.length,
277
- (ptr += name_uni.length)
278
- ].pack('vvV') +
279
-
280
- [ flags ].pack('V') +
281
-
282
- lm +
283
- ntlm +
284
- domain_uni +
285
- user_uni +
286
- name_uni +
287
- session + "\x00"
309
+ make_ntlmssp_blob_auth(domain, name, user, lm, ntlm, enc_session_key, flags )
288
310
  )
289
311
  )
290
312
  )
@@ -308,13 +330,107 @@ class Utils
308
330
  return blob
309
331
  end
310
332
 
333
+ # Return the correct ntlmflags upon the configuration
334
+ def self.make_ntlm_flags(opt = {})
335
+
336
+ signing = opt[:signing] != nil ? opt[:signing] : false
337
+ usentlm2_session = opt[:usentlm2_session] != nil ? opt[:usentlm2_session] : true
338
+ use_ntlmv2 = opt[:use_ntlmv2] != nil ? opt[:use_ntlmv2] : false
339
+ send_lm = opt[:send_lm] != nil ? opt[:send_lm] : true
340
+ send_ntlm = opt[:send_ntlm] != nil ? opt[:send_ntlm] : true
341
+ use_lanman_key = opt[:use_lanman_key] != nil ? opt[:use_lanman_key] : false
342
+
343
+ if signing
344
+ ntlmssp_flags = 0xe2088215
345
+ else
346
+
347
+ ntlmssp_flags = 0xa2080205
348
+ end
349
+
350
+ if usentlm2_session
351
+ if use_ntlmv2
352
+ #set Negotiate Target Info
353
+ ntlmssp_flags |= CONST::NEGOTIATE_TARGET_INFO
354
+ end
355
+
356
+ else
357
+ #remove the ntlm2_session flag
358
+ ntlmssp_flags &= 0xfff7ffff
359
+ #set lanmanflag only when lm and ntlm are sent
360
+ if send_lm
361
+ ntlmssp_flags |= CONST::NEGOTIATE_LMKEY if use_lanman_key
362
+ end
363
+ end
364
+
365
+ #we can also downgrade ntlm2_session when we send only lmv1
366
+ ntlmssp_flags &= 0xfff7ffff if usentlm2_session && (not use_ntlmv2) && (not send_ntlm)
367
+
368
+ return ntlmssp_flags
369
+ end
370
+
371
+
372
+ # Parse an ntlm type 2 challenge blob and return usefull data
373
+ def self.parse_ntlm_type_2_blob(blob)
374
+ data = {}
375
+ # Extract the NTLM challenge key the lazy way
376
+ cidx = blob.index("NTLMSSP\x00\x02\x00\x00\x00")
377
+
378
+ if not cidx
379
+ raise XCEPT::NTLM2MissingChallenge
380
+ end
381
+
382
+ data[:challenge_key] = blob[cidx + 24, 8]
383
+
384
+ data[:server_ntlmssp_flags] = blob[cidx + 20, 4].unpack("V")[0]
385
+
386
+ # Extract the address list from the blob
387
+ alist_len,alist_mlen,alist_off = blob[cidx + 40, 8].unpack("vvV")
388
+ alist_buf = blob[cidx + alist_off, alist_len]
389
+
390
+ while(alist_buf.length > 0)
391
+ atype, alen = alist_buf.slice!(0,4).unpack('vv')
392
+ break if atype == 0x00
393
+ addr = alist_buf.slice!(0, alen)
394
+ case atype
395
+ when 1
396
+ #netbios name
397
+ data[:default_name] = addr.gsub("\x00", '')
398
+ when 2
399
+ #netbios domain
400
+ data[:default_domain] = addr.gsub("\x00", '')
401
+ when 3
402
+ #dns name
403
+ data[:dns_host_name] = addr.gsub("\x00", '')
404
+ when 4
405
+ #dns domain
406
+ data[:dns_domain_name] = addr.gsub("\x00", '')
407
+ when 5
408
+ #The FQDN of the forest.
409
+ when 6
410
+ #A 32-bit value indicating server or client configuration
411
+ when 7
412
+ #Client time
413
+ data[:chall_MsvAvTimestamp] = addr
414
+ when 8
415
+ #A Restriction_Encoding structure
416
+ when 9
417
+ #The SPN of the target server.
418
+ when 10
419
+ #A channel bindings hash.
420
+ end
421
+ end
422
+ return data
423
+ end
424
+
311
425
  # This function return an ntlmv2 client challenge
312
- def self.make_ntlmv2_clientchallenge(win_domain, win_name, dns_domain, dns_name, client_challenge = nil, chall_MsvAvTimestamp = nil)
426
+ # This is a partial implementation, full description is in [MS-NLMP].pdf around 3.1.5.2.1 :-/
427
+ def self.make_ntlmv2_clientchallenge(win_domain, win_name, dns_domain, dns_name,
428
+ client_challenge = nil, chall_MsvAvTimestamp = nil, spnopt = {})
313
429
 
314
430
  client_challenge ||= Rex::Text.rand_text(8)
315
431
  # We have to set the timestamps here to the one in the challenge message from server if present
316
- # If we don't do that, recent server like seven will send a STATUS_INVALID_PARAMETER error packet
317
- timestamp = chall_MsvAvTimestamp != nil ? chall_MsvAvTimestamp : self.time_unix_to_smb(Time.now.to_i).reverse.pack("VV")
432
+ # If we don't do that, recent server like Seven/2008 will send a STATUS_INVALID_PARAMETER error packet
433
+ timestamp = chall_MsvAvTimestamp != '' ? chall_MsvAvTimestamp : self.time_unix_to_smb(Time.now.to_i).reverse.pack("VV")
318
434
  # Make those values unicode as requested
319
435
  win_domain = Rex::Text.to_unicode(win_domain)
320
436
  win_name = Rex::Text.to_unicode(win_name)
@@ -328,6 +444,14 @@ class Utils
328
444
  addr_list << [3, dns_name.length].pack('vv') + dns_name
329
445
  addr_list << [7, 8].pack('vv') + timestamp
330
446
 
447
+ # Windows Seven / 2008r2 Request this type if in local security policies,
448
+ # Microsoft network server : Server SPN target name validation level is set to <Required from client>
449
+ # otherwise it send an STATUS_ACCESS_DENIED packet
450
+ if spnopt[:use_spn]
451
+ spn= Rex::Text.to_unicode("cifs/#{spnopt[:name] || 'unknow'}")
452
+ addr_list << [9, spn.length].pack('vv') + spn
453
+ end
454
+
331
455
  # MAY BE USEFUL FOR FUTURE
332
456
  # Seven (client) add at least one more av that is of type MsAvRestrictions (8)
333
457
  # maybe this will be usefull with future windows OSs but has no use at all for the moment afaik
@@ -338,10 +462,6 @@ class Utils
338
462
  # Seven (client) and maybe others versions also add an av of type MsvChannelBindings (10) but the hash is "\x00" * 16
339
463
  # addr_list << [10, 16].pack('vv') + "\x00" * 16
340
464
 
341
- # Seven and maybe other versions also add an av of type MsvAvTargetName(9) with value cifs/target(_ip)
342
- # implementing it will necessary require knowing the target here, todo... :-/
343
- # spn= Rex::Text.to_unicode("cifs/RHOST")
344
- # addr_list << [9, spn.length].pack('vv') + spn
345
465
 
346
466
  addr_list << [0, 0].pack('vv')
347
467
  ntlm_clientchallenge = [1,1,0,0].pack("CCvV") + #RespType, HiRespType, Reserved1, Reserved2
@@ -352,6 +472,291 @@ class Utils
352
472
 
353
473
  end
354
474
 
475
+ # create lm/ntlm responses
476
+ def self.create_lm_ntlm_responses(user, pass, challenge_key, domain = '', default_name = '', default_domain = '',
477
+ dns_host_name = '', dns_domain_name = '', chall_MsvAvTimestamp = nil, spnopt = {}, opt = {} )
478
+
479
+ usentlm2_session = opt[:usentlm2_session] != nil ? opt[:usentlm2_session] : true
480
+ use_ntlmv2 = opt[:use_ntlmv2] != nil ? opt[:use_ntlmv2] : false
481
+ send_lm = opt[:send_lm] != nil ? opt[:send_lm] : true
482
+ send_ntlm = opt[:send_ntlm] != nil ? opt[:send_ntlm] : true
483
+
484
+ #calculate the lm/ntlm response
485
+ resp_lm = "\x00" * 24
486
+ resp_ntlm = "\x00" * 24
487
+
488
+ client_challenge = Rex::Text.rand_text(8)
489
+ ntlm_cli_challenge = ''
490
+ if send_ntlm #should be default
491
+ if usentlm2_session
492
+ if use_ntlmv2
493
+ ntlm_cli_challenge = self.make_ntlmv2_clientchallenge(default_domain, default_name, dns_domain_name,
494
+ dns_host_name,client_challenge ,
495
+ chall_MsvAvTimestamp, spnopt)
496
+ if self.is_pass_ntlm_hash?(pass)
497
+ argntlm = {
498
+ :ntlmv2_hash => CRYPT::ntlmv2_hash(
499
+ user,
500
+ [ pass.upcase()[33,65] ].pack('H32'),
501
+ domain,{:pass_is_hash => true}
502
+ ),
503
+ :challenge => challenge_key
504
+ }
505
+ else
506
+ argntlm = {
507
+ :ntlmv2_hash => CRYPT::ntlmv2_hash(user, pass, domain),
508
+ :challenge => challenge_key
509
+ }
510
+ end
511
+
512
+ optntlm = { :nt_client_challenge => ntlm_cli_challenge}
513
+ ntlmv2_response = CRYPT::ntlmv2_response(argntlm,optntlm)
514
+ resp_ntlm = ntlmv2_response
515
+
516
+ if send_lm
517
+ if self.is_pass_ntlm_hash?(pass)
518
+ arglm = {
519
+ :ntlmv2_hash => CRYPT::ntlmv2_hash(
520
+ user,
521
+ [ pass.upcase()[33,65] ].pack('H32'),
522
+ domain,{:pass_is_hash => true}
523
+ ),
524
+ :challenge => challenge_key
525
+ }
526
+ else
527
+ arglm = {
528
+ :ntlmv2_hash => CRYPT::ntlmv2_hash(user,pass, domain),
529
+ :challenge => challenge_key
530
+ }
531
+ end
532
+
533
+ optlm = { :client_challenge => client_challenge }
534
+ resp_lm = CRYPT::lmv2_response(arglm, optlm)
535
+ else
536
+ resp_lm = "\x00" * 24
537
+ end
538
+
539
+ else # ntlm2_session
540
+ if self.is_pass_ntlm_hash?(pass)
541
+ argntlm = {
542
+ :ntlm_hash => [ pass.upcase()[33,65] ].pack('H32'),
543
+ :challenge => challenge_key
544
+ }
545
+ else
546
+ argntlm = {
547
+ :ntlm_hash => CRYPT::ntlm_hash(pass),
548
+ :challenge => challenge_key
549
+ }
550
+ end
551
+
552
+ optntlm = { :client_challenge => client_challenge}
553
+ resp_ntlm = CRYPT::ntlm2_session(argntlm,optntlm).join[24,24]
554
+
555
+ # Generate the fake LANMAN hash
556
+ resp_lm = client_challenge + ("\x00" * 16)
557
+ end
558
+
559
+ else # we use lmv1/ntlmv1
560
+ if self.is_pass_ntlm_hash?(pass)
561
+ argntlm = {
562
+ :ntlm_hash => [ pass.upcase()[33,65] ].pack('H32'),
563
+ :challenge => challenge_key
564
+ }
565
+ else
566
+ argntlm = {
567
+ :ntlm_hash => CRYPT::ntlm_hash(pass),
568
+ :challenge => challenge_key
569
+ }
570
+ end
571
+
572
+ resp_ntlm = CRYPT::ntlm_response(argntlm)
573
+ if send_lm
574
+ if self.is_pass_ntlm_hash?(pass)
575
+ arglm = {
576
+ :lm_hash => [ pass.upcase()[0,32] ].pack('H32'),
577
+ :challenge => challenge_key
578
+ }
579
+ else
580
+ arglm = {
581
+ :lm_hash => CRYPT::lm_hash(pass),
582
+ :challenge => challenge_key
583
+ }
584
+ end
585
+ resp_lm = CRYPT::lm_response(arglm)
586
+ else
587
+ #when windows does not send lm in ntlmv1 type response,
588
+ # it gives lm response the same value as ntlm response
589
+ resp_lm = resp_ntlm
590
+ end
591
+ end
592
+ else #send_ntlm = false
593
+ #lmv2
594
+ if usentlm2_session && use_ntlmv2
595
+ if self.is_pass_ntlm_hash?(pass)
596
+ arglm = {
597
+ :ntlmv2_hash => CRYPT::ntlmv2_hash(
598
+ user,
599
+ [ pass.upcase()[33,65] ].pack('H32'),
600
+ domain,{:pass_is_hash => true}
601
+ ),
602
+ :challenge => challenge_key
603
+ }
604
+ else
605
+ arglm = {
606
+ :ntlmv2_hash => CRYPT::ntlmv2_hash(user,pass, domain),
607
+ :challenge => challenge_key
608
+ }
609
+ end
610
+ optlm = { :client_challenge => client_challenge }
611
+ resp_lm = CRYPT::lmv2_response(arglm, optlm)
612
+ else
613
+ if self.is_pass_ntlm_hash?(pass)
614
+ arglm = {
615
+ :lm_hash => [ pass.upcase()[0,32] ].pack('H32'),
616
+ :challenge => challenge_key
617
+ }
618
+ else
619
+ arglm = {
620
+ :lm_hash => CRYPT::lm_hash(pass),
621
+ :challenge => challenge_key
622
+ }
623
+ end
624
+ resp_lm = CRYPT::lm_response(arglm)
625
+ end
626
+ resp_ntlm = ""
627
+ end
628
+ return resp_lm, resp_ntlm, client_challenge, ntlm_cli_challenge
629
+ end
630
+
631
+ # create the session key
632
+ def self.create_session_key(server_ntlmssp_flags, user, pass, domain, challenge_key,
633
+ client_challenge = '', ntlm_cli_challenge = '' , opt = {} )
634
+
635
+ usentlm2_session = opt[:usentlm2_session] != nil ? opt[:usentlm2_session] : true
636
+ use_ntlmv2 = opt[:use_ntlmv2] != nil ? opt[:use_ntlmv2] : false
637
+ send_lm = opt[:send_lm] != nil ? opt[:send_lm] : true
638
+ send_ntlm = opt[:send_ntlm] != nil ? opt[:send_ntlm] : true
639
+ use_lanman_key = opt[:use_lanman_key] != nil ? opt[:use_lanman_key] : false
640
+
641
+ # Create the sessionkey (aka signing key, aka mackey) and encrypted session key
642
+ # Server will decide for key_size and key_exchange
643
+ enc_session_key = ''
644
+ signing_key = ''
645
+
646
+ # Set default key size and key exchange values
647
+ key_size = 40
648
+ key_exchange = false
649
+ # Remove ntlmssp.negotiate56
650
+ ntlmssp_flags &= 0x7fffffff
651
+ # Remove ntlmssp.negotiatekeyexch
652
+ ntlmssp_flags &= 0xbfffffff
653
+ # Remove ntlmssp.negotiate128
654
+ ntlmssp_flags &= 0xdfffffff
655
+ # Check the keyexchange
656
+ if server_ntlmssp_flags & CONST::NEGOTIATE_KEY_EXCH != 0 then
657
+ key_exchange = true
658
+ ntlmssp_flags |= CONST::NEGOTIATE_KEY_EXCH
659
+ end
660
+ # Check 128bits
661
+ if server_ntlmssp_flags & CONST::NEGOTIATE_128 != 0 then
662
+ key_size = 128
663
+ ntlmssp_flags |= CONST::NEGOTIATE_128
664
+ ntlmssp_flags |= CONST::NEGOTIATE_56
665
+ # Check 56bits
666
+ else
667
+ if server_ntlmssp_flags & CONST::NEGOTIATE_56 != 0 then
668
+ key_size = 56
669
+ ntlmssp_flags |= CONST::NEGOTIATE_56
670
+ end
671
+ end
672
+
673
+ # Generate the user session key
674
+ lanman_weak = false
675
+ if send_ntlm # Should be default
676
+ if usentlm2_session
677
+ if use_ntlmv2
678
+ if self.is_pass_ntlm_hash?(pass)
679
+ user_session_key = CRYPT::ntlmv2_user_session_key(user,
680
+ [ pass.upcase()[33,65] ].pack('H32'),
681
+ domain,
682
+ challenge_key, ntlm_cli_challenge,
683
+ {:pass_is_hash => true})
684
+ else
685
+ user_session_key = CRYPT::ntlmv2_user_session_key(user, pass, domain,
686
+ challenge_key, ntlm_cli_challenge)
687
+ end
688
+ else
689
+ if self.is_pass_ntlm_hash?(pass)
690
+ user_session_key = CRYPT::ntlm2_session_user_session_key([ pass.upcase()[33,65] ].pack('H32'),
691
+ challenge_key,
692
+ client_challenge,
693
+ {:pass_is_hash => true})
694
+ else
695
+ user_session_key = CRYPT::ntlm2_session_user_session_key(pass, challenge_key,
696
+ client_challenge)
697
+ end
698
+ end
699
+ else # lmv1/ntlmv1
700
+ # lanman_key may also be used without ntlm response but it is not so much used
701
+ # so we don't care about this feature
702
+ if send_lm && use_lanman_key
703
+ if self.is_pass_ntlm_hash?(pass)
704
+ user_session_key = CRYPT::lanman_session_key([ pass.upcase()[0,32] ].pack('H32'),
705
+ challenge_key,
706
+ {:pass_is_hash => true})
707
+ else
708
+ user_session_key = CRYPT::lanman_session_key(pass, challenge_key)
709
+ end
710
+ lanman_weak = true
711
+
712
+
713
+ else
714
+ if self.is_pass_ntlm_hash?(pass)
715
+ user_session_key = CRYPT::ntlmv1_user_session_key([ pass.upcase()[33,65] ].pack('H32'),
716
+ {:pass_is_hash => true})
717
+ else
718
+ user_session_key = CRYPT::ntlmv1_user_session_key(pass)
719
+ end
720
+ end
721
+ end
722
+ else
723
+ if usentlm2_session && use_ntlmv2
724
+ if self.is_pass_ntlm_hash?(pass)
725
+ user_session_key = CRYPT::lmv2_user_session_key(user, [ pass.upcase()[33,65] ].pack('H32'),
726
+ domain,
727
+ challenge_key, client_challenge,
728
+ {:pass_is_hash => true})
729
+ else
730
+ user_session_key = CRYPT::lmv2_user_session_key(user, pass, domain,
731
+ challenge_key, client_challenge)
732
+ end
733
+ else
734
+ if self.is_pass_ntlm_hash?(pass)
735
+ user_session_key = CRYPT::lmv1_user_session_key([ pass.upcase()[0,32] ].pack('H32'),
736
+ {:pass_is_hash => true})
737
+ else
738
+ user_session_key = CRYPT::lmv1_user_session_key(pass)
739
+ end
740
+ end
741
+ end
742
+
743
+ user_session_key = CRYPT::make_weak_sessionkey(user_session_key,key_size, lanman_weak)
744
+
745
+ # Sessionkey and encrypted session key
746
+ if key_exchange
747
+ signing_key = Rex::Text.rand_text(16)
748
+ enc_session_key = CRYPT::encrypt_sessionkey(signing_key, user_session_key)
749
+ else
750
+ signing_key = user_session_key
751
+ end
752
+
753
+ return signing_key, enc_session_key
754
+
755
+
756
+ end
757
+
758
+
759
+
355
760
  end
356
761
  end
357
762
  end