diff --git a/volatility3/framework/plugins/windows/cachedump.py b/volatility3/framework/plugins/windows/cachedump.py index ef4096b42..7bc35945a 100644 --- a/volatility3/framework/plugins/windows/cachedump.py +++ b/volatility3/framework/plugins/windows/cachedump.py @@ -22,7 +22,7 @@ class Cachedump(interfaces.plugins.PluginInterface): """Dumps lsa secrets from memory""" _required_framework_version = (2, 0, 0) - _version = (1, 0, 1) + _version = (1, 0, 2) @classmethod def get_requirements(cls): diff --git a/volatility3/framework/plugins/windows/hashdump.py b/volatility3/framework/plugins/windows/hashdump.py index fa4081366..3346807d6 100644 --- a/volatility3/framework/plugins/windows/hashdump.py +++ b/volatility3/framework/plugins/windows/hashdump.py @@ -9,7 +9,7 @@ from typing import List, Optional, Tuple from Crypto.Cipher import AES, ARC4, DES -from volatility3.framework import interfaces, renderers +from volatility3.framework import interfaces, renderers, exceptions from volatility3.framework.configuration import requirements from volatility3.framework.symbols.windows.extensions import registry from volatility3.plugins.windows.registry import hivelist @@ -21,7 +21,7 @@ class Hashdump(interfaces.plugins.PluginInterface): """Dumps user hashes from memory""" _required_framework_version = (2, 0, 0) - _version = (1, 1, 0) + _version = (1, 1, 1) @classmethod def get_requirements(cls): @@ -326,7 +326,9 @@ class Hashdump(interfaces.plugins.PluginInterface): empty_nt = b"\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31\xb7\x3c\x59\xd7\xe0\xc0\x89\xc0" @classmethod - def get_hive_key(cls, hive: registry.RegistryHive, key: str): + def get_hive_key( + cls, hive: registry.RegistryHive, key: str + ) -> Optional["registry.CM_KEY_NODE"]: result = None try: if hive: @@ -351,6 +353,9 @@ class Hashdump(interfaces.plugins.PluginInterface): @classmethod def get_bootkey(cls, syshive: registry.RegistryHive) -> Optional[bytes]: + """ + Returns the scrambled bootkey necesary to decrypt hashes + """ cs = 1 lsa_base = f"ControlSet{cs:03}" + "\\Control\\Lsa" lsa_keys = ["JD", "Skew1", "GBG", "Data"] @@ -366,7 +371,10 @@ class Hashdump(interfaces.plugins.PluginInterface): key = cls.get_hive_key(syshive, lsa_base + "\\" + lk) class_data = None if key: - class_data = syshive.read(key.Class + 4, key.ClassLength) + try: + class_data = syshive.read(key.Class + 4, key.ClassLength) + except exceptions.InvalidAddressException: + return None if class_data is None: return None @@ -394,7 +402,11 @@ class Hashdump(interfaces.plugins.PluginInterface): sam_data = None for v in sam_account_key.get_values(): if v.get_name() == "F": - sam_data = samhive.read(v.Data + 4, v.DataLength) + try: + sam_data = samhive.read(v.Data + 4, v.DataLength) + except exceptions.InvalidAddressException: + return None + if not sam_data: return None @@ -444,7 +456,11 @@ class Hashdump(interfaces.plugins.PluginInterface): sam_data = None for v in user.get_values(): if v.get_name() == "V": - sam_data = samhive.read(v.Data + 4, v.DataLength) + try: + sam_data = samhive.read(v.Data + 4, v.DataLength) + except exceptions.InvalidAddressException: + return None + if not sam_data: return None @@ -546,7 +562,11 @@ class Hashdump(interfaces.plugins.PluginInterface): value = None for v in user.get_values(): if v.get_name() == "V": - value = samhive.read(v.Data + 4, v.DataLength) + try: + value = samhive.read(v.Data + 4, v.DataLength) + except exceptions.InvalidAddressException: + return None + if not value: return None diff --git a/volatility3/framework/plugins/windows/lsadump.py b/volatility3/framework/plugins/windows/lsadump.py index ac2b678f6..041a653f4 100644 --- a/volatility3/framework/plugins/windows/lsadump.py +++ b/volatility3/framework/plugins/windows/lsadump.py @@ -22,7 +22,7 @@ class Lsadump(interfaces.plugins.PluginInterface): """Dumps lsa secrets from memory""" _required_framework_version = (2, 0, 0) - _version = (1, 0, 0) + _version = (1, 0, 1) @classmethod def get_requirements(cls): @@ -76,8 +76,7 @@ class Lsadump(interfaces.plugins.PluginInterface): enc_reg_key = hashdump.Hashdump.get_hive_key(sechive, "Policy\\" + policy_key) if not enc_reg_key: return None - enc_reg_value = next(enc_reg_key.get_values()) - + enc_reg_value = next(enc_reg_key.get_values(), None) if not enc_reg_value: return None @@ -112,18 +111,22 @@ class Lsadump(interfaces.plugins.PluginInterface): name: str, lsakey: bytes, is_vista_or_later: bool, - ): + ) -> Optional[bytes]: enc_secret_key = hashdump.Hashdump.get_hive_key( sechive, "Policy\\Secrets\\" + name + "\\CurrVal" ) secret = None if enc_secret_key: - enc_secret_value = next(enc_secret_key.get_values()) + enc_secret_value = next(enc_secret_key.get_values(), None) if enc_secret_value: - enc_secret = sechive.read( - enc_secret_value.Data + 4, enc_secret_value.DataLength - ) + try: + enc_secret = sechive.read( + enc_secret_value.Data + 4, enc_secret_value.DataLength + ) + except exceptions.InvalidAddressExceptions: + return None + if enc_secret: if not is_vista_or_later: secret = cls.decrypt_secret(enc_secret[0xC:], lsakey) @@ -133,7 +136,7 @@ class Lsadump(interfaces.plugins.PluginInterface): return secret @classmethod - def decrypt_secret(cls, secret: bytes, key: bytes): + def decrypt_secret(cls, secret: bytes, key: bytes) -> bytes: """Python implementation of SystemFunction005. Decrypts a block of data with DES using given key. @@ -168,11 +171,11 @@ class Lsadump(interfaces.plugins.PluginInterface): ) bootkey = hashdump.Hashdump.get_bootkey(syshive) - lsakey = self.get_lsa_key(sechive, bootkey, vista_or_later) if not bootkey: vollog.warning("Unable to find bootkey") return None + lsakey = self.get_lsa_key(sechive, bootkey, vista_or_later) if not lsakey: vollog.warning("Unable to find lsa key") return None @@ -190,15 +193,17 @@ class Lsadump(interfaces.plugins.PluginInterface): if not sec_val_key: continue - enc_secret_value = next(sec_val_key.get_values()) + enc_secret_value = next(sec_val_key.get_values(), None) if not enc_secret_value: continue - enc_secret = sechive.read( - enc_secret_value.Data + 4, enc_secret_value.DataLength - ) - if not enc_secret: + try: + enc_secret = sechive.read( + enc_secret_value.Data + 4, enc_secret_value.DataLength + ) + except exceptions.InvalidAddressExceptions: continue + if not vista_or_later: secret = self.decrypt_secret(enc_secret[0xC:], lsakey) else: