librex 0.0.12 → 0.0.13

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.
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