def __decryptHash(self, record): # logging.debug('Decrypting hash for user: %s' % record[self.NAME_TO_INTERNAL['name']]) sid = SAMR_RPC_SID(record[self.NAME_TO_INTERNAL['objectSid']].decode('hex')) rid = sid.formatCanonical().split('-')[-1] if record[self.NAME_TO_INTERNAL['dBCSPwd']] is not None: encryptedLMHash = self.CRYPTED_HASH(record[self.NAME_TO_INTERNAL['dBCSPwd']].decode('hex')) tmpLMHash = self.__removeRC4Layer(encryptedLMHash) LMHash = self.__removeDESLayer(tmpLMHash, rid) else: LMHash = ntlm.LMOWFv1('','') encryptedLMHash = None if record[self.NAME_TO_INTERNAL['unicodePwd']] is not None: encryptedNTHash = self.CRYPTED_HASH(record[self.NAME_TO_INTERNAL['unicodePwd']].decode('hex')) tmpNTHash = self.__removeRC4Layer(encryptedNTHash) NTHash = self.__removeDESLayer(tmpNTHash, rid) else: NTHash = ntlm.NTOWFv1('','') encryptedNTHash = None if record[self.NAME_TO_INTERNAL['userPrincipalName']] is not None: domain = record[self.NAME_TO_INTERNAL['userPrincipalName']].split('@')[-1] userName = '******' % (domain, record[self.NAME_TO_INTERNAL['sAMAccountName']]) else: userName = '******' % record[self.NAME_TO_INTERNAL['sAMAccountName']] answer = "%s:%s:%s:%s:::" % (userName, rid, LMHash.encode('hex'), NTHash.encode('hex')) self.__hashesFound[record[self.NAME_TO_INTERNAL['objectSid']].decode('hex')] = answer # print answer if self.__history: LMHistory = [] NTHistory = [] if record[self.NAME_TO_INTERNAL['lmPwdHistory']] is not None: lmPwdHistory = record[self.NAME_TO_INTERNAL['lmPwdHistory']] encryptedLMHistory = self.CRYPTED_HISTORY(record[self.NAME_TO_INTERNAL['lmPwdHistory']].decode('hex')) tmpLMHistory = self.__removeRC4Layer(encryptedLMHistory) for i in range(0, len(tmpLMHistory)/16): LMHash = self.__removeDESLayer(tmpLMHistory[i*16:(i+1)*16], rid) LMHistory.append(LMHash) if record[self.NAME_TO_INTERNAL['ntPwdHistory']] is not None: ntPwdHistory = record[self.NAME_TO_INTERNAL['ntPwdHistory']] encryptedNTHistory = self.CRYPTED_HISTORY(record[self.NAME_TO_INTERNAL['ntPwdHistory']].decode('hex')) tmpNTHistory = self.__removeRC4Layer(encryptedNTHistory) for i in range(0, len(tmpNTHistory)/16): NTHash = self.__removeDESLayer(tmpNTHistory[i*16:(i+1)*16], rid) NTHistory.append(NTHash) for i, (LMHash, NTHash) in enumerate(map(lambda l,n: (l,n) if l else ('',n), LMHistory[1:], NTHistory[1:])): if self.__noLMHash: lmhash = ntlm.LMOWFv1('','').encode('hex') else: lmhash = LMHash.encode('hex') answer = "%s_history%d:%s:%s:%s:::" % (userName, i, rid, lmhash, NTHash.encode('hex')) self.__hashesFound[record[self.NAME_TO_INTERNAL['objectSid']].decode('hex')+str(i)] = answer
def dump(self): NTPASSWORD = "******" LMPASSWORD = "******" if self.__samFile is None: # No SAM file provided return self.getHBootKey() usersKey = 'SAM\\Domains\\Account\\Users' # Enumerate all the RIDs rids = self.enumKey(usersKey) # Remove the Names item try: rids.remove('Names') except: pass for rid in rids: userAccount = USER_ACCOUNT_V( self.getValue(ntpath.join(usersKey, rid, 'V'))[1]) rid = int(rid, 16) baseOffset = len(USER_ACCOUNT_V()) V = userAccount['Data'] userName = V[userAccount['NameOffset']:userAccount['NameOffset'] + userAccount['NameLength']].decode('utf-16le') if userAccount['LMHashLength'] == 20: encLMHash = V[userAccount['LMHashOffset'] + 4:userAccount['LMHashOffset'] + userAccount['LMHashLength']] else: encLMHash = '' if userAccount['NTHashLength'] == 20: encNTHash = V[userAccount['NTHashOffset'] + 4:userAccount['NTHashOffset'] + userAccount['NTHashLength']] else: encNTHash = '' lmHash = self.__decryptHash(rid, encLMHash, LMPASSWORD) ntHash = self.__decryptHash(rid, encNTHash, NTPASSWORD) if lmHash == '': lmHash = ntlm.LMOWFv1('', '') if ntHash == '': ntHash = ntlm.NTOWFv1('', '') answer = "%s:%d:%s:%s:::" % (userName, rid, lmHash.encode('hex'), ntHash.encode('hex')) self.__itemsFound[rid] = answer return self.__itemsFound
def test_NetrLogonSamLogonWithFlags(self): dce, rpctransport = self.connect() request = nrpc.NetrLogonSamLogonWithFlags() request['LogonServer'] = '\x00' request['ComputerName'] = self.serverName + '\x00' request[ 'LogonLevel'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation request['LogonInformation'][ 'tag'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation request['LogonInformation']['LogonInteractive']['Identity'][ 'LogonDomainName'] = self.domain request['LogonInformation']['LogonInteractive']['Identity'][ 'ParameterControl'] = 2 + 2**14 + 2**7 + 2**9 + 2**5 + 2**11 request['LogonInformation']['LogonInteractive']['Identity'][ 'UserName'] = self.username request['LogonInformation']['LogonInteractive']['Identity'][ 'Workstation'] = '' if len(self.hashes) > 0: lmhash, nthash = self.hashes.split(':') lmhash = unhexlify(lmhash) nthash = unhexlify(nthash) else: lmhash = ntlm.LMOWFv1(self.password) nthash = ntlm.NTOWFv1(self.password) try: from Cryptodome.Cipher import ARC4 except Exception: print( "Warning: You don't have any crypto installed. You need pycryptodomex" ) print("See https://pypi.org/project/pycryptodomex/") rc4 = ARC4.new(self.sessionKey) lmhash = rc4.encrypt(lmhash) rc4 = ARC4.new(self.sessionKey) nthash = rc4.encrypt(nthash) request['LogonInformation']['LogonInteractive'][ 'LmOwfPassword'] = lmhash request['LogonInformation']['LogonInteractive'][ 'NtOwfPassword'] = nthash request[ 'ValidationLevel'] = nrpc.NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4 request['Authenticator'] = self.update_authenticator() request['ReturnAuthenticator']['Credential'] = b'\x00' * 8 request['ReturnAuthenticator']['Timestamp'] = 0 request['ExtraFlags'] = 0 try: resp = dce.request(request) resp.dump() except Exception as e: if str(e).find('STATUS_NO_SUCH_USER') < 0: raise
def test_NetrLogonSamLogon(self): dce, rpctransport = self.connect() self.authenticate(dce) request = nrpc.NetrLogonSamLogon() request['LogonServer'] = self.serverName + '\x00' request['ComputerName'] = self.machine_user + '\x00' request[ 'LogonLevel'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation request['LogonInformation'][ 'tag'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation request['LogonInformation']['LogonInteractive']['Identity'][ 'LogonDomainName'] = self.domain request['LogonInformation']['LogonInteractive']['Identity'][ 'ParameterControl'] = 2 request['LogonInformation']['LogonInteractive']['Identity'][ 'UserName'] = self.username request['LogonInformation']['LogonInteractive']['Identity'][ 'Workstation'] = '' if len(self.hashes): blmhash = self.blmhash bnthash = self.bnthash else: blmhash = ntlm.LMOWFv1(self.password) bnthash = ntlm.NTOWFv1(self.password) try: from Cryptodome.Cipher import ARC4 except Exception: print( "Warning: You don't have any crypto installed. You need PyCrypto" ) print("See http://www.pycrypto.org/") rc4 = ARC4.new(self.sessionKey) blmhash = rc4.encrypt(blmhash) rc4 = ARC4.new(self.sessionKey) bnthash = rc4.encrypt(bnthash) request['LogonInformation']['LogonInteractive'][ 'LmOwfPassword'] = blmhash request['LogonInformation']['LogonInteractive'][ 'NtOwfPassword'] = bnthash request[ 'ValidationLevel'] = nrpc.NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo2 request['Authenticator'] = self.update_authenticator() request['ReturnAuthenticator']['Credential'] = b'\x00' * 8 request['ReturnAuthenticator']['Timestamp'] = 0 try: dce.request(request) except DCERPCException as e: if str(e).find('STATUS_NO_SUCH_USER') < 0: raise
def test_NetrLogonSamLogon(self): dce, rpctransport = self.connect() request = nrpc.NetrLogonSamLogon() request['LogonServer'] = '\x00' request['ComputerName'] = self.serverName + '\x00' request[ 'LogonLevel'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation request['LogonInformation'][ 'tag'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation request['LogonInformation']['LogonInteractive']['Identity'][ 'LogonDomainName'] = self.domain request['LogonInformation']['LogonInteractive']['Identity'][ 'ParameterControl'] = 2 request['LogonInformation']['LogonInteractive']['Identity'][ 'UserName'] = self.username request['LogonInformation']['LogonInteractive']['Identity'][ 'Workstation'] = '' if len(self.hashes) > 0: lmhash, nthash = self.hashes.split(':') lmhash = lmhash.decode('hex') nthash = nthash.decode('hex') else: lmhash = ntlm.LMOWFv1(self.password) nthash = ntlm.NTOWFv1(self.password) try: from Crypto.Cipher import ARC4 except Exception: print "Warning: You don't have any crypto installed. You need PyCrypto" print "See http://www.pycrypto.org/" from impacket import crypto rc4 = ARC4.new(self.sessionKey) lmhash = rc4.encrypt(lmhash) rc4 = ARC4.new(self.sessionKey) nthash = rc4.encrypt(nthash) request['LogonInformation']['LogonInteractive'][ 'LmOwfPassword'] = lmhash request['LogonInformation']['LogonInteractive'][ 'NtOwfPassword'] = nthash request[ 'ValidationLevel'] = nrpc.NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo2 request['Authenticator'] = self.update_authenticator() request['ReturnAuthenticator']['Credential'] = '\x00' * 8 request['ReturnAuthenticator']['Timestamp'] = 0 try: resp = dce.request(request) resp.dump() except Exception, e: if str(e).find('STATUS_NO_SUCH_USER') < 0: raise
def test_NetrLogonSamLogonEx(self): dce, rpctransport = self.connect() self.authenticate(dce) request = nrpc.NetrLogonSamLogonEx() request['LogonServer'] = self.serverName + '\x00' request['ComputerName'] = self.machine_user + '\x00' request[ 'LogonLevel'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation request['LogonInformation'][ 'tag'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation request['LogonInformation']['LogonInteractive']['Identity'][ 'LogonDomainName'] = self.domain request['LogonInformation']['LogonInteractive']['Identity'][ 'ParameterControl'] = 2 + 2**14 + 2**7 + 2**9 + 2**5 + 2**11 request['LogonInformation']['LogonInteractive']['Identity'][ 'UserName'] = self.username request['LogonInformation']['LogonInteractive']['Identity'][ 'Workstation'] = '' if len(self.hashes): blmhash = self.blmhash bnthash = self.bnthash else: blmhash = ntlm.LMOWFv1(self.password) bnthash = ntlm.NTOWFv1(self.password) try: from Cryptodome.Cipher import ARC4 except Exception: print( "Warning: You don't have any crypto installed. You need pycryptodomex" ) print("See https://pypi.org/project/pycryptodomex/") rc4 = ARC4.new(self.sessionKey) blmhash = rc4.encrypt(blmhash) rc4 = ARC4.new(self.sessionKey) bnthash = rc4.encrypt(bnthash) request['LogonInformation']['LogonInteractive'][ 'LmOwfPassword'] = blmhash request['LogonInformation']['LogonInteractive'][ 'NtOwfPassword'] = bnthash request[ 'ValidationLevel'] = nrpc.NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4 request['ExtraFlags'] = 1 try: dce.request(request) except DCERPCException as e: if str(e).find('STATUS_INTERNAL_ERROR') < 0: raise
def test_NetrLogonSamLogonEx(self): dce, rpctransport = self.connect() request = nrpc.NetrLogonSamLogonEx() request['LogonServer'] = '\x00' request['ComputerName'] = self.serverName + '\x00' request[ 'LogonLevel'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation request['LogonInformation'][ 'tag'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation request['LogonInformation']['LogonInteractive']['Identity'][ 'LogonDomainName'] = self.domain request['LogonInformation']['LogonInteractive']['Identity'][ 'ParameterControl'] = 2 + 2**14 + 2**7 + 2**9 + 2**5 + 2**11 request['LogonInformation']['LogonInteractive']['Identity'][ 'UserName'] = self.username request['LogonInformation']['LogonInteractive']['Identity'][ 'Workstation'] = '' if len(self.hashes) > 0: lmhash, nthash = self.hashes.split(':') lmhash = lmhash.decode('hex') nthash = nthash.decode('hex') else: lmhash = ntlm.LMOWFv1(self.password) nthash = ntlm.NTOWFv1(self.password) try: from Crypto.Cipher import ARC4 except Exception: print "Warning: You don't have any crypto installed. You need PyCrypto" print "See http://www.pycrypto.org/" from impacket import crypto rc4 = ARC4.new(self.sessionKey) lmhash = rc4.encrypt(lmhash) rc4 = ARC4.new(self.sessionKey) nthash = rc4.encrypt(nthash) request['LogonInformation']['LogonInteractive'][ 'LmOwfPassword'] = lmhash request['LogonInformation']['LogonInteractive'][ 'NtOwfPassword'] = nthash request[ 'ValidationLevel'] = nrpc.NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4 request['ExtraFlags'] = 1 resp = dce.request(request) resp.dump()
def __printSecret(self, name, secretItem): # Based on [MS-LSAD] section 3.1.1.4 # First off, let's discard NULL secrets. if len(secretItem) == 0: logger.debug('Discarding secret %s, NULL Data' % name) return # We might have secrets with zero if secretItem.startswith('\x00\x00'): logger.debug('Discarding secret %s, all zeros' % name) return upperName = name.upper() logger.info('%s ' % name) secret = '' if upperName.startswith('_SC_'): # Service name, a password might be there # Let's first try to decode the secret try: strDecoded = secretItem.decode('utf-16le') except: pass else: # We have to get the account the service # runs under account = self.get_service_account(name[4:]) if account is None: secret = '(Unknown User) ' else: secret = "%s " % account secret += strDecoded elif upperName.startswith('DEFAULTPASSWORD'): # defaults password for winloggeron # Let's first try to decode the secret try: strDecoded = secretItem.decode('utf-16le') except: pass else: # We have to get the account this password is for account = self.get_default_loggerin_account() if account is None: secret = '(Unknown User) ' else: secret = "%s " % account secret += strDecoded elif upperName.startswith('ASPNET_WP_PASSWORD'): try: strDecoded = secretItem.decode('utf-16le') except: pass else: secret = 'ASPNET %s' % strDecoded elif upperName.startswith('$MACHINE.ACC'): # Compute MD4 of the secret.. yes.. that is the nthash md4 = MD4.new() md4.update(secretItem) secret = "%s\\%s$:%s:%s:::" % ( DataStore.server_domain, DataStore.server_name, ntlm.LMOWFv1('', '').encode('hex'), md4.digest().encode('hex')) if secret != '': print secret self.__secretItems.append(secret) else: # Default print, hexdump self.__secretItems.append('%s %s' % (name, secretItem.encode('hex'))) hexdump(secretItem)
def dumpSAM(self): NTPASSWORD = b"NTPASSWORD\0" LMPASSWORD = b"LMPASSWORD\0" if self.__samFile is None: # No SAM file provided return logger.info('Dumping local SAM hashes (uid:rid:lmhash:nthash)') self.getHBootKey() usersKey = 'SAM\\Domains\\Account\\Users' # Enumerate all the RIDs rids = self.enumKey(usersKey) # Remove the Names item try: rids.remove('Names') except: pass for rid in rids: try: userAccount = USER_ACCOUNT_V( self.getValue(ntpath.join(usersKey, rid, 'V'))[1]) rid = int(rid, 16) logger.debug("Dumping %s from SAM" % str(rid)) V = userAccount['Data'] userName = V[ userAccount['NameOffset']:userAccount['NameOffset'] + userAccount['NameLength']].decode('utf-16le') encNTHash = b'' if V[userAccount['NTHashOffset']:][2:3] == b'\x01': # Old Style hashes newStyle = False logger.debug('NewStyle hashes is: %s' % newStyle) if userAccount['LMHashLength'] == 20: encLMHash = SAM_HASH(V[userAccount['LMHashOffset']:] [:userAccount['LMHashLength']]) if userAccount['NTHashLength'] == 20: encNTHash = SAM_HASH(V[userAccount['NTHashOffset']:] [:userAccount['NTHashLength']]) else: # New Style hashes newStyle = True logger.debug('NewStyle hashes is: %s' % newStyle) if userAccount['LMHashLength'] == 24: encLMHash = SAM_HASH_AES( V[userAccount['LMHashOffset']:] [:userAccount['LMHashLength']]) encNTHash = SAM_HASH_AES(V[userAccount['NTHashOffset']:] [:userAccount['NTHashLength']]) if userAccount['LMHashLength'] >= 20: lmHash = self.__decryptHash(rid, encLMHash, LMPASSWORD, newStyle) else: lmHash = b'' if encNTHash != b'': ntHash = self.__decryptHash(rid, encNTHash, NTPASSWORD, newStyle) else: ntHash = b'' if lmHash == b'': lmHash = ntlm.LMOWFv1('', '') if ntHash == b'': ntHash = ntlm.NTOWFv1('', '') answer = "%s:%d:%s:%s:::" % (userName, rid, hexlify(lmHash).decode('utf-8'), hexlify(ntHash).decode('utf-8')) self.__itemsFound[rid] = answer self.__perSecretCallback(answer) except Exception as e: logger.error('Error encountered when dumping SAM for user ' + userName + ': ' + str(e))
def test_ntlmv1(self): print("####### 4.2.2 NTLMv1 Authentication") ntlm.USE_NTLMv2 = False print("4.2.2.1 LMOWFv1()") res = ntlm.LMOWFv1(self.password) hexdump(res) self.assertTrue( res == bytearray(b'\xe5,\xacgA\x9a\x9a"J;\x10\x8f?\xa6\xcbm')) print("\n") print("4.2.2.1.2 NTOWFv1()") res = ntlm.NTOWFv1(self.password) hexdump(res) self.assertTrue(res == bytearray( b'\xa4\xf4\x9c\x40\x65\x10\xbd\xca\xb6\x82\x4e\xe7\xc3\x0f\xd8\x52' )) print("\n") print("4.2.2.1.3 Session Base Key and Key Exchange Key") ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv1( int(self.flags), self.serverChallenge, self.clientChallenge, self.serverName, self.domain, self.user, self.password, '', '') hexdump(sessionBaseKey) self.assertTrue(sessionBaseKey == bytearray( b'\xD8\x72\x62\xB0\xCD\xE4\xB1\xCB\x74\x99\xBE\xCC\xCD\xF1\x07\x84' )) print("\n") print("4.2.2.2.1 NTLMv1 Response") hexdump(ntResponse) self.assertTrue(ntResponse == bytearray( b'\x67\xC4\x30\x11\xF3\x02\x98\xA2\xAD\x35\xEC\xE6\x4F\x16\x33\x1C\x44\xBD\xBE\xD9\x27\x84\x1F\x94' )) print("\n") print("4.2.2.2.2 LMv1 Response") hexdump(lmResponse) self.assertTrue(lmResponse == bytearray( b'\x98\xDE\xF7\xB8\x7F\x88\xAA\x5D\xAF\xE2\xDF\x77\x96\x88\xA1\x72\xde\xf1\x1c\x7d\x5c\xcd\xef\x13' )) print("\n") print("4.2.2.2.2 LMv1 Response with NTLMSSP_NEGOTIATE_LM_KEY set") flags2 = self.flags #flags2 = flags | ntlm.NTLMSSP_LM_KEY #hexdump(struct.pack('<L',flags2)) ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv1( int(flags2), self.serverChallenge, self.clientChallenge, self.serverName, self.domain, self.user, self.password, '', '') hexdump(lmResponse) print("\n") print("4.2.2.2.3 Encrypted Session Key ") ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv1( int(self.flags), self.serverChallenge, self.clientChallenge, self.serverName, self.domain, self.user, self.password, '', '') keyExchangeKey = ntlm.KXKEY(self.flags, sessionBaseKey, lmResponse, self.serverChallenge, self.password, '', '') encryptedSessionKey = ntlm.generateEncryptedSessionKey( keyExchangeKey, self.randomSessionKey) hexdump(encryptedSessionKey) self.assertTrue(encryptedSessionKey == bytearray( b'\x51\x88\x22\xB1\xB3\xF3\x50\xC8\x95\x86\x82\xEC\xBB\x3E\x3C\xB7' )) print("\n") print("4.2.2.2.3 Encrypted Session Key (NTLMSSP_NON_NT_KEY)") flags2 = self.flags | ntlm.NTLMSSP_REQUEST_NON_NT_SESSION_KEY keyExchangeKey = ntlm.KXKEY(flags2, sessionBaseKey, lmResponse, self.serverChallenge, self.password, '', '') encryptedSessionKey = ntlm.generateEncryptedSessionKey( keyExchangeKey, self.randomSessionKey) hexdump(encryptedSessionKey) #ToDo Fix this #self.assertTrue(encryptedSessionKey==bytearray(b'\x74\x52\xca\x55\xc2\x25\xa1\xca\x04\xb4\x8f\xae\x32\xcf\x56\xfc')) print("\n") print("4.2.2.2.3 Encrypted Session Key (NTLMSSP_LM_KEY)") flags2 = self.flags | ntlm.NTLMSSP_NEGOTIATE_LM_KEY #hexdump(struct.pack('<L',flags2)) keyExchangeKey = ntlm.KXKEY(flags2, sessionBaseKey, lmResponse, self.serverChallenge, self.password, '', '') encryptedSessionKey = ntlm.generateEncryptedSessionKey( keyExchangeKey, self.randomSessionKey) hexdump(encryptedSessionKey) #ToDo Fix this #self.assertTrue(encryptedSessionKey==bytearray(b'\x4c\xd7\xbb\x57\xd6\x97\xef\x9b\x54\x9f\x02\xb8\xf9\xb3\x78\x64') print("\n") print("4.2.2.3 AUTHENTICATE MESSAGE") ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv1( int(self.flags), self.serverChallenge, self.clientChallenge, self.serverName, self.domain, self.user, self.password, '', '') keyExchangeKey = ntlm.KXKEY(self.flags, sessionBaseKey, lmResponse, self.serverChallenge, self.password, '', '') encryptedSessionKey = ntlm.generateEncryptedSessionKey( keyExchangeKey, self.randomSessionKey) ntlmChallengeResponse = ntlm.NTLMAuthChallengeResponse( self.user, self.password, self.serverChallenge) ntlmChallengeResponse['flags'] = flags2 ntlmChallengeResponse['host_name'] = self.workstationName.encode( 'utf-16le') ntlmChallengeResponse['domain_name'] = self.domain.encode('utf-16le') ntlmChallengeResponse['lanman'] = lmResponse ntlmChallengeResponse['ntlm'] = ntResponse ntlmChallengeResponse['session_key'] = encryptedSessionKey hexdump(ntlmChallengeResponse.getData()) self.assertTrue(ntlmChallengeResponse.getData() == bytearray( b'NTLMSSP\x00\x03\x00\x00\x00\x18\x00\x18\x00|\x00\x00\x00\x18\x00\x18\x00\x94\x00\x00\x00\x0c\x00\x0c\x00X\x00\x00\x00\x08\x00\x08\x00d\x00\x00\x00\x10\x00\x10\x00l\x00\x00\x00\x10\x00\x10\x00\xac\x00\x00\x00\xb3\x82\x02\xe2D\x00o\x00m\x00a\x00i\x00n\x00U\x00s\x00e\x00r\x00C\x00O\x00M\x00P\x00U\x00T\x00E\x00R\x00\x98\xde\xf7\xb8\x7f\x88\xaa]\xaf\xe2\xdfw\x96\x88\xa1r\xde\xf1\x1c}\\\xcd\xef\x13g\xc40\x11\xf3\x02\x98\xa2\xad5\xec\xe6O\x163\x1cD\xbd\xbe\xd9\'\x84\x1f\x94Q\x88"\xb1\xb3\xf3P\xc8\x95\x86\x82\xec\xbb><\xb7' )) print("\n") print("4.2.2.4 GSS_WrapEx") print("Output of SEAL()") from Cryptodome.Cipher import ARC4 cipher = ARC4.new(self.randomSessionKey) handle = cipher.encrypt print("Plaintext") hexdump(self.plaintext) print("\n") sealedMsg, signature = ntlm.SEAL(self.flags, self.nonce, self.nonce, self.plaintext, self.plaintext, self.seqNum, handle) #signature = ntlm.SIGN(flags, nonce, plaintext, seqNum, handle) hexdump(sealedMsg) self.assertTrue(sealedMsg == bytearray( b'V\xfe\x04\xd8a\xf91\x9a\xf0\xd7#\x8a.;ME\x7f\xb8')) print("\n") hexdump(signature.getData()) self.assertTrue(signature.getData() == bytearray( b'\x01\x00\x00\x00\x00\x00\x00\x00\t\xdc\xd1\xdf.E\x9d6')) print("\n") print("####### 4.2.3 NTLMv1 with Client Challenge") flags = ntlm.NTLMSSP_NEGOTIATE_56 | ntlm.NTLMSSP_NEGOTIATE_VERSION | ntlm.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY \ | ntlm.NTLMSSP_TARGET_TYPE_SERVER | ntlm.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | ntlm.NTLMSSP_NEGOTIATE_NTLM |\ ntlm.NTLMSSP_NEGOTIATE_SEAL | ntlm.NTLMSSP_NEGOTIATE_SIGN | ntlm.NTLM_NEGOTIATE_OEM | ntlm.NTLMSSP_NEGOTIATE_UNICODE print("Flags") hexdump(struct.pack('<L', flags)) print("\n") print("4.2.3.1.1 NTOWFv1(password)") hexdump(ntlm.NTOWFv1(self.password)) print("\n") print("4.2.3.1.2 Session Base Key") ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv1( int(flags), self.serverChallenge, self.clientChallenge, self.serverName, self.domain, self.user, self.password, '', '') hexdump(sessionBaseKey) self.assertTrue(sessionBaseKey == bytearray( b'\xd8rb\xb0\xcd\xe4\xb1\xcbt\x99\xbe\xcc\xcd\xf1\x07\x84')) print("\n") print("4.2.3.1.3 Key Exchange Key") keyExchangeKey = ntlm.KXKEY(flags, sessionBaseKey, lmResponse, self.serverChallenge, self.password, '', '') hexdump(keyExchangeKey) # ToDo: Fix this #self.assertTrue(keyExchangeKey==bytearray(b'\xeb\x93\x42\x9a\x8b\xd9\x52\xf8\xb8\x9c\x55\xb8\x7f\x47\x5e\xdc')) print("\n") print("4.2.3.2.1 LMv1 Response") hexdump(lmResponse) #self.assertTrue(lmResponse==bytearray(b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')) print("\n") print("4.2.3.2.2 NTLMv1 Response") hexdump(ntResponse) # ToDo: Fix this #self.assertTrue(ntResponse==bytearray(b'\x75\x37\xf8\x03\xae\x36\x71\x28\xca\x45\x82\x04\xbd\xe7\xca\xf8\x1e\x97\xed\x26\x83\x26\x72\x32')) print("\n") print("AUTHENTICATE MESSAGE") ntlm.generateEncryptedSessionKey(keyExchangeKey, self.randomSessionKey) ntlmChallengeResponse = ntlm.NTLMAuthChallengeResponse( self.user, self.password, self.serverChallenge) ntlmChallengeResponse['flags'] = flags2 ntlmChallengeResponse['host_name'] = self.workstationName.encode( 'utf-16le') ntlmChallengeResponse['domain_name'] = self.domain.encode('utf-16le') ntlmChallengeResponse['lanman'] = lmResponse ntlmChallengeResponse['ntlm'] = ntResponse hexdump(ntlmChallengeResponse.getData()) self.assertTrue(ntlmChallengeResponse.getData() == bytearray( b'NTLMSSP\x00\x03\x00\x00\x00\x18\x00\x18\x00|\x00\x00\x00\x18\x00\x18\x00\x94\x00\x00\x00\x0c\x00\x0c\x00X\x00\x00\x00\x08\x00\x08\x00d\x00\x00\x00\x10\x00\x10\x00l\x00\x00\x00\x00\x00\x00\x00\xac\x00\x00\x00\xb3\x82\x02\xe2D\x00o\x00m\x00a\x00i\x00n\x00U\x00s\x00e\x00r\x00C\x00O\x00M\x00P\x00U\x00T\x00E\x00R\x00\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00u7\xf8\x03\xae6q(\xcaE\x82\x04\xbd\xe7\xca\xf8\x1e\x97\xed&\x83&r2' )) print("\n") print("4.2.3.4 GSS_WrapEx") print("Plaintext") hexdump(self.plaintext) print("\n") print("Output of SEAL()") exportedSessionKey = keyExchangeKey clientSigningKey = ntlm.SIGNKEY(flags, exportedSessionKey) clientSealingKey = ntlm.SEALKEY(flags, exportedSessionKey) from Cryptodome.Cipher import ARC4 cipher = ARC4.new(clientSigningKey) cipher2 = ARC4.new(clientSealingKey) client_sealing_h = cipher2.encrypt print("SEALKEY()") hexdump(clientSealingKey) print("\n") print("SIGNKEY()") hexdump(clientSigningKey) print("\n") print("Sealed Data") sealedMsg, signature = ntlm.SEAL(flags, clientSealingKey, clientSigningKey, self.plaintext, self.plaintext, self.seqNum, client_sealing_h) #signature = ntlm.SIGN(flags, clientSigningKey, plaintext, seqNum, client_sealing_h) hexdump(sealedMsg) # ToDo: Fix this #self.assertTrue(ntResponse==bytearray(b'\xa0\x23\x72\xf6\x53\x02\x73\xf3\xaa\x1e\xb9\x01\x90\xce\x52\x00\xc9\x9d')) print("\n") print("Signature") hexdump(signature.getData()) # ToDo: Fix this #self.assertTrue(ntResponse==bytearray(b'\x01\x00\x00\x00\xff\x2a\xeb\x52\xf6\x81\x79\x3a\x00\x00\x00\x00') print("\n")
def __decryptHash(self, record, rid=None, prefixTable=None, outputFile=None): if self.__useVSSMethod is True: logging.debug('Decrypting hash for user: %s' % record[self.NAME_TO_INTERNAL['name']]) sid = SAMR_RPC_SID( unhexlify(record[self.NAME_TO_INTERNAL['objectSid']])) rid = sid.formatCanonical().split('-')[-1] if record[self.NAME_TO_INTERNAL['dBCSPwd']] is not None: encryptedLMHash = self.CRYPTED_HASH( unhexlify(record[self.NAME_TO_INTERNAL['dBCSPwd']])) tmpLMHash = self.__removeRC4Layer(encryptedLMHash) LMHash = self.__removeDESLayer(tmpLMHash, rid) else: LMHash = ntlm.LMOWFv1('', '') if record[self.NAME_TO_INTERNAL['unicodePwd']] is not None: encryptedNTHash = self.CRYPTED_HASH( unhexlify(record[self.NAME_TO_INTERNAL['unicodePwd']])) tmpNTHash = self.__removeRC4Layer(encryptedNTHash) NTHash = self.__removeDESLayer(tmpNTHash, rid) else: NTHash = ntlm.NTOWFv1('', '') if record[self.NAME_TO_INTERNAL['userPrincipalName']] is not None: domain = record[ self.NAME_TO_INTERNAL['userPrincipalName']].split('@')[-1] userName = '******' % ( domain, record[self.NAME_TO_INTERNAL['sAMAccountName']]) else: userName = '******' % record[ self.NAME_TO_INTERNAL['sAMAccountName']] if record[self.NAME_TO_INTERNAL['pwdLastSet']] is not None: pwdLastSet = self.__fileTimeToDateTime( record[self.NAME_TO_INTERNAL['pwdLastSet']]) else: pwdLastSet = 'N/A' answer = "%s:%s:%s:%s:::" % (userName, rid, hexlify(LMHash), hexlify(NTHash)) if outputFile is not None: self.__writeOutput(outputFile, answer + '\n') if self.__pwdLastSet is True: answer = "%s (pwdLastSet=%s)" % (answer, pwdLastSet) self.__logger.highlight(answer) if self.__history: LMHistory = [] NTHistory = [] if record[self.NAME_TO_INTERNAL['lmPwdHistory']] is not None: encryptedLMHistory = self.CRYPTED_HISTORY( unhexlify( record[self.NAME_TO_INTERNAL['lmPwdHistory']])) tmpLMHistory = self.__removeRC4Layer(encryptedLMHistory) for i in range(0, len(tmpLMHistory) / 16): LMHash = self.__removeDESLayer( tmpLMHistory[i * 16:(i + 1) * 16], rid) LMHistory.append(LMHash) if record[self.NAME_TO_INTERNAL['ntPwdHistory']] is not None: encryptedNTHistory = self.CRYPTED_HISTORY( unhexlify( record[self.NAME_TO_INTERNAL['ntPwdHistory']])) tmpNTHistory = self.__removeRC4Layer(encryptedNTHistory) for i in range(0, len(tmpNTHistory) / 16): NTHash = self.__removeDESLayer( tmpNTHistory[i * 16:(i + 1) * 16], rid) NTHistory.append(NTHash) for i, (LMHash, NTHash) in enumerate( map(lambda l, n: (l, n) if l else ('', n), LMHistory[1:], NTHistory[1:])): if self.__noLMHash: lmhash = hexlify(ntlm.LMOWFv1('', '')) else: lmhash = hexlify(LMHash) answer = "%s_history%d:%s:%s:%s:::" % ( userName, i, rid, lmhash, hexlify(NTHash)) if outputFile is not None: self.__writeOutput(outputFile, answer + '\n') self.__logger.highlight(answer) else: logging.debug('Decrypting hash for user: %s' % record['pmsgOut']['V6']['pNC']['StringName'][:-1]) domain = None if self.__history: LMHistory = [] NTHistory = [] for attr in record['pmsgOut']['V6']['pObjects']['Entinf'][ 'AttrBlock']['pAttr']: try: attId = drsuapi.OidFromAttid(prefixTable, attr['attrTyp']) LOOKUP_TABLE = self.ATTRTYP_TO_ATTID except Exception, e: logging.debug( 'Failed to execute OidFromAttid with error %s, fallbacking to fixed table' % e) # Fallbacking to fixed table and hope for the best attId = attr['attrTyp'] LOOKUP_TABLE = self.NAME_TO_ATTRTYP if attId == LOOKUP_TABLE['dBCSPwd']: if attr['AttrVal']['valCount'] > 0: encrypteddBCSPwd = ''.join( attr['AttrVal']['pAVal'][0]['pVal']) encryptedLMHash = drsuapi.DecryptAttributeValue( self.__remoteOps.getDrsr(), encrypteddBCSPwd) LMHash = drsuapi.removeDESLayer(encryptedLMHash, rid) else: LMHash = ntlm.LMOWFv1('', '') elif attId == LOOKUP_TABLE['unicodePwd']: if attr['AttrVal']['valCount'] > 0: encryptedUnicodePwd = ''.join( attr['AttrVal']['pAVal'][0]['pVal']) encryptedNTHash = drsuapi.DecryptAttributeValue( self.__remoteOps.getDrsr(), encryptedUnicodePwd) NTHash = drsuapi.removeDESLayer(encryptedNTHash, rid) else: NTHash = ntlm.NTOWFv1('', '') elif attId == LOOKUP_TABLE['userPrincipalName']: if attr['AttrVal']['valCount'] > 0: try: domain = ''.join( attr['AttrVal']['pAVal'][0]['pVal']).decode( 'utf-16le').split('@')[-1] except: domain = None else: domain = None elif attId == LOOKUP_TABLE['sAMAccountName']: if attr['AttrVal']['valCount'] > 0: try: userName = ''.join(attr['AttrVal']['pAVal'][0] ['pVal']).decode('utf-16le') except: logging.error('Cannot get sAMAccountName for %s' % record['pmsgOut']['V6']['pNC'] ['StringName'][:-1]) userName = '******' else: logging.error( 'Cannot get sAMAccountName for %s' % record['pmsgOut']['V6']['pNC']['StringName'][:-1]) userName = '******' elif attId == LOOKUP_TABLE['objectSid']: if attr['AttrVal']['valCount'] > 0: objectSid = ''.join( attr['AttrVal']['pAVal'][0]['pVal']) else: logging.error( 'Cannot get objectSid for %s' % record['pmsgOut']['V6']['pNC']['StringName'][:-1]) objectSid = rid elif attId == LOOKUP_TABLE['pwdLastSet']: if attr['AttrVal']['valCount'] > 0: try: pwdLastSet = self.__fileTimeToDateTime( unpack( '<Q', ''.join(attr['AttrVal']['pAVal'][0] ['pVal']))[0]) except: traceback.print_exc() logging.error('Cannot get pwdLastSet for %s' % record['pmsgOut']['V6']['pNC'] ['StringName'][:-1]) pwdLastSet = 'N/A' if self.__history: if attId == LOOKUP_TABLE['lmPwdHistory']: if attr['AttrVal']['valCount'] > 0: encryptedLMHistory = ''.join( attr['AttrVal']['pAVal'][0]['pVal']) tmpLMHistory = drsuapi.DecryptAttributeValue( self.__remoteOps.getDrsr(), encryptedLMHistory) for i in range(0, len(tmpLMHistory) / 16): LMHashHistory = drsuapi.removeDESLayer( tmpLMHistory[i * 16:(i + 1) * 16], rid) LMHistory.append(LMHashHistory) else: logging.debug('No lmPwdHistory for user %s' % record['pmsgOut']['V6']['pNC'] ['StringName'][:-1]) elif attId == LOOKUP_TABLE['ntPwdHistory']: if attr['AttrVal']['valCount'] > 0: encryptedNTHistory = ''.join( attr['AttrVal']['pAVal'][0]['pVal']) tmpNTHistory = drsuapi.DecryptAttributeValue( self.__remoteOps.getDrsr(), encryptedNTHistory) for i in range(0, len(tmpNTHistory) / 16): NTHashHistory = drsuapi.removeDESLayer( tmpNTHistory[i * 16:(i + 1) * 16], rid) NTHistory.append(NTHashHistory) else: logging.debug('No ntPwdHistory for user %s' % record['pmsgOut']['V6']['pNC'] ['StringName'][:-1]) if domain is not None: userName = '******' % (domain, userName) answer = "%s:%s:%s:%s:::" % (userName, rid, hexlify(LMHash), hexlify(NTHash)) if outputFile is not None: self.__writeOutput(outputFile, answer + '\n') if self.__pwdLastSet is True: answer = "%s (pwdLastSet=%s)" % (answer, pwdLastSet) self.__logger.highlight(answer) if self.__history: for i, (LMHashHistory, NTHashHistory) in enumerate( map(lambda l, n: (l, n) if l else ('', n), LMHistory[1:], NTHistory[1:])): if self.__noLMHash: lmhash = hexlify(ntlm.LMOWFv1('', '')) else: lmhash = hexlify(LMHashHistory) answer = "%s_history%d:%s:%s:%s:::" % ( userName, i, rid, lmhash, hexlify(NTHashHistory)) self.__logger.highlight(answer) if outputFile is not None: self.__writeOutput(outputFile, answer + '\n')
def __printSecret(self, name, secretItem): # Based on [MS-LSAD] section 3.1.1.4 # First off, let's discard NULL secrets. if len(secretItem) == 0: logging.debug('Discarding secret %s, NULL Data' % name) return # We might have secrets with zero if secretItem.startswith('\x00\x00'): logging.debug('Discarding secret %s, all zeros' % name) return upperName = name.upper() logging.info('%s ' % name) secret = '' if upperName.startswith('_SC_'): # Service name, a password might be there # Let's first try to decode the secret try: strDecoded = secretItem.decode('utf-16le') except: pass else: # We have to get the account the service # runs under if self.__isRemote is True: account = self.__remoteOps.getServiceAccount(name[4:]) if account is None: secret = '(Unknown User):' else: secret = "%s:" % account else: # We don't support getting this info for local targets at the moment secret = '(Unknown User):' secret += strDecoded elif upperName.startswith('DEFAULTPASSWORD'): # defaults password for winlogon # Let's first try to decode the secret try: strDecoded = secretItem.decode('utf-16le') except: pass else: # We have to get the account this password is for if self.__isRemote is True: account = self.__remoteOps.getDefaultLoginAccount() if account is None: secret = '(Unknown User):' else: secret = "%s:" % account else: # We don't support getting this info for local targets at the moment secret = '(Unknown User):' secret += strDecoded elif upperName.startswith('ASPNET_WP_PASSWORD'): try: strDecoded = secretItem.decode('utf-16le') except: pass else: secret = 'ASPNET: %s' % strDecoded elif upperName.startswith('$MACHINE.ACC'): # compute MD4 of the secret.. yes.. that is the nthash? :-o md4 = MD4.new() md4.update(secretItem) if self.__isRemote is True: machine, domain = self.__remoteOps.getMachineNameAndDomain() secret = "%s\\%s$:%s:%s:::" % (domain, machine, hexlify(ntlm.LMOWFv1('','')), hexlify(md4.digest())) else: secret = "$MACHINE.ACC: %s:%s" % (hexlify(ntlm.LMOWFv1('','')), hexlify(md4.digest())) if secret != '': self.__secretItems.append(secret) self.__logger.highlight(secret) else: # Default print, hexdump self.__secretItems.append('%s:%s' % (name, hexlify(secretItem))) self.__logger.highlight('{}:{}'.format(name, hexlify(secretItem)))
def dump(self): NTPASSWORD = "******" LMPASSWORD = "******" sam_hashes = [] if self.__samFile is None: # No SAM file provided return self.__logger.success( 'Dumping local SAM hashes (uid:rid:lmhash:nthash)') self.getHBootKey() usersKey = 'SAM\\Domains\\Account\\Users' # Enumerate all the RIDs rids = self.enumKey(usersKey) # Remove the Names item try: rids.remove('Names') except: pass for rid in rids: userAccount = USER_ACCOUNT_V( self.getValue(ntpath.join(usersKey, rid, 'V'))[1]) rid = int(rid, 16) V = userAccount['Data'] userName = V[userAccount['NameOffset']:userAccount['NameOffset'] + userAccount['NameLength']].decode('utf-16le') if userAccount['LMHashLength'] == 20: encLMHash = V[userAccount['LMHashOffset'] + 4:userAccount['LMHashOffset'] + userAccount['LMHashLength']] else: encLMHash = '' if userAccount['NTHashLength'] == 20: encNTHash = V[userAccount['NTHashOffset'] + 4:userAccount['NTHashOffset'] + userAccount['NTHashLength']] else: encNTHash = '' lmHash = self.__decryptHash(rid, encLMHash, LMPASSWORD) ntHash = self.__decryptHash(rid, encNTHash, NTPASSWORD) if lmHash == '': lmHash = ntlm.LMOWFv1('', '') if ntHash == '': ntHash = ntlm.NTOWFv1('', '') answer = "%s:%d:%s:%s:::" % (userName, rid, hexlify(lmHash), hexlify(ntHash)) self.__itemsFound[rid] = answer self.__logger.highlight(answer) sam_hashes.append(answer) self.__db.add_credential( 'hash', self.__hostname, userName, '{}:{}'.format(hexlify(lmHash), hexlify(ntHash))) return sam_hashes
clientChallenge = "\xaa" * 8 serverChallenge = "\x01\x23\x45\x67\x89\xab\xcd\xef" flags = ntlm.NTLMSSP_KEY_EXCHANGE | ntlm.NTLMSSP_KEY_56 | ntlm.NTLMSSP_KEY_128 | ntlm.NTLMSSP_VERSION | ntlm.NTLMSSP_TARGET_TYPE_SERVER | ntlm.NTLMSSP_ALWAYS_SIGN | ntlm.NTLMSSP_NTLM_KEY | ntlm.NTLMSSP_SEAL | ntlm.NTLMSSP_SIGN | ntlm.NTLMSSP_OEM | ntlm.NTLMSSP_UNICODE seqNum = 0 nonce = '\x00' * 4 plaintext = 'Plaintext'.encode('utf-16le') print "## BEFORE RUNNING THESE TESTS" print "Don't forget to set up aTime = '\\x00'*8 in computeResponseNTLMv2 otherwise the results won't be right. " print "Look for that in ntlm.py and uncomment the lines, comment the other ones and don't forget to revert everything back whenever finished testing" print "Flags" hexdump(struct.pack('<L', flags)) print "####### 4.2.2 NTLMv1 Authentication" ntlm.USE_NTLMv2 = False print "4.2.2.1 LMOWFv1()" hexdump(ntlm.LMOWFv1(password)) print "\n" print "4.2.2.1.2 NTOWFv1()" hexdump(ntlm.NTOWFv1(password)) print "\n" print "4.2.2.1.3 Session Base Key and Key Exchange Key" ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv1( long(flags), serverChallenge, clientChallenge, serverName, domain, user, password, '', '') hexdump(sessionBaseKey) print "\n" print "4.2.2.2.1 NTLMv1 Response" hexdump(ntResponse) print "\n" print "4.2.2.2.2 LMv1 Response" hexdump(lmResponse)
def __printSecret(self, name, secretItem): # Based on [MS-LSAD] section 3.1.1.4 # First off, let's discard NULL secrets. if len(secretItem) == 0: # logging.debug('Discarding secret %s, NULL Data' % name) return # We might have secrets with zero if secretItem.startswith('\x00\x00'): # logging.debug('Discarding secret %s, all zeros' % name) return upperName = name.upper() values = {} values['Category'] = name user = '' password = '' # Service passwords if upperName.startswith('_SC_'): values['Category'] = 'Windows Service' values['Service Name'] = name try: strDecoded = secretItem.decode('utf-16le') except: pass else: # Account the service runs under user = FindUSer().find_userName(strDecoded) if not user: user = '******' password = strDecoded # defaults password for winlogon elif upperName.startswith('DEFAULTPASSWORD'): values['Category'] = 'Windows Autologon' # Let's first try to decode the secret try: strDecoded = secretItem.decode('utf-16le') except: pass else: user = FindUSer().find_userName(strDecoded) if not user: user = '******' password = strDecoded elif upperName.startswith('ASPNET_WP_PASSWORD'): try: strDecoded = secretItem.decode('utf-16le') except: pass else: user = '******' password = strDecoded # compute MD4 of the secret.. yes.. that is the nthash? :-o elif upperName.startswith('$MACHINE.ACC'): md4 = MD4.new() md4.update(secretItem) user = '******' % ntlm.LMOWFv1('','').encode('hex') password = md4.digest().encode('hex') if user: values['user'] = user values['password'] = password else: # Default print, hexdump values['hex'] = secretItem.encode('hex') # hexdump(secretItem) self.__secretItems.append(values)