diff --git a/examples/dpapi.py b/examples/dpapi.py index bd0f102cc5..807ea54fe0 100755 --- a/examples/dpapi.py +++ b/examples/dpapi.py @@ -75,8 +75,8 @@ def getDPAPI_SYSTEM(self,secretType, secret): machineKey, userKey = secret.split('\n') machineKey = machineKey.split(':')[1] userKey = userKey.split(':')[1] - self.dpapiSystem['MachineKey'] = unhexlify(machineKey[2:]) - self.dpapiSystem['UserKey'] = unhexlify(userKey[2:]) + self.dpapiSystem['MachineKey'] = unhexlify(machineKey.removeprefix("0x")) + self.dpapiSystem['UserKey'] = unhexlify(userKey.removeprefix("0x")) def getLSA(self): localOperations = LocalOperations(self.options.system) @@ -164,7 +164,7 @@ def run(self): print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return elif self.options.key and self.options.sid: - key = unhexlify(self.options.key[2:]) + key = unhexlify(self.options.key.removeprefix("0x")) key1, key2 = deriveKeysFromUserkey(self.options.sid, key) decryptedKey = mk.decrypt(key1) if decryptedKey: @@ -177,7 +177,7 @@ def run(self): print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return elif self.options.key: - key = unhexlify(self.options.key[2:]) + key = unhexlify(self.options.key.removeprefix("0x")) decryptedKey = mk.decrypt(key) if decryptedKey: print('Decrypted key with key provided') @@ -393,7 +393,7 @@ def run(self): blob = DPAPI_BLOB(cred['Data']) if self.options.key is not None: - key = unhexlify(self.options.key[2:]) + key = unhexlify(self.options.key.removeprefix("0x")) decrypted = blob.decrypt(key) if decrypted is not None: creds = CREDENTIAL_BLOB(decrypted) @@ -413,7 +413,7 @@ def run(self): blob = VAULT_VCRD(data) if self.options.key is not None: - key = unhexlify(self.options.key[2:]) + key = unhexlify(self.options.key.removeprefix("0x")) cleartext = None for i, entry in enumerate(blob.attributesLen): @@ -445,7 +445,7 @@ def run(self): vpol.dump() if self.options.key is not None: - key = unhexlify(self.options.key[2:]) + key = unhexlify(self.options.key.removeprefix("0x")) blob = vpol['Blob'] data = blob.decrypt(key) if data is not None: @@ -458,7 +458,7 @@ def run(self): blob = DPAPI_BLOB(data) if self.options.key is not None: - key = unhexlify(self.options.key[2:]) + key = unhexlify(self.options.key.removeprefix("0x")) if self.options.entropy_file is not None: fp2 = open(self.options.entropy_file, 'rb') entropy = fp2.read() @@ -471,7 +471,11 @@ def run(self): decrypted = blob.decrypt(key, entropy) if decrypted is not None: print('Successfully decrypted data') - hexdump(decrypted) + if self.options.outfile is not None: + with open(self.options.outfile, 'wb') as f: + f.write(decrypted) + else: + hexdump(decrypted) return else: # Just print the data @@ -488,7 +492,7 @@ def run(self): # Handle key options if self.options.key: - key = unhexlify(self.options.key[2:]) + key = unhexlify(self.options.key.removeprefix("0x")) keys = deriveKeysFromUserkey(chf.credhist_entries_list[0].sid, key) # Only other option is using a password @@ -602,6 +606,7 @@ def run(self): unprotect.add_argument('-key', action='store', required=False, help='Key used for decryption') unprotect.add_argument('-entropy', action='store', default=None, required=False, help='String with extra entropy needed for decryption') unprotect.add_argument('-entropy-file', action='store', default=None, required=False, help='File with binary entropy contents (overwrites -entropy)') + unprotect.add_argument('-outfile', action='store', default=None, required=False, help='File to write decrypted data to (if not specified, it will be printed as hexdump)') # A CREDHIST command credhist = subparsers.add_parser('credhist', help='CREDHIST related functions') diff --git a/impacket/dpapi.py b/impacket/dpapi.py index 9a1f68c5ad..edd44b2f7d 100644 --- a/impacket/dpapi.py +++ b/impacket/dpapi.py @@ -634,7 +634,12 @@ def fixparity(deskey): return derivedKey def decrypt(self, key, entropy = None): - keyHash = SHA1.new(key).digest() + if len(key) == 20: + # Key has already been hashed + keyHash = key + else: + keyHash = SHA1.new(key).digest() + sessionKey = HMAC.new(keyHash, self['Salt'], ALGORITHMS_DATA[self['HashAlgo']][1]) if entropy is not None: sessionKey.update(entropy)