Files
volatility3/volatility/plugins/windows/registry/certificates.py
T
Mike Auty f872aa3390 Revert "Add in no-dump option to certificates plugin."
Arg, too much mind changing.  This option would make sense if the
certificates plugin returned much useful information, but parsing
certificates isn't easy in with just stdlib, and therefore dumping the
certificates is the most sensible thing for this plugin to do (meaning
no need for a no-dump option).

This reverts commit 5491825652.
2019-09-17 16:59:50 +01:00

69 lines
3.6 KiB
Python

import struct
from typing import List, Iterator, Tuple
from volatility.framework import interfaces, renderers
from volatility.framework.configuration import requirements
from volatility.framework.symbols.windows.extensions.registry import RegValueTypes
from volatility.plugins.windows.registry import hivelist, printkey
class Certificates(interfaces.plugins.PluginInterface):
"""Lists the certificates in the registry's Certificate Store."""
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', 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.PluginRequirement(name = 'printkey', plugin = printkey.PrintKey, version = (1, 0, 0))
]
def parse_data(self, data: bytes):
name = renderers.NotAvailableValue()
certificate_data = renderers.NotAvailableValue()
while len(data) > 12:
ctype, clength = struct.unpack("<QI", data[0:12])
cvalue, data = data[12:12 + clength], data[12 + clength:]
if ctype == 0x10000000b:
name = str(cvalue, 'utf-16').strip("\x00")
elif ctype == 0x100000020:
certificate_data = cvalue
return (name, certificate_data)
def _generator(self) -> Iterator[Tuple[int, Tuple[int, str]]]:
for hive in hivelist.HiveList.list_hives(
self.context,
base_config_path = self.config_path,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols']):
for top_key in ["Microsoft\\SystemCertificates",
"Software\\Microsoft\\SystemCertificates",
]:
try:
# Walk it
node_path = hive.get_key(top_key, return_list = True)
for (depth, is_key, last_write_time, key_path, volatility, node) in printkey.PrintKey.key_iterator(
hive, node_path, recurse = True):
if not is_key and RegValueTypes.get(node.Type).name == "REG_BINARY":
name, certificate_data = self.parse_data(node.decode_data())
unique_key_offset = key_path.index(top_key) + len(top_key) + 1
reg_section = key_path[unique_key_offset:key_path.index("\\", unique_key_offset)]
key_hash = key_path[key_path.rindex("\\") + 1:]
if not isinstance(certificate_data, interfaces.renderers.BaseAbsentValue):
filedata = interfaces.plugins.FileInterface(
"{} - {} - {}.crt".format(hex(hive.hive_offset), reg_section, key_hash))
filedata.data.write(certificate_data)
self.produce_file(filedata)
yield (0, (top_key, reg_section, key_hash, name))
except KeyError:
# Key wasn't found in this hive, carry on
pass
def run(self) -> renderers.TreeGrid:
return renderers.TreeGrid([("Certificate path", str), ("Certificate section", str), ("Certificate ID", str),
("Certificate name", str)], self._generator())