From f873ced04e6e7bdd0d91ad4147382fdb589b7aa7 Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sun, 16 May 2021 17:01:52 +0100 Subject: [PATCH] Windows: Improve hashdumping plugin errors --- .../framework/plugins/windows/cachedump.py | 35 +++++++++----- .../framework/plugins/windows/hashdump.py | 27 ++++++++--- .../framework/plugins/windows/lsadump.py | 48 ++++++++++--------- 3 files changed, 68 insertions(+), 42 deletions(-) diff --git a/volatility3/framework/plugins/windows/cachedump.py b/volatility3/framework/plugins/windows/cachedump.py index dc8246ef8..8436b46f6 100644 --- a/volatility3/framework/plugins/windows/cachedump.py +++ b/volatility3/framework/plugins/windows/cachedump.py @@ -1,20 +1,22 @@ # This file is Copyright 2020 Volatility Foundation and licensed under the Volatility Software License 1.0 # which is available at https://www.volatilityfoundation.org/license/vsl-v1.0 # - +import logging from struct import unpack from typing import Tuple from Crypto.Cipher import ARC4, AES from Crypto.Hash import HMAC -from volatility3.framework import interfaces, renderers, exceptions +from volatility3.framework import interfaces, renderers from volatility3.framework.configuration import requirements from volatility3.framework.layers import registry from volatility3.framework.symbols.windows import versions from volatility3.plugins.windows import hashdump, lsadump from volatility3.plugins.windows.registry import hivelist +vollog = logging.getLogger(__name__) + class Cachedump(interfaces.plugins.PluginInterface): """Dumps lsa secrets from memory""" @@ -30,7 +32,8 @@ class Cachedump(interfaces.plugins.PluginInterface): architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"), requirements.PluginRequirement(name = 'hivelist', plugin = hivelist.HiveList, version = (1, 0, 0)), - requirements.PluginRequirement(name = 'lsadump', plugin = lsadump.Lsadump, version = (1, 0, 0)) + requirements.PluginRequirement(name = 'lsadump', plugin = lsadump.Lsadump, version = (1, 0, 0)), + requirements.PluginRequirement(name = 'hashdump', plugin = hashdump.Hashdump, version = (1, 1, 0)) ] @staticmethod @@ -60,7 +63,7 @@ class Cachedump(interfaces.plugins.PluginInterface): (uname_len, domain_len) = unpack(" List[interfaces.objects.ObjectInterface]: user_key_path = "SAM\\Domains\\Account\\Users" - user_key = samhive.get_key(user_key_path) + user_key = cls.get_hive_key(samhive, user_key_path) + if not user_key: return [] return [k for k in user_key.get_subkeys() if k.Name != "Names"] @@ -75,7 +87,7 @@ class Hashdump(interfaces.plugins.PluginInterface): lsa_base = "ControlSet{0:03}".format(cs) + "\\Control\\Lsa" lsa_keys = ["JD", "Skew1", "GBG", "Data"] - lsa = syshive.get_key(lsa_base) + lsa = cls.get_hive_key(syshive, lsa_base) if not lsa: return None @@ -83,9 +95,10 @@ class Hashdump(interfaces.plugins.PluginInterface): bootkey = '' for lk in lsa_keys: - key = syshive.get_key(lsa_base + '\\' + lk) - - class_data = syshive.read(key.Class + 4, key.ClassLength) + key = cls.get_hive_key(syshive, lsa_base + '\\' + lk) + class_data = None + if key: + class_data = syshive.read(key.Class + 4, key.ClassLength) if class_data is None: return None @@ -102,7 +115,7 @@ class Hashdump(interfaces.plugins.PluginInterface): if not bootkey: return None - sam_account_key = samhive.get_key(sam_account_path) + sam_account_key = cls.get_hive_key(samhive, sam_account_path) if not sam_account_key: return None @@ -270,7 +283,7 @@ class Hashdump(interfaces.plugins.PluginInterface): rid = int(str(user.get_name()), 16) yield (0, (name, rid, lmout, ntout)) else: - raise ValueError("Hbootkey is not valid") + vollog.warning("Hbootkey is not valid") def run(self): offset = self.config.get('offset', None) diff --git a/volatility3/framework/plugins/windows/lsadump.py b/volatility3/framework/plugins/windows/lsadump.py index a9ee1737b..c3d765f83 100644 --- a/volatility3/framework/plugins/windows/lsadump.py +++ b/volatility3/framework/plugins/windows/lsadump.py @@ -31,7 +31,8 @@ class Lsadump(interfaces.plugins.PluginInterface): description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"), - requirements.PluginRequirement(name = 'hivelist', plugin = hivelist.HiveList, version = (1, 0, 0)) + requirements.VersionRequirement(name = 'hashdump', component = hashdump.Hashdump, version = (1, 1, 0)), + requirements.VersionRequirement(name = 'hivelist', component = hivelist.HiveList, version = (1, 0, 0)) ] @classmethod @@ -65,7 +66,7 @@ class Lsadump(interfaces.plugins.PluginInterface): else: policy_key = 'PolSecretEncryptionKey' - enc_reg_key = sechive.get_key("Policy\\" + policy_key) + 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()) @@ -94,23 +95,21 @@ class Lsadump(interfaces.plugins.PluginInterface): @classmethod def get_secret_by_name(cls, sechive: registry.RegistryHive, name: str, lsakey: bytes, is_vista_or_later: bool): - try: - enc_secret_key = sechive.get_key("Policy\\Secrets\\" + name + "\\CurrVal") - except KeyError: - raise ValueError("Unable to read cache from memory") + enc_secret_key = hashdump.Hashdump.get_hive_key(sechive, "Policy\\Secrets\\" + name + "\\CurrVal") - enc_secret_value = next(enc_secret_key.get_values()) - if not enc_secret_value: - return None + secret = None + if enc_secret_key: + enc_secret_value = next(enc_secret_key.get_values()) + if enc_secret_value: - enc_secret = sechive.read(enc_secret_value.Data + 4, enc_secret_value.DataLength) - if not enc_secret: - return None + enc_secret = sechive.read(enc_secret_value.Data + 4, enc_secret_value.DataLength) + if enc_secret: + + if not is_vista_or_later: + secret = cls.decrypt_secret(enc_secret[0xC:], lsakey) + else: + secret = cls.decrypt_aes(enc_secret, lsakey) - if not is_vista_or_later: - secret = cls.decrypt_secret(enc_secret[0xC:], lsakey) - else: - secret = cls.decrypt_aes(enc_secret, lsakey) return secret @classmethod @@ -133,7 +132,7 @@ class Lsadump(interfaces.plugins.PluginInterface): if len(key[j:j + 7]) < 7: j = len(key[j:j + 7]) - (dec_data_len, ) = unpack("