# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. # # This software is provided under under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file # for more information. # from __future__ import division from __future__ import print_function import base64 import struct import calendar import time import hashlib import random import string import binascii from six import b from impacket.structure import Structure from impacket import LOG # This is important. NTLMv2 is not negotiated by the client or server. # It is used if set locally on both sides. Change this item if you don't want to use # NTLMv2 by default and fall back to NTLMv1 (with EXTENDED_SESSION_SECURITY or not) # Check the following links: # https://davenport.sourceforge.io/ntlm.html # https://blogs.msdn.microsoft.com/openspecification/2010/04/19/ntlm-keys-and-sundry-stuff/ # https://social.msdn.microsoft.com/Forums/c8f488ed-1b96-4e06-bd65-390aa41138d1/msnlmp-msntht-determining-ntlm-v1-or-v2-in-http-authentication?forum=os_specifications # So I'm setting a global variable to control this, this can also be set programmatically USE_NTLMv2 = True # if false will fall back to NTLMv1 (or NTLMv1 with ESS a.k.a NTLM2) TEST_CASE = False # Only set to True when running Test Cases def computeResponse(flags, serverChallenge, clientChallenge, serverName, domain, user, password, lmhash='', nthash='', use_ntlmv2=USE_NTLMv2): if use_ntlmv2: return computeResponseNTLMv2(flags, serverChallenge, clientChallenge, serverName, domain, user, password, lmhash, nthash, use_ntlmv2=use_ntlmv2) else: return computeResponseNTLMv1(flags, serverChallenge, clientChallenge, serverName, domain, user, password, lmhash, nthash, use_ntlmv2=use_ntlmv2) try: from Cryptodome.Cipher import ARC4 from Cryptodome.Cipher import DES from Cryptodome.Hash import MD4 except Exception: LOG.critical("Warning: You don't have any crypto installed. You need pycryptodomex") LOG.critical("See https://pypi.org/project/pycryptodomex/") NTLM_AUTH_NONE = 1 NTLM_AUTH_CONNECT = 2 NTLM_AUTH_CALL = 3 NTLM_AUTH_PKT = 4 NTLM_AUTH_PKT_INTEGRITY = 5 NTLM_AUTH_PKT_PRIVACY = 6 # If set, requests 56-bit encryption. If the client sends NTLMSSP_NEGOTIATE_SEAL or NTLMSSP_NEGOTIATE_SIGN # with NTLMSSP_NEGOTIATE_56 to the server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_56 to # the client in the CHALLENGE_MESSAGE. Otherwise it is ignored. If both NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 # are requested and supported by the client and server, NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 will both be # returned to the client. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD set NTLMSSP_NEGOTIATE_56 if it is # supported. An alternate name for this field is NTLMSSP_NEGOTIATE_56. NTLMSSP_NEGOTIATE_56 = 0x80000000 # If set, requests an explicit key exchange. This capability SHOULD be used because it improves security for message # integrity or confidentiality. See sections 3.2.5.1.2, 3.2.5.2.1, and 3.2.5.2.2 for details. An alternate name for # this field is NTLMSSP_NEGOTIATE_KEY_EXCH. NTLMSSP_NEGOTIATE_KEY_EXCH = 0x40000000 # If set, requests 128-bit session key negotiation. An alternate name for this field is NTLMSSP_NEGOTIATE_128. # If the client sends NTLMSSP_NEGOTIATE_128 to the server in the NEGOTIATE_MESSAGE, the server MUST return # NTLMSSP_NEGOTIATE_128 to the client in the CHALLENGE_MESSAGE only if the client sets NTLMSSP_NEGOTIATE_SEAL or # NTLMSSP_NEGOTIATE_SIGN. Otherwise it is ignored. If both NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 are # requested and supported by the client and server, NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 will both be # returned to the client. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD set NTLMSSP_NEGOTIATE_128 if it # is supported. An alternate name for this field is NTLMSSP_NEGOTIATE_128 NTLMSSP_NEGOTIATE_128 = 0x20000000 NTLMSSP_RESERVED_1 = 0x10000000 NTLMSSP_RESERVED_2 = 0x08000000 NTLMSSP_RESERVED_3 = 0x04000000 # If set, requests the protocol version number. The data corresponding to this flag is provided in the Version field # of the NEGOTIATE_MESSAGE, the CHALLENGE_MESSAGE, and the AUTHENTICATE_MESSAGE.<22> An alternate name for this field # is NTLMSSP_NEGOTIATE_VERSION NTLMSSP_NEGOTIATE_VERSION = 0x02000000 NTLMSSP_RESERVED_4 = 0x01000000 # If set, indicates that the TargetInfo fields in the CHALLENGE_MESSAGE (section 2.2.1.2) are populated. # An alternate name for this field is NTLMSSP_NEGOTIATE_TARGET_INFO. NTLMSSP_NEGOTIATE_TARGET_INFO = 0x00800000 # If set, requests the usage of the LMOWF (section 3.3). An alternate name for this field is # NTLMSSP_REQUEST_NON_NT_SESSION_KEY. NTLMSSP_REQUEST_NON_NT_SESSION_KEY = 0x00400000 NTLMSSP_RESERVED_5 = 0x00200000 # If set, requests an identify level token. An alternate name for this field is NTLMSSP_NEGOTIATE_IDENTIFY NTLMSSP_NEGOTIATE_IDENTIFY = 0x00100000 # If set, requests usage of the NTLM v2 session security. NTLM v2 session security is a misnomer because it is not # NTLM v2. It is NTLM v1 using the extended session security that is also in NTLM v2. NTLMSSP_NEGOTIATE_LM_KEY and # NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are mutually exclusive. If both NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY # and NTLMSSP_NEGOTIATE_LM_KEY are requested, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY alone MUST be returned to the # client. NTLM v2 authentication session key generation MUST be supported by both the client and the DC in order to be # used, and extended session security signing and sealing requires support from the client and the server in order to # be used.<23> An alternate name for this field is NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY = 0x00080000 NTLMSSP_NEGOTIATE_NTLM2 = 0x00080000 NTLMSSP_TARGET_TYPE_SHARE = 0x00040000 # If set, TargetName MUST be a server name. The data corresponding to this flag is provided by the server in the # TargetName field of the CHALLENGE_MESSAGE. If this bit is set, then NTLMSSP_TARGET_TYPE_DOMAIN MUST NOT be set. # This flag MUST be ignored in the NEGOTIATE_MESSAGE and the AUTHENTICATE_MESSAGE. An alternate name for this field # is NTLMSSP_TARGET_TYPE_SERVER NTLMSSP_TARGET_TYPE_SERVER = 0x00020000 # If set, TargetName MUST be a domain name. The data corresponding to this flag is provided by the server in the # TargetName field of the CHALLENGE_MESSAGE. If set, then NTLMSSP_TARGET_TYPE_SERVER MUST NOT be set. This flag MUST # be ignored in the NEGOTIATE_MESSAGE and the AUTHENTICATE_MESSAGE. An alternate name for this field is # NTLMSSP_TARGET_TYPE_DOMAIN. NTLMSSP_TARGET_TYPE_DOMAIN = 0x00010000 # If set, requests the presence of a signature block on all messages. NTLMSSP_NEGOTIATE_ALWAYS_SIGN MUST be set in the # NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. NTLMSSP_NEGOTIATE_ALWAYS_SIGN is overridden # by NTLMSSP_NEGOTIATE_SIGN and NTLMSSP_NEGOTIATE_SEAL, if they are supported. An alternate name for this field is # NTLMSSP_NEGOTIATE_ALWAYS_SIGN. NTLMSSP_NEGOTIATE_ALWAYS_SIGN = 0x00008000 # forces the other end to sign packets NTLMSSP_RESERVED_6 = 0x00004000 # This flag indicates whether the Workstation field is present. If this flag is not set, the Workstation field MUST be # ignored. If this flag is set, the length field of the Workstation field specifies whether the workstation name is # nonempty or not.<24> An alternate name for this field is NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED. NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED = 0x00002000 # If set, the domain name is provided (section 2.2.1.1).<25> An alternate name for this field is # NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED = 0x00001000 NTLMSSP_RESERVED_7 = 0x00000800 # If set, LM authentication is not allowed and only NT authentication is used. NTLMSSP_NEGOTIATE_NT_ONLY = 0x00000400 # If set, requests usage of the NTLM v1 session security protocol. NTLMSSP_NEGOTIATE_NTLM MUST be set in the # NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. An alternate name for this field is # NTLMSSP_NEGOTIATE_NTLM NTLMSSP_NEGOTIATE_NTLM = 0x00000200 NTLMSSP_RESERVED_8 = 0x00000100 # If set, requests LAN Manager (LM) session key computation. NTLMSSP_NEGOTIATE_LM_KEY and # NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are mutually exclusive. If both NTLMSSP_NEGOTIATE_LM_KEY and # NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are requested, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY alone MUST be # returned to the client. NTLM v2 authentication session key generation MUST be supported by both the client and the # DC in order to be used, and extended session security signing and sealing requires support from the client and the # server to be used. An alternate name for this field is NTLMSSP_NEGOTIATE_LM_KEY. NTLMSSP_NEGOTIATE_LM_KEY = 0x00000080 # If set, requests connectionless authentication. If NTLMSSP_NEGOTIATE_DATAGRAM is set, then NTLMSSP_NEGOTIATE_KEY_EXCH # MUST always be set in the AUTHENTICATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. An alternate # name for this field is NTLMSSP_NEGOTIATE_DATAGRAM. NTLMSSP_NEGOTIATE_DATAGRAM = 0x00000040 # If set, requests session key negotiation for message confidentiality. If the client sends NTLMSSP_NEGOTIATE_SEAL to # the server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_SEAL to the client in the # CHALLENGE_MESSAGE. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD always set NTLMSSP_NEGOTIATE_56 and # NTLMSSP_NEGOTIATE_128, if they are supported. An alternate name for this field is NTLMSSP_NEGOTIATE_SEAL. NTLMSSP_NEGOTIATE_SEAL = 0x00000020 # If set, requests session key negotiation for message signatures. If the client sends NTLMSSP_NEGOTIATE_SIGN to the # server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_SIGN to the client in the CHALLENGE_MESSAGE. # An alternate name for this field is NTLMSSP_NEGOTIATE_SIGN. NTLMSSP_NEGOTIATE_SIGN = 0x00000010 # means packet is signed, if verifier is wrong it fails NTLMSSP_RESERVED_9 = 0x00000008 # If set, a TargetName field of the CHALLENGE_MESSAGE (section 2.2.1.2) MUST be supplied. An alternate name for this # field is NTLMSSP_REQUEST_TARGET. NTLMSSP_REQUEST_TARGET = 0x00000004 # If set, requests OEM character set encoding. An alternate name for this field is NTLM_NEGOTIATE_OEM. See bit A for # details. NTLM_NEGOTIATE_OEM = 0x00000002 # If set, requests Unicode character set encoding. An alternate name for this field is NTLMSSP_NEGOTIATE_UNICODE. NTLMSSP_NEGOTIATE_UNICODE = 0x00000001 # AV_PAIR constants NTLMSSP_AV_EOL = 0x00 NTLMSSP_AV_HOSTNAME = 0x01 NTLMSSP_AV_DOMAINNAME = 0x02 NTLMSSP_AV_DNS_HOSTNAME = 0x03 NTLMSSP_AV_DNS_DOMAINNAME = 0x04 NTLMSSP_AV_DNS_TREENAME = 0x05 NTLMSSP_AV_FLAGS = 0x06 NTLMSSP_AV_TIME = 0x07 NTLMSSP_AV_RESTRICTIONS = 0x08 NTLMSSP_AV_TARGET_NAME = 0x09 NTLMSSP_AV_CHANNEL_BINDINGS = 0x0a class AV_PAIRS: def __init__(self, data = None): self.fields = {} if data is not None: self.fromString(data) def __setitem__(self,key,value): self.fields[key] = (len(value),value) def __getitem__(self, key): if key in self.fields: return self.fields[key] return None def __delitem__(self, key): del self.fields[key] def __len__(self): return len(self.getData()) def __str__(self): return len(self.getData()) def fromString(self, data): tInfo = data fType = 0xff while fType is not NTLMSSP_AV_EOL: fType = struct.unpack(' 0: self['flags'] |= NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED if len(self.fields['domain_name']) > 0: self['flags'] |= NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED version_len = len(self.fields['os_version']) if version_len > 0: self['flags'] |= NTLMSSP_NEGOTIATE_VERSION elif self.__hasNegotiateVersion(): raise Exception('Must provide the os_version field if the NTLMSSP_NEGOTIATE_VERSION flag is set') if (self['flags'] & NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED) == NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED: self['host_offset']=32 + version_len if (self['flags'] & NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED) == NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED: self['domain_offset']=32+len(self['host_name']) + version_len return Structure.getData(self) def fromString(self,data): Structure.fromString(self,data) domain_offset = self['domain_offset'] domain_end = self['domain_len'] + domain_offset self['domain_name'] = data[ domain_offset : domain_end ] host_offset = self['host_offset'] host_end = self['host_len'] + host_offset self['host_name'] = data[ host_offset : host_end ] if len(data) >= 36 and self.__hasNegotiateVersion(): self['os_version'] = VERSION(data[32:]) else: self['os_version'] = '' class NTLMAuthChallenge(Structure): structure = ( ('','"NTLMSSP\x00'), ('message_type','> 1) & 0x7f) << 1) s.append(((key[0] & 0x01) << 6 | ((key[1] >> 2) & 0x3f)) << 1) s.append(((key[1] & 0x03) << 5 | ((key[2] >> 3) & 0x1f)) << 1) s.append(((key[2] & 0x07) << 4 | ((key[3] >> 4) & 0x0f)) << 1) s.append(((key[3] & 0x0f) << 3 | ((key[4] >> 5) & 0x07)) << 1) s.append(((key[4] & 0x1f) << 2 | ((key[5] >> 6) & 0x03)) << 1) s.append(((key[5] & 0x3f) << 1 | ((key[6] >> 7) & 0x01)) << 1) s.append((key[6] & 0x7f) << 1) return bytes(s) def __DES_block(key, msg): cipher = DES.new(__expand_DES_key(key),DES.MODE_ECB) return cipher.encrypt(msg) def ntlmssp_DES_encrypt(key, challenge): answer = __DES_block(key[:7], challenge) answer += __DES_block(key[7:14], challenge) answer += __DES_block(key[14:], challenge) return answer # High level functions to use NTLMSSP def getNTLMSSPType1(workstation='', domain='', signingRequired = False, use_ntlmv2 = USE_NTLMv2): # Let's do some encoding checks before moving on. Kind of dirty, but found effective when dealing with # international characters. import sys encoding = sys.getfilesystemencoding() if encoding is not None: try: workstation.encode('utf-16le') except: workstation = workstation.decode(encoding) try: domain.encode('utf-16le') except: domain = domain.decode(encoding) # Let's prepare a Type 1 NTLMSSP Message auth = NTLMAuthNegotiate() auth['flags']=0 if signingRequired: auth['flags'] = NTLMSSP_NEGOTIATE_KEY_EXCH | NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_ALWAYS_SIGN | \ NTLMSSP_NEGOTIATE_SEAL if use_ntlmv2: auth['flags'] |= NTLMSSP_NEGOTIATE_TARGET_INFO auth['flags'] |= NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY | NTLMSSP_NEGOTIATE_UNICODE | \ NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_56 # We're not adding workstation / domain fields this time. Normally Windows clients don't add such information but, # we will save the workstation name to be used later. auth.setWorkstation(workstation) return auth def getNTLMSSPType3(type1, type2, user, password, domain, lmhash = '', nthash = '', use_ntlmv2 = USE_NTLMv2): # Safety check in case somebody sent password = None.. That's not allowed. Setting it to '' and hope for the best. if password is None: password = '' # Let's do some encoding checks before moving on. Kind of dirty, but found effective when dealing with # international characters. import sys encoding = sys.getfilesystemencoding() if encoding is not None: try: user.encode('utf-16le') except: user = user.decode(encoding) try: password.encode('utf-16le') except: password = password.decode(encoding) try: domain.encode('utf-16le') except: domain = user.decode(encoding) ntlmChallenge = NTLMAuthChallenge(type2) # Let's start with the original flags sent in the type1 message responseFlags = type1['flags'] # Token received and parsed. Depending on the authentication # method we will create a valid ChallengeResponse ntlmChallengeResponse = NTLMAuthChallengeResponse(user, password, ntlmChallenge['challenge']) clientChallenge = b("".join([random.choice(string.digits+string.ascii_letters) for _ in range(8)])) serverName = ntlmChallenge['TargetInfoFields'] ntResponse, lmResponse, sessionBaseKey = computeResponse(ntlmChallenge['flags'], ntlmChallenge['challenge'], clientChallenge, serverName, domain, user, password, lmhash, nthash, use_ntlmv2) # Let's check the return flags if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) == 0: # No extended session security, taking it out responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_128 ) == 0: # No support for 128 key len, taking it out responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_128 if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_KEY_EXCH) == 0: # No key exchange supported, taking it out responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_KEY_EXCH if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_SEAL) == 0: # No sign available, taking it out responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_SEAL if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_SIGN) == 0: # No sign available, taking it out responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_SIGN if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) == 0: # No sign available, taking it out responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_ALWAYS_SIGN keyExchangeKey = KXKEY(ntlmChallenge['flags'], sessionBaseKey, lmResponse, ntlmChallenge['challenge'], password, lmhash, nthash, use_ntlmv2) # Special case for anonymous login if user == '' and password == '' and lmhash == '' and nthash == '': keyExchangeKey = b'\x00'*16 # If we set up key exchange, let's fill the right variables if ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_KEY_EXCH: # not exactly what I call random tho :\ # exportedSessionKey = this is the key we should use to sign exportedSessionKey = b("".join([random.choice(string.digits+string.ascii_letters) for _ in range(16)])) #exportedSessionKey = "A"*16 #print "keyExchangeKey %r" % keyExchangeKey # Let's generate the right session key based on the challenge flags #if responseFlags & NTLMSSP_NTLM2_KEY: # Extended session security enabled # if responseFlags & NTLMSSP_KEY_128: # Full key # exportedSessionKey = exportedSessionKey # elif responseFlags & NTLMSSP_KEY_56: # Only 56-bit key # exportedSessionKey = exportedSessionKey[:7] # else: # exportedSessionKey = exportedSessionKey[:5] #elif responseFlags & NTLMSSP_KEY_56: # No extended session security, just 56 bits key # exportedSessionKey = exportedSessionKey[:7] + '\xa0' #else: # exportedSessionKey = exportedSessionKey[:5] + '\xe5\x38\xb0' encryptedRandomSessionKey = generateEncryptedSessionKey(keyExchangeKey, exportedSessionKey) else: encryptedRandomSessionKey = None # [MS-NLMP] page 46 exportedSessionKey = keyExchangeKey ntlmChallengeResponse['flags'] = responseFlags ntlmChallengeResponse['domain_name'] = domain.encode('utf-16le') ntlmChallengeResponse['host_name'] = type1.getWorkstation().encode('utf-16le') if lmResponse == '': ntlmChallengeResponse['lanman'] = b'\x00' else: ntlmChallengeResponse['lanman'] = lmResponse ntlmChallengeResponse['ntlm'] = ntResponse if encryptedRandomSessionKey is not None: ntlmChallengeResponse['session_key'] = encryptedRandomSessionKey return ntlmChallengeResponse, exportedSessionKey # NTLMv1 Algorithm def generateSessionKeyV1(password, lmhash, nthash): hash = MD4.new() hash.update(NTOWFv1(password, lmhash, nthash)) return hash.digest() def computeResponseNTLMv1(flags, serverChallenge, clientChallenge, serverName, domain, user, password, lmhash='', nthash='', use_ntlmv2=USE_NTLMv2): if user == '' and password == '': # Special case for anonymous authentication lmResponse = '' ntResponse = '' else: lmhash = LMOWFv1(password, lmhash, nthash) nthash = NTOWFv1(password, lmhash, nthash) if flags & NTLMSSP_NEGOTIATE_LM_KEY: ntResponse = '' lmResponse = get_ntlmv1_response(lmhash, serverChallenge) elif flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: md5 = hashlib.new('md5') chall = (serverChallenge + clientChallenge) md5.update(chall) ntResponse = ntlmssp_DES_encrypt(nthash, md5.digest()[:8]) lmResponse = clientChallenge + b'\x00'*16 else: ntResponse = get_ntlmv1_response(nthash,serverChallenge) lmResponse = get_ntlmv1_response(lmhash, serverChallenge) sessionBaseKey = generateSessionKeyV1(password, lmhash, nthash) return ntResponse, lmResponse, sessionBaseKey def compute_lmhash(password): # This is done according to Samba's encryption specification (docs/html/ENCRYPTION.html) password = password.upper() lmhash = __DES_block(b(password[:7]), KNOWN_DES_INPUT) lmhash += __DES_block(b(password[7:14]), KNOWN_DES_INPUT) return lmhash def NTOWFv1(password, lmhash = '', nthash=''): if nthash != '': return nthash return compute_nthash(password) def LMOWFv1(password, lmhash = '', nthash=''): if lmhash != '': return lmhash return compute_lmhash(password) def compute_nthash(password): # This is done according to Samba's encryption specification (docs/html/ENCRYPTION.html) try: password = str(password).encode('utf_16le') except UnicodeDecodeError: import sys password = password.decode(sys.getfilesystemencoding()).encode('utf_16le') hash = MD4.new() hash.update(password) return hash.digest() def get_ntlmv1_response(key, challenge): return ntlmssp_DES_encrypt(key, challenge) # NTLMv2 Algorithm - as described in MS-NLMP Section 3.3.2 # Crypto Stuff def MAC(flags, handle, signingKey, seqNum, message): # [MS-NLMP] Section 3.4.4 # Returns the right messageSignature depending on the flags messageSignature = NTLMMessageSignature(flags) if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: if flags & NTLMSSP_NEGOTIATE_KEY_EXCH: messageSignature['Version'] = 1 messageSignature['Checksum'] = \ struct.unpack(' Local Policies -> Security Options -> Server SPN target name validation # level if TEST_CASE is False: av_pairs[NTLMSSP_AV_TARGET_NAME] = 'cifs/'.encode('utf-16le') + av_pairs[NTLMSSP_AV_HOSTNAME][1] if av_pairs[NTLMSSP_AV_TIME] is not None: aTime = av_pairs[NTLMSSP_AV_TIME][1] else: aTime = struct.pack('