lib/rex/proto/ntlm/utils.rb in librex-0.0.68 vs lib/rex/proto/ntlm/utils.rb in librex-0.0.70
- old
+ new
@@ -6,757 +6,757 @@
module Rex
module Proto
module NTLM
class Utils
- CONST = Rex::Proto::NTLM::Constants
- CRYPT = Rex::Proto::NTLM::Crypt
- XCEPT = Rex::Proto::NTLM::Exceptions
+ CONST = Rex::Proto::NTLM::Constants
+ CRYPT = Rex::Proto::NTLM::Crypt
+ XCEPT = Rex::Proto::NTLM::Exceptions
#duplicate from lib/rex/proto/smb/utils cause we only need this fonction from Rex::Proto::SMB::Utils
- # Convert a unix timestamp to a 64-bit signed server time
- def self.time_unix_to_smb(unix_time)
- t64 = (unix_time + 11644473600) * 10000000
- thi = (t64 & 0xffffffff00000000) >> 32
- tlo = (t64 & 0x00000000ffffffff)
- return [thi, tlo]
- end
+ # Convert a unix timestamp to a 64-bit signed server time
+ def self.time_unix_to_smb(unix_time)
+ t64 = (unix_time + 11644473600) * 10000000
+ thi = (t64 & 0xffffffff00000000) >> 32
+ tlo = (t64 & 0x00000000ffffffff)
+ return [thi, tlo]
+ end
- # Determine whether the password is a known hash format
- def self.is_pass_ntlm_hash?(str)
- str.downcase =~ /^[0-9a-f]{32}:[0-9a-f]{32}$/
- end
+ # Determine whether the password is a known hash format
+ def self.is_pass_ntlm_hash?(str)
+ str.downcase =~ /^[0-9a-f]{32}:[0-9a-f]{32}$/
+ end
- #
- # Prepends an ASN1 formatted length field to a piece of data
- #
- def self.asn1encode(str = '')
- res = ''
+ #
+ # Prepends an ASN1 formatted length field to a piece of data
+ #
+ def self.asn1encode(str = '')
+ res = ''
- # If the high bit of the first byte is 1, it contains the number of
- # length bytes that follow
+ # If the high bit of the first byte is 1, it contains the number of
+ # length bytes that follow
- case str.length
- when 0 .. 0x7F
- res = [str.length].pack('C') + str
- when 0x80 .. 0xFF
- res = [0x81, str.length].pack('CC') + str
- when 0x100 .. 0xFFFF
- res = [0x82, str.length].pack('Cn') + str
- when 0x10000 .. 0xffffff
- res = [0x83, str.length >> 16, str.length & 0xFFFF].pack('CCn') + str
- when 0x1000000 .. 0xffffffff
- res = [0x84, str.length].pack('CN') + str
- else
- raise "ASN1 str too long"
- end
- return res
- end
+ case str.length
+ when 0 .. 0x7F
+ res = [str.length].pack('C') + str
+ when 0x80 .. 0xFF
+ res = [0x81, str.length].pack('CC') + str
+ when 0x100 .. 0xFFFF
+ res = [0x82, str.length].pack('Cn') + str
+ when 0x10000 .. 0xffffff
+ res = [0x83, str.length >> 16, str.length & 0xFFFF].pack('CCn') + str
+ when 0x1000000 .. 0xffffffff
+ res = [0x84, str.length].pack('CN') + str
+ else
+ raise "ASN1 str too long"
+ end
+ return res
+ end
- # GSS functions
+ # GSS functions
- # GSS BLOB usefull for SMB_NEGOCIATE_RESPONSE message
- # mechTypes: 2 items :
- # -MechType: 1.3.6.1.4.1.311.2.2.30 (SNMPv2-SMI::enterprises.311.2.2.30)
- # -MechType: 1.3.6.1.4.1.311.2.2.10 (NTLMSSP - Microsoft NTLM Security Support Provider)
- #
- # this is the default on Win7
- def self.make_simple_negotiate_secblob_resp
- blob =
- "\x60" + self.asn1encode(
- "\x06" + self.asn1encode(
- "\x2b\x06\x01\x05\x05\x02"
- ) +
- "\xa0" + self.asn1encode(
- "\x30" + self.asn1encode(
- "\xa0" + self.asn1encode(
- "\x30" + self.asn1encode(
- "\x06" + self.asn1encode(
- "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
- )
- )
- )
- )
- )
- )
+ # GSS BLOB usefull for SMB_NEGOCIATE_RESPONSE message
+ # mechTypes: 2 items :
+ # -MechType: 1.3.6.1.4.1.311.2.2.30 (SNMPv2-SMI::enterprises.311.2.2.30)
+ # -MechType: 1.3.6.1.4.1.311.2.2.10 (NTLMSSP - Microsoft NTLM Security Support Provider)
+ #
+ # this is the default on Win7
+ def self.make_simple_negotiate_secblob_resp
+ blob =
+ "\x60" + self.asn1encode(
+ "\x06" + self.asn1encode(
+ "\x2b\x06\x01\x05\x05\x02"
+ ) +
+ "\xa0" + self.asn1encode(
+ "\x30" + self.asn1encode(
+ "\xa0" + self.asn1encode(
+ "\x30" + self.asn1encode(
+ "\x06" + self.asn1encode(
+ "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
+ )
+ )
+ )
+ )
+ )
+ )
- return blob
- end
+ return blob
+ end
- # GSS BLOB usefull for SMB_NEGOCIATE_RESPONSE message
- # mechTypes: 4 items :
- # MechType: 1.2.840.48018.1.2.2 (MS KRB5 - Microsoft Kerberos 5)
- # MechType: 1.2.840.113554.1.2.2 (KRB5 - Kerberos 5)
- # MechType: 1.2.840.113554.1.2.2.3 (KRB5 - Kerberos 5 - User to User)
- # MechType: 1.3.6.1.4.1.311.2.2.10 (NTLMSSP - Microsoft NTLM Security Support Provider)
- # mechListMIC:
- # principal: account@domain
- def self.make_negotiate_secblob_resp(account, domain)
- blob =
- "\x60" + self.asn1encode(
- "\x06" + self.asn1encode(
- "\x2b\x06\x01\x05\x05\x02"
- ) +
- "\xa0" + self.asn1encode(
- "\x30" + self.asn1encode(
- "\xa0" + self.asn1encode(
- "\x30" + self.asn1encode(
- "\x06" + self.asn1encode(
- "\x2a\x86\x48\x82\xf7\x12\x01\x02\x02"
- ) +
- "\x06" + self.asn1encode(
- "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"
- ) +
- "\x06" + self.asn1encode(
- "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x03"
- ) +
- "\x06" + self.asn1encode(
- "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
- )
- )
- ) +
- "\xa3" + self.asn1encode(
- "\x30" + self.asn1encode(
- "\xa0" + self.asn1encode(
- "\x1b" + self.asn1encode(
- account + '@' + domain
- )
- )
- )
- )
- )
- )
- )
+ # GSS BLOB usefull for SMB_NEGOCIATE_RESPONSE message
+ # mechTypes: 4 items :
+ # MechType: 1.2.840.48018.1.2.2 (MS KRB5 - Microsoft Kerberos 5)
+ # MechType: 1.2.840.113554.1.2.2 (KRB5 - Kerberos 5)
+ # MechType: 1.2.840.113554.1.2.2.3 (KRB5 - Kerberos 5 - User to User)
+ # MechType: 1.3.6.1.4.1.311.2.2.10 (NTLMSSP - Microsoft NTLM Security Support Provider)
+ # mechListMIC:
+ # principal: account@domain
+ def self.make_negotiate_secblob_resp(account, domain)
+ blob =
+ "\x60" + self.asn1encode(
+ "\x06" + self.asn1encode(
+ "\x2b\x06\x01\x05\x05\x02"
+ ) +
+ "\xa0" + self.asn1encode(
+ "\x30" + self.asn1encode(
+ "\xa0" + self.asn1encode(
+ "\x30" + self.asn1encode(
+ "\x06" + self.asn1encode(
+ "\x2a\x86\x48\x82\xf7\x12\x01\x02\x02"
+ ) +
+ "\x06" + self.asn1encode(
+ "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"
+ ) +
+ "\x06" + self.asn1encode(
+ "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x03"
+ ) +
+ "\x06" + self.asn1encode(
+ "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
+ )
+ )
+ ) +
+ "\xa3" + self.asn1encode(
+ "\x30" + self.asn1encode(
+ "\xa0" + self.asn1encode(
+ "\x1b" + self.asn1encode(
+ account + '@' + domain
+ )
+ )
+ )
+ )
+ )
+ )
+ )
- return blob
- end
+ return blob
+ end
- # BLOB without GSS usefull for ntlmssp type 1 message
- def self.make_ntlmssp_blob_init(domain = 'WORKGROUP', name = 'WORKSTATION', flags=0x80201)
- blob = "NTLMSSP\x00" +
- [1, flags].pack('VV') +
+ # BLOB without GSS usefull for ntlmssp type 1 message
+ def self.make_ntlmssp_blob_init(domain = 'WORKGROUP', name = 'WORKSTATION', flags=0x80201)
+ blob = "NTLMSSP\x00" +
+ [1, flags].pack('VV') +
- [
- domain.length, #length
- domain.length, #max length
- 32
- ].pack('vvV') +
+ [
+ domain.length, #length
+ domain.length, #max length
+ 32
+ ].pack('vvV') +
- [
- name.length, #length
- name.length, #max length
- domain.length + 32
- ].pack('vvV') +
+ [
+ name.length, #length
+ name.length, #max length
+ domain.length + 32
+ ].pack('vvV') +
- domain + name
- return blob
- end
+ domain + name
+ return blob
+ end
- # GSS BLOB usefull for ntlmssp type 1 message
- def self.make_ntlmssp_secblob_init(domain = 'WORKGROUP', name = 'WORKSTATION', flags=0x80201)
- blob =
- "\x60" + self.asn1encode(
- "\x06" + self.asn1encode(
- "\x2b\x06\x01\x05\x05\x02"
- ) +
- "\xa0" + self.asn1encode(
- "\x30" + self.asn1encode(
- "\xa0" + self.asn1encode(
- "\x30" + self.asn1encode(
- "\x06" + self.asn1encode(
- "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
- )
- )
- ) +
- "\xa2" + self.asn1encode(
- "\x04" + self.asn1encode(
- make_ntlmssp_blob_init(domain, name, flags)
- )
- )
- )
- )
- )
+ # GSS BLOB usefull for ntlmssp type 1 message
+ def self.make_ntlmssp_secblob_init(domain = 'WORKGROUP', name = 'WORKSTATION', flags=0x80201)
+ blob =
+ "\x60" + self.asn1encode(
+ "\x06" + self.asn1encode(
+ "\x2b\x06\x01\x05\x05\x02"
+ ) +
+ "\xa0" + self.asn1encode(
+ "\x30" + self.asn1encode(
+ "\xa0" + self.asn1encode(
+ "\x30" + self.asn1encode(
+ "\x06" + self.asn1encode(
+ "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
+ )
+ )
+ ) +
+ "\xa2" + self.asn1encode(
+ "\x04" + self.asn1encode(
+ make_ntlmssp_blob_init(domain, name, flags)
+ )
+ )
+ )
+ )
+ )
- return blob
- end
+ return blob
+ end
- # BLOB without GSS usefull for ntlm type 2 message
- def self.make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
+ # BLOB without GSS usefull for ntlm type 2 message
+ def self.make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
- addr_list = ''
- addr_list << [2, win_domain.length].pack('vv') + win_domain
- addr_list << [1, win_name.length].pack('vv') + win_name
- addr_list << [4, dns_domain.length].pack('vv') + dns_domain
- addr_list << [3, dns_name.length].pack('vv') + dns_name
- addr_list << [0, 0].pack('vv')
+ addr_list = ''
+ addr_list << [2, win_domain.length].pack('vv') + win_domain
+ addr_list << [1, win_name.length].pack('vv') + win_name
+ addr_list << [4, dns_domain.length].pack('vv') + dns_domain
+ addr_list << [3, dns_name.length].pack('vv') + dns_name
+ addr_list << [0, 0].pack('vv')
- ptr = 0
- blob = "NTLMSSP\x00" +
- [2].pack('V') +
- [
- win_domain.length, # length
- win_domain.length, # max length
- (ptr += 48) # offset
- ].pack('vvV') +
- [ flags ].pack('V') +
- chall +
- "\x00\x00\x00\x00\x00\x00\x00\x00" +
- [
- addr_list.length, # length
- addr_list.length, # max length
- (ptr += win_domain.length)
- ].pack('vvV') +
- win_domain +
- addr_list
- return blob
- end
+ ptr = 0
+ blob = "NTLMSSP\x00" +
+ [2].pack('V') +
+ [
+ win_domain.length, # length
+ win_domain.length, # max length
+ (ptr += 48) # offset
+ ].pack('vvV') +
+ [ flags ].pack('V') +
+ chall +
+ "\x00\x00\x00\x00\x00\x00\x00\x00" +
+ [
+ addr_list.length, # length
+ addr_list.length, # max length
+ (ptr += win_domain.length)
+ ].pack('vvV') +
+ win_domain +
+ addr_list
+ return blob
+ end
- # GSS BLOB usefull for ntlmssp type 2 message
- def self.make_ntlmssp_secblob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
+ # GSS BLOB usefull for ntlmssp type 2 message
+ def self.make_ntlmssp_secblob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
- blob =
- "\xa1" + self.asn1encode(
- "\x30" + self.asn1encode(
- "\xa0" + self.asn1encode(
- "\x0a" + self.asn1encode(
- "\x01"
- )
- ) +
- "\xa1" + self.asn1encode(
- "\x06" + self.asn1encode(
- "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
- )
- ) +
- "\xa2" + self.asn1encode(
- "\x04" + self.asn1encode(
- make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
- )
- )
- )
- )
+ blob =
+ "\xa1" + self.asn1encode(
+ "\x30" + self.asn1encode(
+ "\xa0" + self.asn1encode(
+ "\x0a" + self.asn1encode(
+ "\x01"
+ )
+ ) +
+ "\xa1" + self.asn1encode(
+ "\x06" + self.asn1encode(
+ "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
+ )
+ ) +
+ "\xa2" + self.asn1encode(
+ "\x04" + self.asn1encode(
+ make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
+ )
+ )
+ )
+ )
- return blob
- end
+ return blob
+ end
- # BLOB without GSS Usefull for ntlmssp type 3 message
- def self.make_ntlmssp_blob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201)
- lm ||= "\x00" * 24
- ntlm ||= "\x00" * 24
+ # BLOB without GSS Usefull for ntlmssp type 3 message
+ def self.make_ntlmssp_blob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201)
+ lm ||= "\x00" * 24
+ ntlm ||= "\x00" * 24
- domain_uni = Rex::Text.to_unicode(domain)
- user_uni = Rex::Text.to_unicode(user)
- name_uni = Rex::Text.to_unicode(name)
- session = enc_session_key
+ domain_uni = Rex::Text.to_unicode(domain)
+ user_uni = Rex::Text.to_unicode(user)
+ name_uni = Rex::Text.to_unicode(name)
+ session = enc_session_key
- ptr = 64
+ ptr = 64
- blob = "NTLMSSP\x00" +
- [ 3 ].pack('V') +
+ blob = "NTLMSSP\x00" +
+ [ 3 ].pack('V') +
- [ # Lan Manager Response
- lm.length,
- lm.length,
- (ptr)
- ].pack('vvV') +
+ [ # Lan Manager Response
+ lm.length,
+ lm.length,
+ (ptr)
+ ].pack('vvV') +
- [ # NTLM Manager Response
- ntlm.length,
- ntlm.length,
- (ptr += lm.length)
- ].pack('vvV') +
+ [ # NTLM Manager Response
+ ntlm.length,
+ ntlm.length,
+ (ptr += lm.length)
+ ].pack('vvV') +
- [ # Domain Name
- domain_uni.length,
- domain_uni.length,
- (ptr += ntlm.length)
- ].pack('vvV') +
+ [ # Domain Name
+ domain_uni.length,
+ domain_uni.length,
+ (ptr += ntlm.length)
+ ].pack('vvV') +
- [ # Username
- user_uni.length,
- user_uni.length,
- (ptr += domain_uni.length)
- ].pack('vvV') +
+ [ # Username
+ user_uni.length,
+ user_uni.length,
+ (ptr += domain_uni.length)
+ ].pack('vvV') +
- [ # Hostname
- name_uni.length,
- name_uni.length,
- (ptr += user_uni.length)
- ].pack('vvV') +
+ [ # Hostname
+ name_uni.length,
+ name_uni.length,
+ (ptr += user_uni.length)
+ ].pack('vvV') +
- [ # Session Key (none)
- session.length,
- session.length,
- (ptr += name_uni.length)
- ].pack('vvV') +
+ [ # Session Key (none)
+ session.length,
+ session.length,
+ (ptr += name_uni.length)
+ ].pack('vvV') +
- [ flags ].pack('V') +
+ [ flags ].pack('V') +
- lm +
- ntlm +
- domain_uni +
- user_uni +
- name_uni +
- session + "\x00"
- return blob
+ lm +
+ ntlm +
+ domain_uni +
+ user_uni +
+ name_uni +
+ session + "\x00"
+ return blob
- end
+ end
- # GSS BLOB Usefull for ntlmssp type 3 message
- def self.make_ntlmssp_secblob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201)
+ # GSS BLOB Usefull for ntlmssp type 3 message
+ def self.make_ntlmssp_secblob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201)
- blob =
- "\xa1" + self.asn1encode(
- "\x30" + self.asn1encode(
- "\xa2" + self.asn1encode(
- "\x04" + self.asn1encode(
- make_ntlmssp_blob_auth(domain, name, user, lm, ntlm, enc_session_key, flags )
- )
- )
- )
- )
- return blob
- end
+ blob =
+ "\xa1" + self.asn1encode(
+ "\x30" + self.asn1encode(
+ "\xa2" + self.asn1encode(
+ "\x04" + self.asn1encode(
+ make_ntlmssp_blob_auth(domain, name, user, lm, ntlm, enc_session_key, flags )
+ )
+ )
+ )
+ )
+ return blob
+ end
- # GSS BLOB Usefull for SMB Success
- def self.make_ntlmv2_secblob_success
- blob =
- "\xa1" + self.asn1encode(
- "\x30" + self.asn1encode(
- "\xa0" + self.asn1encode(
- "\x0a" + self.asn1encode(
- "\x00"
- )
- )
- )
- )
- return blob
- end
+ # GSS BLOB Usefull for SMB Success
+ def self.make_ntlmv2_secblob_success
+ blob =
+ "\xa1" + self.asn1encode(
+ "\x30" + self.asn1encode(
+ "\xa0" + self.asn1encode(
+ "\x0a" + self.asn1encode(
+ "\x00"
+ )
+ )
+ )
+ )
+ return blob
+ end
- # Return the correct ntlmflags upon the configuration
- def self.make_ntlm_flags(opt = {})
+ # Return the correct ntlmflags upon the configuration
+ def self.make_ntlm_flags(opt = {})
- signing = opt[:signing] != nil ? opt[:signing] : false
- usentlm2_session = opt[:usentlm2_session] != nil ? opt[:usentlm2_session] : true
- use_ntlmv2 = opt[:use_ntlmv2] != nil ? opt[:use_ntlmv2] : false
- send_lm = opt[:send_lm] != nil ? opt[:send_lm] : true
- send_ntlm = opt[:send_ntlm] != nil ? opt[:send_ntlm] : true
- use_lanman_key = opt[:use_lanman_key] != nil ? opt[:use_lanman_key] : false
+ signing = opt[:signing] != nil ? opt[:signing] : false
+ usentlm2_session = opt[:usentlm2_session] != nil ? opt[:usentlm2_session] : true
+ use_ntlmv2 = opt[:use_ntlmv2] != nil ? opt[:use_ntlmv2] : false
+ send_lm = opt[:send_lm] != nil ? opt[:send_lm] : true
+ send_ntlm = opt[:send_ntlm] != nil ? opt[:send_ntlm] : true
+ use_lanman_key = opt[:use_lanman_key] != nil ? opt[:use_lanman_key] : false
- if signing
- ntlmssp_flags = 0xe2088215
- else
+ if signing
+ ntlmssp_flags = 0xe2088215
+ else
- ntlmssp_flags = 0xa2080205
- end
+ ntlmssp_flags = 0xa2080205
+ end
- if usentlm2_session
- if use_ntlmv2
- #set Negotiate Target Info
- ntlmssp_flags |= CONST::NEGOTIATE_TARGET_INFO
- end
+ if usentlm2_session
+ if use_ntlmv2
+ #set Negotiate Target Info
+ ntlmssp_flags |= CONST::NEGOTIATE_TARGET_INFO
+ end
- else
- #remove the ntlm2_session flag
- ntlmssp_flags &= 0xfff7ffff
- #set lanmanflag only when lm and ntlm are sent
- if send_lm
- ntlmssp_flags |= CONST::NEGOTIATE_LMKEY if use_lanman_key
- end
- end
+ else
+ #remove the ntlm2_session flag
+ ntlmssp_flags &= 0xfff7ffff
+ #set lanmanflag only when lm and ntlm are sent
+ if send_lm
+ ntlmssp_flags |= CONST::NEGOTIATE_LMKEY if use_lanman_key
+ end
+ end
- #we can also downgrade ntlm2_session when we send only lmv1
- ntlmssp_flags &= 0xfff7ffff if usentlm2_session && (not use_ntlmv2) && (not send_ntlm)
+ #we can also downgrade ntlm2_session when we send only lmv1
+ ntlmssp_flags &= 0xfff7ffff if usentlm2_session && (not use_ntlmv2) && (not send_ntlm)
- return ntlmssp_flags
- end
+ return ntlmssp_flags
+ end
- # Parse an ntlm type 2 challenge blob and return usefull data
- def self.parse_ntlm_type_2_blob(blob)
- data = {}
- # Extract the NTLM challenge key the lazy way
- cidx = blob.index("NTLMSSP\x00\x02\x00\x00\x00")
+ # Parse an ntlm type 2 challenge blob and return usefull data
+ def self.parse_ntlm_type_2_blob(blob)
+ data = {}
+ # Extract the NTLM challenge key the lazy way
+ cidx = blob.index("NTLMSSP\x00\x02\x00\x00\x00")
- if not cidx
- raise XCEPT::NTLMMissingChallenge
- end
+ if not cidx
+ raise XCEPT::NTLMMissingChallenge
+ end
- data[:challenge_key] = blob[cidx + 24, 8]
+ data[:challenge_key] = blob[cidx + 24, 8]
- data[:server_ntlmssp_flags] = blob[cidx + 20, 4].unpack("V")[0]
+ data[:server_ntlmssp_flags] = blob[cidx + 20, 4].unpack("V")[0]
- # Extract the address list from the blob
- alist_len,alist_mlen,alist_off = blob[cidx + 40, 8].unpack("vvV")
- alist_buf = blob[cidx + alist_off, alist_len]
+ # Extract the address list from the blob
+ alist_len,alist_mlen,alist_off = blob[cidx + 40, 8].unpack("vvV")
+ alist_buf = blob[cidx + alist_off, alist_len]
- while(alist_buf.length > 0)
- atype, alen = alist_buf.slice!(0,4).unpack('vv')
- break if atype == 0x00
- addr = alist_buf.slice!(0, alen)
- case atype
- when 1
- #netbios name
- data[:default_name] = addr.gsub("\x00", '')
- when 2
- #netbios domain
- data[:default_domain] = addr.gsub("\x00", '')
- when 3
- #dns name
- data[:dns_host_name] = addr.gsub("\x00", '')
- when 4
- #dns domain
- data[:dns_domain_name] = addr.gsub("\x00", '')
- when 5
- #The FQDN of the forest.
- when 6
- #A 32-bit value indicating server or client configuration
- when 7
- #Client time
- data[:chall_MsvAvTimestamp] = addr
- when 8
- #A Restriction_Encoding structure
- when 9
- #The SPN of the target server.
- when 10
- #A channel bindings hash.
- end
- end
- return data
- end
+ while(alist_buf.length > 0)
+ atype, alen = alist_buf.slice!(0,4).unpack('vv')
+ break if atype == 0x00
+ addr = alist_buf.slice!(0, alen)
+ case atype
+ when 1
+ #netbios name
+ data[:default_name] = addr.gsub("\x00", '')
+ when 2
+ #netbios domain
+ data[:default_domain] = addr.gsub("\x00", '')
+ when 3
+ #dns name
+ data[:dns_host_name] = addr.gsub("\x00", '')
+ when 4
+ #dns domain
+ data[:dns_domain_name] = addr.gsub("\x00", '')
+ when 5
+ #The FQDN of the forest.
+ when 6
+ #A 32-bit value indicating server or client configuration
+ when 7
+ #Client time
+ data[:chall_MsvAvTimestamp] = addr
+ when 8
+ #A Restriction_Encoding structure
+ when 9
+ #The SPN of the target server.
+ when 10
+ #A channel bindings hash.
+ end
+ end
+ return data
+ end
- # This function return an ntlmv2 client challenge
- # This is a partial implementation, full description is in [MS-NLMP].pdf around 3.1.5.2.1 :-/
- def self.make_ntlmv2_clientchallenge(win_domain, win_name, dns_domain, dns_name,
- client_challenge = nil, chall_MsvAvTimestamp = nil, spnopt = {})
+ # This function return an ntlmv2 client challenge
+ # This is a partial implementation, full description is in [MS-NLMP].pdf around 3.1.5.2.1 :-/
+ def self.make_ntlmv2_clientchallenge(win_domain, win_name, dns_domain, dns_name,
+ client_challenge = nil, chall_MsvAvTimestamp = nil, spnopt = {})
- client_challenge ||= Rex::Text.rand_text(8)
- # We have to set the timestamps here to the one in the challenge message from server if present
- # If we don't do that, recent server like Seven/2008 will send a STATUS_INVALID_PARAMETER error packet
- timestamp = chall_MsvAvTimestamp != '' ? chall_MsvAvTimestamp : self.time_unix_to_smb(Time.now.to_i).reverse.pack("VV")
- # Make those values unicode as requested
- win_domain = Rex::Text.to_unicode(win_domain)
- win_name = Rex::Text.to_unicode(win_name)
- dns_domain = Rex::Text.to_unicode(dns_domain)
- dns_name = Rex::Text.to_unicode(dns_name)
- # Make the AV_PAIRs
- addr_list = ''
- addr_list << [2, win_domain.length].pack('vv') + win_domain
- addr_list << [1, win_name.length].pack('vv') + win_name
- addr_list << [4, dns_domain.length].pack('vv') + dns_domain
- addr_list << [3, dns_name.length].pack('vv') + dns_name
- addr_list << [7, 8].pack('vv') + timestamp
+ client_challenge ||= Rex::Text.rand_text(8)
+ # We have to set the timestamps here to the one in the challenge message from server if present
+ # If we don't do that, recent server like Seven/2008 will send a STATUS_INVALID_PARAMETER error packet
+ timestamp = chall_MsvAvTimestamp != '' ? chall_MsvAvTimestamp : self.time_unix_to_smb(Time.now.to_i).reverse.pack("VV")
+ # Make those values unicode as requested
+ win_domain = Rex::Text.to_unicode(win_domain)
+ win_name = Rex::Text.to_unicode(win_name)
+ dns_domain = Rex::Text.to_unicode(dns_domain)
+ dns_name = Rex::Text.to_unicode(dns_name)
+ # Make the AV_PAIRs
+ addr_list = ''
+ addr_list << [2, win_domain.length].pack('vv') + win_domain
+ addr_list << [1, win_name.length].pack('vv') + win_name
+ addr_list << [4, dns_domain.length].pack('vv') + dns_domain
+ addr_list << [3, dns_name.length].pack('vv') + dns_name
+ addr_list << [7, 8].pack('vv') + timestamp
- # Windows Seven / 2008r2 Request this type if in local security policies,
- # Microsoft network server : Server SPN target name validation level is set to <Required from client>
- # otherwise it send an STATUS_ACCESS_DENIED packet
- if spnopt[:use_spn]
- spn= Rex::Text.to_unicode("cifs/#{spnopt[:name] || 'unknow'}")
- addr_list << [9, spn.length].pack('vv') + spn
- end
+ # Windows Seven / 2008r2 Request this type if in local security policies,
+ # Microsoft network server : Server SPN target name validation level is set to <Required from client>
+ # otherwise it send an STATUS_ACCESS_DENIED packet
+ if spnopt[:use_spn]
+ spn= Rex::Text.to_unicode("cifs/#{spnopt[:name] || 'unknow'}")
+ addr_list << [9, spn.length].pack('vv') + spn
+ end
- # MAY BE USEFUL FOR FUTURE
- # Seven (client) add at least one more av that is of type MsAvRestrictions (8)
- # maybe this will be usefull with future windows OSs but has no use at all for the moment afaik
- # restriction_encoding = [48,0,0,0].pack("VVV") + # Size, Z4, IntegrityLevel, SubjectIntegrityLevel
- # Rex::Text.rand_text(32) # MachineId generated on startup on win7 and above
- # addr_list << [8, restriction_encoding.length].pack('vv') + restriction_encoding
+ # MAY BE USEFUL FOR FUTURE
+ # Seven (client) add at least one more av that is of type MsAvRestrictions (8)
+ # maybe this will be usefull with future windows OSs but has no use at all for the moment afaik
+ # restriction_encoding = [48,0,0,0].pack("VVV") + # Size, Z4, IntegrityLevel, SubjectIntegrityLevel
+ # Rex::Text.rand_text(32) # MachineId generated on startup on win7 and above
+ # addr_list << [8, restriction_encoding.length].pack('vv') + restriction_encoding
- # Seven (client) and maybe others versions also add an av of type MsvChannelBindings (10) but the hash is "\x00" * 16
- # addr_list << [10, 16].pack('vv') + "\x00" * 16
+ # Seven (client) and maybe others versions also add an av of type MsvChannelBindings (10) but the hash is "\x00" * 16
+ # addr_list << [10, 16].pack('vv') + "\x00" * 16
- addr_list << [0, 0].pack('vv')
- ntlm_clientchallenge = [1,1,0,0].pack("CCvV") + #RespType, HiRespType, Reserved1, Reserved2
- timestamp + #Timestamp
- client_challenge + #clientchallenge
- [0].pack("V") + #Reserved3
- addr_list + "\x00" * 4
+ addr_list << [0, 0].pack('vv')
+ ntlm_clientchallenge = [1,1,0,0].pack("CCvV") + #RespType, HiRespType, Reserved1, Reserved2
+ timestamp + #Timestamp
+ client_challenge + #clientchallenge
+ [0].pack("V") + #Reserved3
+ addr_list + "\x00" * 4
- end
+ end
- # create lm/ntlm responses
- def self.create_lm_ntlm_responses(user, pass, challenge_key, domain = '', default_name = '', default_domain = '',
- dns_host_name = '', dns_domain_name = '', chall_MsvAvTimestamp = nil, spnopt = {}, opt = {} )
+ # create lm/ntlm responses
+ def self.create_lm_ntlm_responses(user, pass, challenge_key, domain = '', default_name = '', default_domain = '',
+ dns_host_name = '', dns_domain_name = '', chall_MsvAvTimestamp = nil, spnopt = {}, opt = {} )
- usentlm2_session = opt[:usentlm2_session] != nil ? opt[:usentlm2_session] : true
- use_ntlmv2 = opt[:use_ntlmv2] != nil ? opt[:use_ntlmv2] : false
- send_lm = opt[:send_lm] != nil ? opt[:send_lm] : true
- send_ntlm = opt[:send_ntlm] != nil ? opt[:send_ntlm] : true
+ usentlm2_session = opt[:usentlm2_session] != nil ? opt[:usentlm2_session] : true
+ use_ntlmv2 = opt[:use_ntlmv2] != nil ? opt[:use_ntlmv2] : false
+ send_lm = opt[:send_lm] != nil ? opt[:send_lm] : true
+ send_ntlm = opt[:send_ntlm] != nil ? opt[:send_ntlm] : true
- #calculate the lm/ntlm response
- resp_lm = "\x00" * 24
- resp_ntlm = "\x00" * 24
+ #calculate the lm/ntlm response
+ resp_lm = "\x00" * 24
+ resp_ntlm = "\x00" * 24
- client_challenge = Rex::Text.rand_text(8)
- ntlm_cli_challenge = ''
- if send_ntlm #should be default
- if usentlm2_session
- if use_ntlmv2
- ntlm_cli_challenge = self.make_ntlmv2_clientchallenge(default_domain, default_name, dns_domain_name,
- dns_host_name,client_challenge ,
- chall_MsvAvTimestamp, spnopt)
- if self.is_pass_ntlm_hash?(pass)
- argntlm = {
- :ntlmv2_hash => CRYPT::ntlmv2_hash(
- user,
- [ pass.upcase()[33,65] ].pack('H32'),
- domain,{:pass_is_hash => true}
- ),
- :challenge => challenge_key
- }
- else
- argntlm = {
- :ntlmv2_hash => CRYPT::ntlmv2_hash(user, pass, domain),
- :challenge => challenge_key
- }
- end
+ client_challenge = Rex::Text.rand_text(8)
+ ntlm_cli_challenge = ''
+ if send_ntlm #should be default
+ if usentlm2_session
+ if use_ntlmv2
+ ntlm_cli_challenge = self.make_ntlmv2_clientchallenge(default_domain, default_name, dns_domain_name,
+ dns_host_name,client_challenge ,
+ chall_MsvAvTimestamp, spnopt)
+ if self.is_pass_ntlm_hash?(pass)
+ argntlm = {
+ :ntlmv2_hash => CRYPT::ntlmv2_hash(
+ user,
+ [ pass.upcase()[33,65] ].pack('H32'),
+ domain,{:pass_is_hash => true}
+ ),
+ :challenge => challenge_key
+ }
+ else
+ argntlm = {
+ :ntlmv2_hash => CRYPT::ntlmv2_hash(user, pass, domain),
+ :challenge => challenge_key
+ }
+ end
- optntlm = { :nt_client_challenge => ntlm_cli_challenge}
- ntlmv2_response = CRYPT::ntlmv2_response(argntlm,optntlm)
- resp_ntlm = ntlmv2_response
+ optntlm = { :nt_client_challenge => ntlm_cli_challenge}
+ ntlmv2_response = CRYPT::ntlmv2_response(argntlm,optntlm)
+ resp_ntlm = ntlmv2_response
- if send_lm
- if self.is_pass_ntlm_hash?(pass)
- arglm = {
- :ntlmv2_hash => CRYPT::ntlmv2_hash(
- user,
- [ pass.upcase()[33,65] ].pack('H32'),
- domain,{:pass_is_hash => true}
- ),
- :challenge => challenge_key
- }
- else
- arglm = {
- :ntlmv2_hash => CRYPT::ntlmv2_hash(user,pass, domain),
- :challenge => challenge_key
- }
- end
+ if send_lm
+ if self.is_pass_ntlm_hash?(pass)
+ arglm = {
+ :ntlmv2_hash => CRYPT::ntlmv2_hash(
+ user,
+ [ pass.upcase()[33,65] ].pack('H32'),
+ domain,{:pass_is_hash => true}
+ ),
+ :challenge => challenge_key
+ }
+ else
+ arglm = {
+ :ntlmv2_hash => CRYPT::ntlmv2_hash(user,pass, domain),
+ :challenge => challenge_key
+ }
+ end
- optlm = { :client_challenge => client_challenge }
- resp_lm = CRYPT::lmv2_response(arglm, optlm)
- else
- resp_lm = "\x00" * 24
- end
+ optlm = { :client_challenge => client_challenge }
+ resp_lm = CRYPT::lmv2_response(arglm, optlm)
+ else
+ resp_lm = "\x00" * 24
+ end
- else # ntlm2_session
- if self.is_pass_ntlm_hash?(pass)
- argntlm = {
- :ntlm_hash => [ pass.upcase()[33,65] ].pack('H32'),
- :challenge => challenge_key
- }
- else
- argntlm = {
- :ntlm_hash => CRYPT::ntlm_hash(pass),
- :challenge => challenge_key
- }
- end
+ else # ntlm2_session
+ if self.is_pass_ntlm_hash?(pass)
+ argntlm = {
+ :ntlm_hash => [ pass.upcase()[33,65] ].pack('H32'),
+ :challenge => challenge_key
+ }
+ else
+ argntlm = {
+ :ntlm_hash => CRYPT::ntlm_hash(pass),
+ :challenge => challenge_key
+ }
+ end
- optntlm = { :client_challenge => client_challenge}
- resp_ntlm = CRYPT::ntlm2_session(argntlm,optntlm).join[24,24]
+ optntlm = { :client_challenge => client_challenge}
+ resp_ntlm = CRYPT::ntlm2_session(argntlm,optntlm).join[24,24]
- # Generate the fake LANMAN hash
- resp_lm = client_challenge + ("\x00" * 16)
- end
+ # Generate the fake LANMAN hash
+ resp_lm = client_challenge + ("\x00" * 16)
+ end
- else # we use lmv1/ntlmv1
- if self.is_pass_ntlm_hash?(pass)
- argntlm = {
- :ntlm_hash => [ pass.upcase()[33,65] ].pack('H32'),
- :challenge => challenge_key
- }
- else
- argntlm = {
- :ntlm_hash => CRYPT::ntlm_hash(pass),
- :challenge => challenge_key
- }
- end
+ else # we use lmv1/ntlmv1
+ if self.is_pass_ntlm_hash?(pass)
+ argntlm = {
+ :ntlm_hash => [ pass.upcase()[33,65] ].pack('H32'),
+ :challenge => challenge_key
+ }
+ else
+ argntlm = {
+ :ntlm_hash => CRYPT::ntlm_hash(pass),
+ :challenge => challenge_key
+ }
+ end
- resp_ntlm = CRYPT::ntlm_response(argntlm)
- if send_lm
- if self.is_pass_ntlm_hash?(pass)
- arglm = {
- :lm_hash => [ pass.upcase()[0,32] ].pack('H32'),
- :challenge => challenge_key
- }
- else
- arglm = {
- :lm_hash => CRYPT::lm_hash(pass),
- :challenge => challenge_key
- }
- end
- resp_lm = CRYPT::lm_response(arglm)
- else
- #when windows does not send lm in ntlmv1 type response,
- # it gives lm response the same value as ntlm response
- resp_lm = resp_ntlm
- end
- end
- else #send_ntlm = false
- #lmv2
- if usentlm2_session && use_ntlmv2
- if self.is_pass_ntlm_hash?(pass)
- arglm = {
- :ntlmv2_hash => CRYPT::ntlmv2_hash(
- user,
- [ pass.upcase()[33,65] ].pack('H32'),
- domain,{:pass_is_hash => true}
- ),
- :challenge => challenge_key
- }
- else
- arglm = {
- :ntlmv2_hash => CRYPT::ntlmv2_hash(user,pass, domain),
- :challenge => challenge_key
- }
- end
- optlm = { :client_challenge => client_challenge }
- resp_lm = CRYPT::lmv2_response(arglm, optlm)
- else
- if self.is_pass_ntlm_hash?(pass)
- arglm = {
- :lm_hash => [ pass.upcase()[0,32] ].pack('H32'),
- :challenge => challenge_key
- }
- else
- arglm = {
- :lm_hash => CRYPT::lm_hash(pass),
- :challenge => challenge_key
- }
- end
- resp_lm = CRYPT::lm_response(arglm)
- end
- resp_ntlm = ""
- end
- return resp_lm, resp_ntlm, client_challenge, ntlm_cli_challenge
- end
+ resp_ntlm = CRYPT::ntlm_response(argntlm)
+ if send_lm
+ if self.is_pass_ntlm_hash?(pass)
+ arglm = {
+ :lm_hash => [ pass.upcase()[0,32] ].pack('H32'),
+ :challenge => challenge_key
+ }
+ else
+ arglm = {
+ :lm_hash => CRYPT::lm_hash(pass),
+ :challenge => challenge_key
+ }
+ end
+ resp_lm = CRYPT::lm_response(arglm)
+ else
+ #when windows does not send lm in ntlmv1 type response,
+ # it gives lm response the same value as ntlm response
+ resp_lm = resp_ntlm
+ end
+ end
+ else #send_ntlm = false
+ #lmv2
+ if usentlm2_session && use_ntlmv2
+ if self.is_pass_ntlm_hash?(pass)
+ arglm = {
+ :ntlmv2_hash => CRYPT::ntlmv2_hash(
+ user,
+ [ pass.upcase()[33,65] ].pack('H32'),
+ domain,{:pass_is_hash => true}
+ ),
+ :challenge => challenge_key
+ }
+ else
+ arglm = {
+ :ntlmv2_hash => CRYPT::ntlmv2_hash(user,pass, domain),
+ :challenge => challenge_key
+ }
+ end
+ optlm = { :client_challenge => client_challenge }
+ resp_lm = CRYPT::lmv2_response(arglm, optlm)
+ else
+ if self.is_pass_ntlm_hash?(pass)
+ arglm = {
+ :lm_hash => [ pass.upcase()[0,32] ].pack('H32'),
+ :challenge => challenge_key
+ }
+ else
+ arglm = {
+ :lm_hash => CRYPT::lm_hash(pass),
+ :challenge => challenge_key
+ }
+ end
+ resp_lm = CRYPT::lm_response(arglm)
+ end
+ resp_ntlm = ""
+ end
+ return resp_lm, resp_ntlm, client_challenge, ntlm_cli_challenge
+ end
- # create the session key
- def self.create_session_key(ntlmssp_flags, server_ntlmssp_flags, user, pass, domain, challenge_key,
- client_challenge = '', ntlm_cli_challenge = '' , opt = {} )
+ # create the session key
+ def self.create_session_key(ntlmssp_flags, server_ntlmssp_flags, user, pass, domain, challenge_key,
+ client_challenge = '', ntlm_cli_challenge = '' , opt = {} )
- usentlm2_session = opt[:usentlm2_session] != nil ? opt[:usentlm2_session] : true
- use_ntlmv2 = opt[:use_ntlmv2] != nil ? opt[:use_ntlmv2] : false
- send_lm = opt[:send_lm] != nil ? opt[:send_lm] : true
- send_ntlm = opt[:send_ntlm] != nil ? opt[:send_ntlm] : true
- use_lanman_key = opt[:use_lanman_key] != nil ? opt[:use_lanman_key] : false
+ usentlm2_session = opt[:usentlm2_session] != nil ? opt[:usentlm2_session] : true
+ use_ntlmv2 = opt[:use_ntlmv2] != nil ? opt[:use_ntlmv2] : false
+ send_lm = opt[:send_lm] != nil ? opt[:send_lm] : true
+ send_ntlm = opt[:send_ntlm] != nil ? opt[:send_ntlm] : true
+ use_lanman_key = opt[:use_lanman_key] != nil ? opt[:use_lanman_key] : false
- # Create the sessionkey (aka signing key, aka mackey) and encrypted session key
- # Server will decide for key_size and key_exchange
- enc_session_key = ''
- signing_key = ''
+ # Create the sessionkey (aka signing key, aka mackey) and encrypted session key
+ # Server will decide for key_size and key_exchange
+ enc_session_key = ''
+ signing_key = ''
- # Set default key size and key exchange values
- key_size = 40
- key_exchange = false
- # Remove ntlmssp.negotiate56
- ntlmssp_flags &= 0x7fffffff
- # Remove ntlmssp.negotiatekeyexch
- ntlmssp_flags &= 0xbfffffff
- # Remove ntlmssp.negotiate128
- ntlmssp_flags &= 0xdfffffff
- # Check the keyexchange
- if server_ntlmssp_flags & CONST::NEGOTIATE_KEY_EXCH != 0 then
- key_exchange = true
- ntlmssp_flags |= CONST::NEGOTIATE_KEY_EXCH
- end
- # Check 128bits
- if server_ntlmssp_flags & CONST::NEGOTIATE_128 != 0 then
- key_size = 128
- ntlmssp_flags |= CONST::NEGOTIATE_128
- ntlmssp_flags |= CONST::NEGOTIATE_56
- # Check 56bits
- else
- if server_ntlmssp_flags & CONST::NEGOTIATE_56 != 0 then
- key_size = 56
- ntlmssp_flags |= CONST::NEGOTIATE_56
- end
- end
- # Generate the user session key
- lanman_weak = false
- if send_ntlm # Should be default
- if usentlm2_session
- if use_ntlmv2
- if self.is_pass_ntlm_hash?(pass)
- user_session_key = CRYPT::ntlmv2_user_session_key(user,
- [ pass.upcase()[33,65] ].pack('H32'),
- domain,
- challenge_key, ntlm_cli_challenge,
- {:pass_is_hash => true})
- else
- user_session_key = CRYPT::ntlmv2_user_session_key(user, pass, domain,
- challenge_key, ntlm_cli_challenge)
- end
- else
- if self.is_pass_ntlm_hash?(pass)
- user_session_key = CRYPT::ntlm2_session_user_session_key([ pass.upcase()[33,65] ].pack('H32'),
- challenge_key,
- client_challenge,
- {:pass_is_hash => true})
- else
- user_session_key = CRYPT::ntlm2_session_user_session_key(pass, challenge_key,
- client_challenge)
- end
- end
- else # lmv1/ntlmv1
- # lanman_key may also be used without ntlm response but it is not so much used
- # so we don't care about this feature
- if send_lm && use_lanman_key
- if self.is_pass_ntlm_hash?(pass)
- user_session_key = CRYPT::lanman_session_key([ pass.upcase()[0,32] ].pack('H32'),
- challenge_key,
- {:pass_is_hash => true})
- else
- user_session_key = CRYPT::lanman_session_key(pass, challenge_key)
- end
- lanman_weak = true
+ # Set default key size and key exchange values
+ key_size = 40
+ key_exchange = false
+ # Remove ntlmssp.negotiate56
+ ntlmssp_flags &= 0x7fffffff
+ # Remove ntlmssp.negotiatekeyexch
+ ntlmssp_flags &= 0xbfffffff
+ # Remove ntlmssp.negotiate128
+ ntlmssp_flags &= 0xdfffffff
+ # Check the keyexchange
+ if server_ntlmssp_flags & CONST::NEGOTIATE_KEY_EXCH != 0 then
+ key_exchange = true
+ ntlmssp_flags |= CONST::NEGOTIATE_KEY_EXCH
+ end
+ # Check 128bits
+ if server_ntlmssp_flags & CONST::NEGOTIATE_128 != 0 then
+ key_size = 128
+ ntlmssp_flags |= CONST::NEGOTIATE_128
+ ntlmssp_flags |= CONST::NEGOTIATE_56
+ # Check 56bits
+ else
+ if server_ntlmssp_flags & CONST::NEGOTIATE_56 != 0 then
+ key_size = 56
+ ntlmssp_flags |= CONST::NEGOTIATE_56
+ end
+ end
+ # Generate the user session key
+ lanman_weak = false
+ if send_ntlm # Should be default
+ if usentlm2_session
+ if use_ntlmv2
+ if self.is_pass_ntlm_hash?(pass)
+ user_session_key = CRYPT::ntlmv2_user_session_key(user,
+ [ pass.upcase()[33,65] ].pack('H32'),
+ domain,
+ challenge_key, ntlm_cli_challenge,
+ {:pass_is_hash => true})
+ else
+ user_session_key = CRYPT::ntlmv2_user_session_key(user, pass, domain,
+ challenge_key, ntlm_cli_challenge)
+ end
+ else
+ if self.is_pass_ntlm_hash?(pass)
+ user_session_key = CRYPT::ntlm2_session_user_session_key([ pass.upcase()[33,65] ].pack('H32'),
+ challenge_key,
+ client_challenge,
+ {:pass_is_hash => true})
+ else
+ user_session_key = CRYPT::ntlm2_session_user_session_key(pass, challenge_key,
+ client_challenge)
+ end
+ end
+ else # lmv1/ntlmv1
+ # lanman_key may also be used without ntlm response but it is not so much used
+ # so we don't care about this feature
+ if send_lm && use_lanman_key
+ if self.is_pass_ntlm_hash?(pass)
+ user_session_key = CRYPT::lanman_session_key([ pass.upcase()[0,32] ].pack('H32'),
+ challenge_key,
+ {:pass_is_hash => true})
+ else
+ user_session_key = CRYPT::lanman_session_key(pass, challenge_key)
+ end
+ lanman_weak = true
- else
- if self.is_pass_ntlm_hash?(pass)
- user_session_key = CRYPT::ntlmv1_user_session_key([ pass.upcase()[33,65] ].pack('H32'),
- {:pass_is_hash => true})
- else
- user_session_key = CRYPT::ntlmv1_user_session_key(pass)
- end
- end
- end
- else
- if usentlm2_session && use_ntlmv2
- if self.is_pass_ntlm_hash?(pass)
- user_session_key = CRYPT::lmv2_user_session_key(user, [ pass.upcase()[33,65] ].pack('H32'),
- domain,
- challenge_key, client_challenge,
- {:pass_is_hash => true})
- else
- user_session_key = CRYPT::lmv2_user_session_key(user, pass, domain,
- challenge_key, client_challenge)
- end
- else
- if self.is_pass_ntlm_hash?(pass)
- user_session_key = CRYPT::lmv1_user_session_key([ pass.upcase()[0,32] ].pack('H32'),
- {:pass_is_hash => true})
- else
- user_session_key = CRYPT::lmv1_user_session_key(pass)
- end
- end
- end
+ else
+ if self.is_pass_ntlm_hash?(pass)
+ user_session_key = CRYPT::ntlmv1_user_session_key([ pass.upcase()[33,65] ].pack('H32'),
+ {:pass_is_hash => true})
+ else
+ user_session_key = CRYPT::ntlmv1_user_session_key(pass)
+ end
+ end
+ end
+ else
+ if usentlm2_session && use_ntlmv2
+ if self.is_pass_ntlm_hash?(pass)
+ user_session_key = CRYPT::lmv2_user_session_key(user, [ pass.upcase()[33,65] ].pack('H32'),
+ domain,
+ challenge_key, client_challenge,
+ {:pass_is_hash => true})
+ else
+ user_session_key = CRYPT::lmv2_user_session_key(user, pass, domain,
+ challenge_key, client_challenge)
+ end
+ else
+ if self.is_pass_ntlm_hash?(pass)
+ user_session_key = CRYPT::lmv1_user_session_key([ pass.upcase()[0,32] ].pack('H32'),
+ {:pass_is_hash => true})
+ else
+ user_session_key = CRYPT::lmv1_user_session_key(pass)
+ end
+ end
+ end
- user_session_key = CRYPT::make_weak_sessionkey(user_session_key,key_size, lanman_weak)
+ user_session_key = CRYPT::make_weak_sessionkey(user_session_key,key_size, lanman_weak)
- # Sessionkey and encrypted session key
- if key_exchange
- signing_key = Rex::Text.rand_text(16)
- enc_session_key = CRYPT::encrypt_sessionkey(signing_key, user_session_key)
- else
- signing_key = user_session_key
- end
+ # Sessionkey and encrypted session key
+ if key_exchange
+ signing_key = Rex::Text.rand_text(16)
+ enc_session_key = CRYPT::encrypt_sessionkey(signing_key, user_session_key)
+ else
+ signing_key = user_session_key
+ end
- return signing_key, enc_session_key, ntlmssp_flags
+ return signing_key, enc_session_key, ntlmssp_flags
- end
+ end
end
end