Yapf-0.28.0 rerun across the whole codebase.

This commit is contained in:
Mike Auty
2019-09-21 21:08:23 +01:00
parent dad88692b8
commit 72567e1c50
91 changed files with 1208 additions and 1124 deletions
+55 -63
View File
@@ -205,74 +205,66 @@ class VolatilityTester:
if __name__ == '__main__':
plugins = [
VolatilityPlugin(
name = "pslist", vol2_plugin_parameters = ["pslist"], vol3_plugin_parameters = ["windows.pslist"]),
VolatilityPlugin(
name = "psscan",
vol2_plugin_parameters = ["psscan"],
vol3_plugin_parameters = ["windows.psscan"],
rekall_plugin_parameters = ["psscan", "--scan_kernel"]),
VolatilityPlugin(
name = "driverscan",
vol2_plugin_parameters = ["driverscan"],
vol3_plugin_parameters = ["windows.driverscan"],
rekall_plugin_parameters = ["driverscan", "--scan_kernel"]),
VolatilityPlugin(
name = "handles", vol2_plugin_parameters = ["handles"], vol3_plugin_parameters = ["windows.handles"]),
VolatilityPlugin(
name = "modules", vol2_plugin_parameters = ["modules"], vol3_plugin_parameters = ["windows.modules"]),
VolatilityPlugin(
name = "hivelist",
vol2_plugin_parameters = ["hivelist"],
vol3_plugin_parameters = ["registry.hivelist"],
rekall_plugin_parameters = ["hives"]),
VolatilityPlugin(
name = "vadinfo",
vol2_plugin_parameters = ["vadinfo"],
vol3_plugin_parameters = ["windows.vadinfo"],
rekall_plugin_parameters = ["vad"]),
VolatilityPlugin(
name = "modscan",
vol2_plugin_parameters = ["modscan"],
vol3_plugin_parameters = ["windows.modscan"],
rekall_plugin_parameters = ["modscan", "--scan_kernel"]),
VolatilityPlugin(
name = "svcscan",
vol2_plugin_parameters = ["svcscan"],
vol3_plugin_parameters = ["windows.svcscan"],
rekall_plugin_parameters = ["svcscan"]),
VolatilityPlugin(name = "pslist",
vol2_plugin_parameters = ["pslist"],
vol3_plugin_parameters = ["windows.pslist"]),
VolatilityPlugin(name = "psscan",
vol2_plugin_parameters = ["psscan"],
vol3_plugin_parameters = ["windows.psscan"],
rekall_plugin_parameters = ["psscan", "--scan_kernel"]),
VolatilityPlugin(name = "driverscan",
vol2_plugin_parameters = ["driverscan"],
vol3_plugin_parameters = ["windows.driverscan"],
rekall_plugin_parameters = ["driverscan", "--scan_kernel"]),
VolatilityPlugin(name = "handles",
vol2_plugin_parameters = ["handles"],
vol3_plugin_parameters = ["windows.handles"]),
VolatilityPlugin(name = "modules",
vol2_plugin_parameters = ["modules"],
vol3_plugin_parameters = ["windows.modules"]),
VolatilityPlugin(name = "hivelist",
vol2_plugin_parameters = ["hivelist"],
vol3_plugin_parameters = ["registry.hivelist"],
rekall_plugin_parameters = ["hives"]),
VolatilityPlugin(name = "vadinfo",
vol2_plugin_parameters = ["vadinfo"],
vol3_plugin_parameters = ["windows.vadinfo"],
rekall_plugin_parameters = ["vad"]),
VolatilityPlugin(name = "modscan",
vol2_plugin_parameters = ["modscan"],
vol3_plugin_parameters = ["windows.modscan"],
rekall_plugin_parameters = ["modscan", "--scan_kernel"]),
VolatilityPlugin(name = "svcscan",
vol2_plugin_parameters = ["svcscan"],
vol3_plugin_parameters = ["windows.svcscan"],
rekall_plugin_parameters = ["svcscan"]),
VolatilityPlugin(name = "ssdt", vol2_plugin_parameters = ["ssdt"], vol3_plugin_parameters = ["windows.ssdt"]),
VolatilityPlugin(
name = "printkey",
vol2_plugin_parameters = ["printkey", "-K", "Classes"],
vol3_plugin_parameters = ["registry.printkey", "--key", "Classes"],
rekall_plugin_parameters = ["printkey", "--key", "Classes"])
VolatilityPlugin(name = "printkey",
vol2_plugin_parameters = ["printkey", "-K", "Classes"],
vol3_plugin_parameters = ["registry.printkey", "--key", "Classes"],
rekall_plugin_parameters = ["printkey", "--key", "Classes"])
]
parser = argparse.ArgumentParser()
parser.add_argument("--output-dir", type = str, default = os.getcwd(), help = "Directory to store all results")
parser.add_argument(
"--vol3path",
type = str,
default = os.path.join(os.getcwd(), 'volatility3'),
help = "Path ot the volatility 3 directory")
parser.add_argument(
"--vol2path",
type = str,
default = os.path.join(os.getcwd(), 'volatility'),
help = "Path to the volatility 2 directory")
parser.add_argument(
"--rekallpath",
type = str,
default = os.path.join(os.getcwd(), 'rekall'),
help = "Path to the rekall directory")
parser.add_argument(
"--frameworks",
nargs = "+",
type = str,
choices = [x.short_name.lower() for x in VolatilityTest.__subclasses__()],
default = [x.short_name.lower() for x in VolatilityTest.__subclasses__()],
help = "A comma separated list of frameworks to test")
parser.add_argument("--vol3path",
type = str,
default = os.path.join(os.getcwd(), 'volatility3'),
help = "Path ot the volatility 3 directory")
parser.add_argument("--vol2path",
type = str,
default = os.path.join(os.getcwd(), 'volatility'),
help = "Path to the volatility 2 directory")
parser.add_argument("--rekallpath",
type = str,
default = os.path.join(os.getcwd(), 'rekall'),
help = "Path to the rekall directory")
parser.add_argument("--frameworks",
nargs = "+",
type = str,
choices = [x.short_name.lower() for x in VolatilityTest.__subclasses__()],
default = [x.short_name.lower() for x in VolatilityTest.__subclasses__()],
help = "A comma separated list of frameworks to test")
parser.add_argument('images', metavar = 'IMAGE', type = str, nargs = '+', help = 'The list of images to compare')
args = parser.parse_args()
+17 -13
View File
@@ -9,41 +9,43 @@
import struct, sys
def seekread(f, offset=None, length=0, relative=True):
def seekread(f, offset = None, length = 0, relative = True):
if (offset != None):
# offset provided, let's seek
f.seek(offset, [0,1,2][relative])
f.seek(offset, [0, 1, 2][relative])
if (length != 0):
return f.read(length)
def parse_pbzx(pbzx_path):
section = 0
xar_out_path = '%s.part%02d.cpio.xz' % (pbzx_path, section)
f = open(pbzx_path, 'rb')
# pbzx = f.read()
# f.close()
magic = seekread(f,length=4)
magic = seekread(f, length = 4)
if magic != 'pbzx':
raise "Error: Not a pbzx file"
# Read 8 bytes for initial flags
flags = seekread(f,length=8)
flags = seekread(f, length = 8)
# Interpret the flags as a 64-bit big-endian unsigned int
flags = struct.unpack('>Q', flags)[0]
xar_f = open(xar_out_path, 'wb')
while (flags & (1 << 24)):
# Read in more flags
flags = seekread(f,length=8)
flags = seekread(f, length = 8)
flags = struct.unpack('>Q', flags)[0]
# Read in length
f_length = seekread(f,length=8)
f_length = seekread(f, length = 8)
f_length = struct.unpack('>Q', f_length)[0]
xzmagic = seekread(f,length=6)
xzmagic = seekread(f, length = 6)
if xzmagic != '\xfd7zXZ\x00':
# This isn't xz content, this is actually _raw decompressed cpio_ chunk of 16MB in size...
# Let's back up ...
seekread(f,offset=-6,length=0)
seekread(f, offset = -6, length = 0)
# ... and split it out ...
f_content = seekread(f,length=f_length)
f_content = seekread(f, length = f_length)
section += 1
decomp_out = '%s.part%02d.cpio' % (pbzx_path, section)
g = open(decomp_out, 'wb')
@@ -57,8 +59,8 @@ def parse_pbzx(pbzx_path):
else:
f_length -= 6
# This part needs buffering
f_content = seekread(f,length=f_length)
tail = seekread(f,offset=-2,length=2)
f_content = seekread(f, length = f_length)
tail = seekread(f, offset = -2, length = 2)
xar_f.write(xzmagic)
xar_f.write(f_content)
if tail != 'YZ':
@@ -70,9 +72,11 @@ def parse_pbzx(pbzx_path):
except:
pass
def main():
result = parse_pbzx(sys.argv[1])
print "Now xz decompress the .xz chunks, then 'cat' them all together in order into a single new.cpio file"
if __name__ == '__main__':
main()
main()
+10 -4
View File
@@ -322,10 +322,16 @@ if __name__ == '__main__':
file_group.add_argument("-f", "--file", metavar = "FILE", help = "PDB file to translate to ISF")
data_group = parser.add_argument_group("data", description = "Convert based on a GUID and filename pattern")
data_group.add_argument("-p", "--pattern", metavar = "PATTERN", help = "Filename pattern to recover PDB file")
data_group.add_argument(
"-g", "--guid", metavar = "GUID", help = "GUID + Age string for the required PDB file", default = None)
data_group.add_argument(
"-k", "--keep", action = "store_true", default = False, help = "Keep the downloaded PDB file")
data_group.add_argument("-g",
"--guid",
metavar = "GUID",
help = "GUID + Age string for the required PDB file",
default = None)
data_group.add_argument("-k",
"--keep",
action = "store_true",
default = False,
help = "Keep the downloaded PDB file")
args = parser.parse_args()
delfile = False
+32 -33
View File
@@ -6,36 +6,35 @@ import setuptools
from volatility.framework import constants
setuptools.setup(
name = "volatility",
description = "Memory forensics framework",
version = constants.PACKAGE_VERSION,
license = "VSL",
keywords = "volatility memory forensics framework windows linux volshell",
author = "Volatility Foundation",
author_email = "volatility@volatilityfoundation.org",
url = "https://volatilityfoundation.org/volatility/",
project_urls = {
"Bug Tracker": "https://github.com/volatilityfoundation/volatility3/issues",
"Documentation": "https://volatilityfoundation.org/volatility/docs/",
"Source Code": "https://github.com/volatilityfoundation/volatility3",
},
include_package_data = True,
exclude_package_data = {
'': ['development', 'development.*'],
'development': ['*']
},
packages = setuptools.find_packages(exclude = ["developement", "development.*"]),
entry_points = {
'console_scripts': [
'vol = volatility.cli:main',
'volshell = volatility.cli.volshell:main',
],
},
install_requires = ["pefile"],
extras_require = {
'jsonschema': ["jsonschema>=2.3.0"],
'yara': ["yara-python>=3.8.0"],
'disasm': ["capstone;platform_system=='Linux'", "capstone-windows;platform_system=='Windows'"],
'doc': ["sphinx>=1.8.2", "sphinx_autodoc_typehints>=1.4.0", "sphinx-rtd-theme>=0.4.3"],
})
setuptools.setup(name = "volatility",
description = "Memory forensics framework",
version = constants.PACKAGE_VERSION,
license = "VSL",
keywords = "volatility memory forensics framework windows linux volshell",
author = "Volatility Foundation",
author_email = "volatility@volatilityfoundation.org",
url = "https://volatilityfoundation.org/volatility/",
project_urls = {
"Bug Tracker": "https://github.com/volatilityfoundation/volatility3/issues",
"Documentation": "https://volatilityfoundation.org/volatility/docs/",
"Source Code": "https://github.com/volatilityfoundation/volatility3",
},
include_package_data = True,
exclude_package_data = {
'': ['development', 'development.*'],
'development': ['*']
},
packages = setuptools.find_packages(exclude = ["developement", "development.*"]),
entry_points = {
'console_scripts': [
'vol = volatility.cli:main',
'volshell = volatility.cli.volshell:main',
],
},
install_requires = ["pefile"],
extras_require = {
'jsonschema': ["jsonschema>=2.3.0"],
'yara': ["yara-python>=3.8.0"],
'disasm': ["capstone;platform_system=='Linux'", "capstone-windows;platform_system=='Windows'"],
'doc': ["sphinx>=1.8.2", "sphinx_autodoc_typehints>=1.4.0", "sphinx-rtd-theme>=0.4.3"],
})
+61 -64
View File
@@ -83,63 +83,61 @@ class CommandLine(interfaces.plugins.FileConsumerInterface):
renderers = dict([(x.name.lower(), x) for x in framework.class_subclasses(text_renderer.CLIRenderer)])
parser = argparse.ArgumentParser(prog = 'volatility', description = "An open-source memory forensics framework")
parser.add_argument(
"-c", "--config", help = "Load the configuration from a json file", default = None, type = str)
parser.add_argument(
"--parallelism",
help = "Enables parallelism (defaults to processes if no argument given)",
nargs = '?',
choices = ['processes', 'threads', 'off'],
const = 'processes',
default = None,
type = str)
parser.add_argument(
"-e",
"--extend",
help = "Extend the configuration with a new (or changed) setting",
default = None,
action = 'append')
parser.add_argument(
"-p",
"--plugin-dirs",
help = "Semi-colon separated list of paths to find plugins",
default = "",
type = str)
parser.add_argument(
"-s",
"--symbol-dirs",
help = "Semi-colon separated list of paths to find symbols",
default = "",
type = str)
parser.add_argument("-c",
"--config",
help = "Load the configuration from a json file",
default = None,
type = str)
parser.add_argument("--parallelism",
help = "Enables parallelism (defaults to processes if no argument given)",
nargs = '?',
choices = ['processes', 'threads', 'off'],
const = 'processes',
default = None,
type = str)
parser.add_argument("-e",
"--extend",
help = "Extend the configuration with a new (or changed) setting",
default = None,
action = 'append')
parser.add_argument("-p",
"--plugin-dirs",
help = "Semi-colon separated list of paths to find plugins",
default = "",
type = str)
parser.add_argument("-s",
"--symbol-dirs",
help = "Semi-colon separated list of paths to find symbols",
default = "",
type = str)
parser.add_argument("-v", "--verbosity", help = "Increase output verbosity", default = 0, action = "count")
parser.add_argument(
"-l", "--log", help = "Log output to a file as well as the console", default = None, type = str)
parser.add_argument(
"-o",
"--output-dir",
help = "Directory in which to output any generated files",
default = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')),
type = str)
parser.add_argument("-l",
"--log",
help = "Log output to a file as well as the console",
default = None,
type = str)
parser.add_argument("-o",
"--output-dir",
help = "Directory in which to output any generated files",
default = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')),
type = str)
parser.add_argument("-q", "--quiet", help = "Remove progress feedback", default = False, action = 'store_true')
parser.add_argument(
"-r",
"--renderer",
metavar = 'RENDERER',
help = "Determines how to render the output ({})".format(", ".join(list(renderers))),
default = "quick",
choices = list(renderers))
parser.add_argument(
"-f",
"--file",
metavar = 'FILE',
default = None,
type = str,
help = "Shorthand for --single-location=file:// if single-location is not defined")
parser.add_argument(
"--write-config",
help = "Write configuration JSON file out to config.json",
default = False,
action = 'store_true')
parser.add_argument("-r",
"--renderer",
metavar = 'RENDERER',
help = "Determines how to render the output ({})".format(", ".join(list(renderers))),
default = "quick",
choices = list(renderers))
parser.add_argument("-f",
"--file",
metavar = 'FILE',
default = None,
type = str,
help = "Shorthand for --single-location=file:// if single-location is not defined")
parser.add_argument("--write-config",
help = "Write configuration JSON file out to config.json",
default = False,
action = 'store_true')
# We have to filter out help, otherwise parse_known_args will trigger the help message before having
# processed the plugin choice or had the plugin subparser added.
@@ -156,8 +154,8 @@ class CommandLine(interfaces.plugins.FileConsumerInterface):
if partial_args.log:
file_logger = logging.FileHandler(partial_args.log)
file_logger.setLevel(1)
file_formatter = logging.Formatter(
datefmt = '%y-%m-%d %H:%M:%S', fmt = '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
file_formatter = logging.Formatter(datefmt = '%y-%m-%d %H:%M:%S',
fmt = '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
file_logger.setFormatter(file_formatter)
vollog.addHandler(file_logger)
vollog.info("Logging started")
@@ -385,13 +383,12 @@ class CommandLine(interfaces.plugins.FileConsumerInterface):
additional["choices"] = requirement.choices
else:
continue
parser.add_argument(
"--" + requirement.name.replace('_', '-'),
help = requirement.description,
default = requirement.default,
dest = requirement.name,
required = not requirement.optional,
**additional)
parser.add_argument("--" + requirement.name.replace('_', '-'),
help = requirement.description,
default = requirement.default,
dest = requirement.name,
required = not requirement.optional,
**additional)
# We shouldn't really steal a private member from argparse, but otherwise we're just duplicating code
+2 -2
View File
@@ -244,8 +244,8 @@ class PrettyTextRenderer(CLIRenderer):
column = grid.columns[column_index]
renderer = self._type_renderers.get(column.type, self._type_renderers['default'])
data = renderer(node.values[column_index])
max_column_widths[column.name] = max(
max_column_widths.get(column.name, len(column.name)), len("{}".format(data)))
max_column_widths[column.name] = max(max_column_widths.get(column.name, len(column.name)),
len("{}".format(data)))
line[column] = data
accumulator.append((node.path_depth, line))
return accumulator
+47 -47
View File
@@ -45,54 +45,54 @@ class VolShell(cli.CommandLine):
framework.require_interface_version(0, 0, 0)
parser = argparse.ArgumentParser(
prog = 'volshell', description = "A tool for interactivate forensic analysis of memory images")
parser.add_argument(
"-c", "--config", help = "Load the configuration from a json file", default = None, type = str)
parser.add_argument(
"-e",
"--extend",
help = "Extend the configuration with a new (or changed) setting",
default = None,
action = 'append')
parser.add_argument(
"-p",
"--plugin-dirs",
help = "Semi-colon separated list of paths to find plugins",
default = "",
type = str)
parser.add_argument(
"-s",
"--symbol-dirs",
help = "Semi-colon separated list of paths to find symbols",
default = "",
type = str)
parser = argparse.ArgumentParser(prog = 'volshell',
description = "A tool for interactivate forensic analysis of memory images")
parser.add_argument("-c",
"--config",
help = "Load the configuration from a json file",
default = None,
type = str)
parser.add_argument("-e",
"--extend",
help = "Extend the configuration with a new (or changed) setting",
default = None,
action = 'append')
parser.add_argument("-p",
"--plugin-dirs",
help = "Semi-colon separated list of paths to find plugins",
default = "",
type = str)
parser.add_argument("-s",
"--symbol-dirs",
help = "Semi-colon separated list of paths to find symbols",
default = "",
type = str)
parser.add_argument("-v", "--verbosity", help = "Increase output verbosity", default = 0, action = "count")
parser.add_argument(
"-o",
"--output-dir",
help = "Directory in which to output any generated files",
default = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')),
type = str)
parser.add_argument("-o",
"--output-dir",
help = "Directory in which to output any generated files",
default = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')),
type = str)
parser.add_argument("-q", "--quiet", help = "Remove progress feedback", default = False, action = 'store_true')
parser.add_argument("--log", help = "Log output to a file as well as the console", default = None, type = str)
parser.add_argument(
"-f",
"--file",
metavar = 'FILE',
default = None,
type = str,
help = "Shorthand for --single-location=file:// if single-location is not defined")
parser.add_argument(
"--write-config",
help = "Write configuration JSON file out to config.json",
default = False,
action = 'store_true')
parser.add_argument("-f",
"--file",
metavar = 'FILE',
default = None,
type = str,
help = "Shorthand for --single-location=file:// if single-location is not defined")
parser.add_argument("--write-config",
help = "Write configuration JSON file out to config.json",
default = False,
action = 'store_true')
# Volshell specific flags
os_specific = parser.add_mutually_exclusive_group(required = False)
os_specific.add_argument(
"-w", "--windows", default = False, action = "store_true", help = "Run a Windows volshell")
os_specific.add_argument("-w",
"--windows",
default = False,
action = "store_true",
help = "Run a Windows volshell")
os_specific.add_argument("-l", "--linux", default = False, action = "store_true", help = "Run a Linux volshell")
os_specific.add_argument("-m", "--mac", default = False, action = "store_true", help = "Run a Mac volshell")
@@ -111,8 +111,8 @@ class VolShell(cli.CommandLine):
if partial_args.log:
file_logger = logging.FileHandler(partial_args.log)
file_logger.setLevel(0)
file_formatter = logging.Formatter(
datefmt = '%y-%m-%d %H:%M:%S', fmt = '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
file_formatter = logging.Formatter(datefmt = '%y-%m-%d %H:%M:%S',
fmt = '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
file_logger.setFormatter(file_formatter)
vollog.addHandler(file_logger)
vollog.info("Logging started")
@@ -147,9 +147,9 @@ class VolShell(cli.CommandLine):
# We don't list plugin arguments, because they can be provided within python
volshell_plugin_list = {'generic': shellplugin.Volshell, 'windows': windows.Volshell}
for plugin in volshell_plugin_list:
subparser = parser.add_argument_group(
title = plugin.capitalize(),
description = "Configuration options based on {} options".format(plugin.capitalize()))
subparser = parser.add_argument_group(title = plugin.capitalize(),
description = "Configuration options based on {} options".format(
plugin.capitalize()))
self.populate_requirements_argparse(subparser, volshell_plugin_list[plugin])
configurables_list[plugin] = volshell_plugin_list[plugin]
+3 -2
View File
@@ -29,8 +29,9 @@ class Volshell(interfaces.plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"])
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"])
]
def run(self, additional_locals: Dict[str, Any] = None) -> interfaces.renderers.TreeGrid:
+11 -8
View File
@@ -63,11 +63,15 @@ class LintelStacker(interfaces.automagic.StackerLayerInterface):
if symbol_files:
isf_path = symbol_files[0]
table_name = context.symbol_space.free_table_name('LintelStacker')
table = linux.LinuxKernelIntermedSymbols(
context, 'temporary.' + table_name, name = table_name, isf_url = isf_path)
table = linux.LinuxKernelIntermedSymbols(context,
'temporary.' + table_name,
name = table_name,
isf_url = isf_path)
context.symbol_space.append(table)
kaslr_shift, _ = LinuxUtilities.find_aslr(
context, table_name, layer_name, progress_callback = progress_callback)
kaslr_shift, _ = LinuxUtilities.find_aslr(context,
table_name,
layer_name,
progress_callback = progress_callback)
layer_class = intel.Intel # type: Type
if 'init_level4_pgt' in table.symbols:
@@ -282,10 +286,9 @@ class LinuxUtilities(object):
swapper_signature = rb"swapper(\/0|\x00\x00)\x00\x00\x00\x00\x00\x00"
module = context.module(symbol_table, layer_name, 0)
for offset in context.layers[layer_name].scan(
scanner = scanners.RegExScanner(swapper_signature),
context = context,
progress_callback = progress_callback):
for offset in context.layers[layer_name].scan(scanner = scanners.RegExScanner(swapper_signature),
context = context,
progress_callback = progress_callback):
task_symbol = module.get_type('task_struct')
init_task_address = offset - task_symbol.relative_child_offset('comm')
init_task = module.object(object_type = 'task_struct', offset = init_task_address, absolute = True)
+19 -19
View File
@@ -56,8 +56,8 @@ class MacintelStacker(interfaces.automagic.StackerLayerInterface):
return None
mss = scanners.MultiStringScanner([x for x in mac_banners if x])
for banner_offset, banner in layer.scan(
context = context, scanner = mss, progress_callback = progress_callback):
for banner_offset, banner in layer.scan(context = context, scanner = mss,
progress_callback = progress_callback):
dtb = None
vollog.debug("Identified banner: {}".format(repr(banner)))
@@ -65,19 +65,17 @@ class MacintelStacker(interfaces.automagic.StackerLayerInterface):
if symbol_files:
isf_path = symbol_files[0]
table_name = context.symbol_space.free_table_name('MacintelStacker')
table = mac.MacKernelIntermedSymbols(
context = context,
config_path = join('temporary', table_name),
name = table_name,
isf_url = isf_path)
table = mac.MacKernelIntermedSymbols(context = context,
config_path = join('temporary', table_name),
name = table_name,
isf_url = isf_path)
context.symbol_space.append(table)
kaslr_shift = MacUtilities.find_aslr(
context = context,
symbol_table = table_name,
layer_name = layer_name,
compare_banner = banner,
compare_banner_offset = banner_offset,
progress_callback = progress_callback)
kaslr_shift = MacUtilities.find_aslr(context = context,
symbol_table = table_name,
layer_name = layer_name,
compare_banner = banner,
compare_banner_offset = banner_offset,
progress_callback = progress_callback)
if kaslr_shift == 0:
vollog.debug("Invalid kalsr_shift found at offset: {}".format(banner_offset))
@@ -91,8 +89,10 @@ class MacintelStacker(interfaces.automagic.StackerLayerInterface):
context.config[join(config_path, "memory_layer")] = layer_name
context.config[join(config_path, "page_map_offset")] = bootpml4_addr
layer = layers.intel.Intel32e(
context, config_path = config_path, name = new_layer_name, metadata = {'os': 'Mac'})
layer = layers.intel.Intel32e(context,
config_path = config_path,
name = new_layer_name,
metadata = {'os': 'Mac'})
idlepml4_ptr = table.get_symbol("IdlePML4").address + kaslr_shift
idlepml4_str = layer.read(idlepml4_ptr, 4)
@@ -140,9 +140,9 @@ class MacUtilities(object):
def _scan_generator(cls, context, layer_name, progress_callback):
darwin_signature = rb"Darwin Kernel Version \d{1,3}\.\d{1,3}\.\d{1,3}: [^\x00]+\x00"
for offset in context.layers[layer_name].scan(
scanner = scanners.RegExScanner(darwin_signature), context = context,
progress_callback = progress_callback):
for offset in context.layers[layer_name].scan(scanner = scanners.RegExScanner(darwin_signature),
context = context,
progress_callback = progress_callback):
banner = context.layers[layer_name].read(offset, 128)
+29 -27
View File
@@ -99,9 +99,10 @@ def scan(ctx: interfaces.context.ContextInterface,
if end is None:
end = ctx.layers[layer_name].maximum_address
for (GUID, age, pdb_name, signature_offset) in ctx.layers[layer_name].scan(
ctx, PdbSignatureScanner(pdb_names), progress_callback = progress_callback, sections = [(start,
end - start)]):
for (GUID, age, pdb_name, signature_offset) in ctx.layers[layer_name].scan(ctx,
PdbSignatureScanner(pdb_names),
progress_callback = progress_callback,
sections = [(start, end - start)]):
mz_offset = None
sig_pfn = signature_offset // page_size
@@ -243,8 +244,9 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
data_written = False
with lzma.open(potential_output_filename, "w") as of:
# Once we haven't thrown an error, do the computation
filename = pdbconv.PdbRetreiver().retreive_pdb(
guid + str(age), file_name = pdb_name, progress_callback = progress_callback)
filename = pdbconv.PdbRetreiver().retreive_pdb(guid + str(age),
file_name = pdb_name,
progress_callback = progress_callback)
if filename:
tmp_files.append(filename)
location = "file:" + request.pathname2url(tmp_files[-1])
@@ -303,11 +305,10 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
physical_layer_name = self.get_physical_layer_name(context, vlayer)
kvo_path = interfaces.configuration.path_join(vlayer.config_path, 'kernel_virtual_offset')
kernels = scan(
ctx = context,
layer_name = physical_layer_name,
page_size = vlayer.page_size,
progress_callback = progress_callback)
kernels = scan(ctx = context,
layer_name = physical_layer_name,
page_size = vlayer.page_size,
progress_callback = progress_callback)
for kernel in kernels:
# It seems the kernel is loaded at a fixed mapping (presumably because the memory manager hasn't started yet)
if kernel['mz_offset'] is None or not isinstance(kernel['mz_offset'], int):
@@ -346,16 +347,16 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
physical_layer_name = self.get_physical_layer_name(context, vlayer)
physical_layer = context.layers[physical_layer_name]
# TODO: On older windows, this might be \WINDOWS\system32\nt rather than \SystemRoot\system32\nt
results = physical_layer.scan(
context, scanners.BytesScanner(b"\\SystemRoot\\system32\\nt"), progress_callback = progress_callback)
results = physical_layer.scan(context,
scanners.BytesScanner(b"\\SystemRoot\\system32\\nt"),
progress_callback = progress_callback)
seen = set() # type: Set[int]
# Because this will launch a scan of the virtual layer, we want to be careful
for result in results:
# TODO: Identify the specific structure we're finding and document this a bit better
pointer = context.object(
"pdbscan!unsigned long long",
offset = (result - 16 - int(vlayer.bits_per_register / 8)),
layer_name = physical_layer_name)
pointer = context.object("pdbscan!unsigned long long",
offset = (result - 16 - int(vlayer.bits_per_register / 8)),
layer_name = physical_layer_name)
address = pointer & vlayer.address_mask
if address in seen:
continue
@@ -380,8 +381,9 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
seen = set() # type: Set[int]
for result in results:
# TODO: Identify the specific structure we're finding and document this a bit better
pointer = context.object(
"pdbscan!unsigned long long", offset = result + 8, layer_name = physical_layer_name)
pointer = context.object("pdbscan!unsigned long long",
offset = result + 8,
layer_name = physical_layer_name)
address = pointer & vlayer.address_mask
if address in seen:
continue
@@ -408,13 +410,12 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
try:
if vlayer.read(address, 0x2) == b'MZ':
res = list(
scan(
ctx = context,
layer_name = vlayer.name,
page_size = vlayer.page_size,
progress_callback = progress_callback,
start = address,
end = address + self.max_pdb_size))
scan(ctx = context,
layer_name = vlayer.name,
page_size = vlayer.page_size,
progress_callback = progress_callback,
start = address,
end = address + self.max_pdb_size))
if res:
valid_kernels[virtual_layer_name] = (address, res[0])
except exceptions.InvalidAddressException:
@@ -467,8 +468,9 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
# TODO: check if this is a windows symbol requirement, otherwise ignore it
self._symbol_requirements = self.find_requirements(context, config_path, requirement,
requirements.SymbolTableRequirement)
potential_layers = self.find_virtual_layers_from_req(
context = context, config_path = config_path, requirement = requirement)
potential_layers = self.find_virtual_layers_from_req(context = context,
config_path = config_path,
requirement = requirement)
for sub_config_path, symbol_req in self._symbol_requirements:
parent_path = interfaces.configuration.parent_path(sub_config_path)
if symbol_req.unsatisfied(context, parent_path):
+5 -4
View File
@@ -105,8 +105,8 @@ class LayerStacker(interfaces.automagic.AutomagicInterface):
stacked = True
stacked_layers = [current_layer_name]
framework.import_files(sys.modules['volatility.framework.layers'])
stack_set = sorted(
framework.class_subclasses(interfaces.automagic.StackerLayerInterface), key = lambda x: x.stack_order)
stack_set = sorted(framework.class_subclasses(interfaces.automagic.StackerLayerInterface),
key = lambda x: x.stack_order)
while stacked:
stacked = False
new_layer = None
@@ -189,6 +189,7 @@ class LayerStacker(interfaces.automagic.AutomagicInterface):
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
# This is not optional for the stacker to run, so optional must be marked as False
return [
requirements.URIRequirement(
"single_location", description = "Specifies a base location on which to stack", optional = True)
requirements.URIRequirement("single_location",
description = "Specifies a base location on which to stack",
optional = True)
]
+42 -25
View File
@@ -69,8 +69,8 @@ class DtbTest:
Returns:
A valid DTB within this page (and an additional parameter for data)
"""
value = data[page_offset + (self.ptr_reference * self.ptr_size):page_offset + (
(self.ptr_reference + 1) * self.ptr_size)]
value = data[page_offset + (self.ptr_reference * self.ptr_size):page_offset +
((self.ptr_reference + 1) * self.ptr_size)]
try:
ptr = self._unpack(value)
except struct.error:
@@ -115,22 +115,28 @@ class DtbTest:
class DtbTest32bit(DtbTest):
def __init__(self):
super().__init__(
layer_type = layers.intel.WindowsIntel, ptr_struct = "I", ptr_reference = 0x300, mask = 0xFFFFF000)
super().__init__(layer_type = layers.intel.WindowsIntel,
ptr_struct = "I",
ptr_reference = 0x300,
mask = 0xFFFFF000)
class DtbTest64bit(DtbTest):
def __init__(self):
super().__init__(
layer_type = layers.intel.WindowsIntel32e, ptr_struct = "Q", ptr_reference = 0x1ED, mask = 0x3FFFFFFFFFF000)
super().__init__(layer_type = layers.intel.WindowsIntel32e,
ptr_struct = "Q",
ptr_reference = 0x1ED,
mask = 0x3FFFFFFFFFF000)
class DtbTestPae(DtbTest):
def __init__(self):
super().__init__(
layer_type = layers.intel.WindowsIntelPAE, ptr_struct = "Q", ptr_reference = 0x3, mask = 0x3FFFFFFFFFF000)
super().__init__(layer_type = layers.intel.WindowsIntelPAE,
ptr_struct = "Q",
ptr_reference = 0x3,
mask = 0x3FFFFFFFFFF000)
def second_pass(self, dtb: int, data: bytes, data_offset: int) -> Optional[Tuple[int, Any]]:
"""PAE top level directory tables contains four entries and the self-
@@ -187,15 +193,19 @@ class DtbSelfReferential(DtbTest):
class DtbSelfRef32bit(DtbSelfReferential):
def __init__(self):
super().__init__(
layer_type = layers.intel.WindowsIntel, ptr_struct = "I", ptr_reference = 0x300, mask = 0xFFFFF000)
super().__init__(layer_type = layers.intel.WindowsIntel,
ptr_struct = "I",
ptr_reference = 0x300,
mask = 0xFFFFF000)
class DtbSelfRef64bit(DtbSelfReferential):
def __init__(self):
super().__init__(
layer_type = layers.intel.WindowsIntel32e, ptr_struct = "Q", ptr_reference = 0x1ED, mask = 0x3FFFFFFFFFF000)
super().__init__(layer_type = layers.intel.WindowsIntel32e,
ptr_struct = "Q",
ptr_reference = 0x1ED,
mask = 0x3FFFFFFFFFF000)
class PageMapScanner(interfaces.layers.ScannerInterface):
@@ -331,19 +341,20 @@ class WintelStacker(interfaces.automagic.StackerLayerInterface):
config_path = interfaces.configuration.path_join("IntelHelper", new_layer_name)
context.config[interfaces.configuration.path_join(config_path, "memory_layer")] = layer_name
context.config[interfaces.configuration.path_join(config_path, "page_map_offset")] = dtb
layer = test.layer_type(
context, config_path = config_path, name = new_layer_name, metadata = {'os': 'Windows'})
layer = test.layer_type(context,
config_path = config_path,
name = new_layer_name,
metadata = {'os': 'Windows'})
break
# Fall back to a heuristic for finding the Windows DTB
if layer is None:
vollog.debug("Self-referential pointer not in well-known location, moving to recent windows heuristic")
# There is a very high chance that the DTB will live in this narrow segment, assuming we couldn't find it previously
hits = context.layers[layer_name].scan(
context,
PageMapScanner([DtbSelfRef64bit()]),
sections = [(0x1a0000, 0x50000)],
progress_callback = progress_callback)
hits = context.layers[layer_name].scan(context,
PageMapScanner([DtbSelfRef64bit()]),
sections = [(0x1a0000, 0x50000)],
progress_callback = progress_callback)
# Flatten the generator
hits = list(hits)
if hits:
@@ -354,8 +365,10 @@ class WintelStacker(interfaces.automagic.StackerLayerInterface):
context.config[interfaces.configuration.path_join(config_path, "memory_layer")] = layer_name
context.config[interfaces.configuration.path_join(config_path, "page_map_offset")] = page_map_offset
# TODO: Need to determine the layer type (chances are high it's x64, hence this default)
layer = layers.intel.WindowsIntel32e(
context, config_path = config_path, name = new_layer_name, metadata = {'os': 'Windows'})
layer = layers.intel.WindowsIntel32e(context,
config_path = config_path,
name = new_layer_name,
metadata = {'os': 'Windows'})
if layer is not None and config_path:
vollog.debug("DTB was found at: 0x{:0x}".format(context.config[interfaces.configuration.path_join(
config_path, "page_map_offset")]))
@@ -373,8 +386,11 @@ class WinSwapLayers(interfaces.automagic.AutomagicInterface):
progress_callback: constants.ProgressCallback = None) -> None:
"""Finds translation layers that can have swap layers added."""
path_join = interfaces.configuration.path_join
self._translation_requirement = self.find_requirements(
context, config_path, requirement, requirements.TranslationLayerRequirement, shortcut = False)
self._translation_requirement = self.find_requirements(context,
config_path,
requirement,
requirements.TranslationLayerRequirement,
shortcut = False)
for trans_sub_config, trans_req in self._translation_requirement:
if not isinstance(trans_req, requirements.TranslationLayerRequirement):
# We need this so the type-checker knows we're a TranslationLayerRequirement
@@ -400,8 +416,9 @@ class WinSwapLayers(interfaces.automagic.AutomagicInterface):
context.config[layer_class_path] = 'volatility.framework.layers.physical.FileLayer'
# Add the requirement
new_req = requirements.TranslationLayerRequirement(
name = current_layer_name, description = "Swap Layer", optional = False)
new_req = requirements.TranslationLayerRequirement(name = current_layer_name,
description = "Swap Layer",
optional = False)
swap_req.add_requirement(new_req)
context.config[path_join(swap_sub_config, 'number_of_elements')] = counter
@@ -163,8 +163,9 @@ class ComplexListRequirement(MultiRequirement, configuration.ConfigurableRequire
def get_requirements(cls) -> List[configuration.RequirementInterface]:
# This is not optional for the stacker to run, so optional must be marked as False
return [
IntRequirement(
"number_of_elements", description = "Determines how many layers are in this list", optional = False)
IntRequirement("number_of_elements",
description = "Determines how many layers are in this list",
optional = False)
]
@abc.abstractmethod
@@ -212,8 +213,9 @@ class LayerListRequirement(ComplexListRequirement):
def new_requirement(self, index) -> configuration.RequirementInterface:
"""Constructs a new requirement based on the specified index."""
return TranslationLayerRequirement(
name = self.name + str(index), description = "Layer for swap space", optional = False)
return TranslationLayerRequirement(name = self.name + str(index),
description = "Layer for swap space",
optional = False)
class TranslationLayerRequirement(configuration.ConstructableRequirementInterface,
+33 -38
View File
@@ -110,10 +110,9 @@ class Context(interfaces.context.ContextInterface):
object_template = object_template.clone()
object_template.update_vol(**arguments)
return object_template(
context = self,
object_info = interfaces.objects.ObjectInformation(
layer_name = layer_name, offset = offset, native_layer_name = native_layer_name))
return object_template(context = self,
object_info = interfaces.objects.ObjectInformation(
layer_name = layer_name, offset = offset, native_layer_name = native_layer_name))
def module(self,
module_name: str,
@@ -131,19 +130,17 @@ class Context(interfaces.context.ContextInterface):
size: The size, in bytes, that the module occupys from offset location within the layer named layer_name
"""
if size:
return SizedModule(
self,
module_name = module_name,
layer_name = layer_name,
offset = offset,
size = size,
native_layer_name = native_layer_name)
return Module(
self,
module_name = module_name,
layer_name = layer_name,
offset = offset,
native_layer_name = native_layer_name)
return SizedModule(self,
module_name = module_name,
layer_name = layer_name,
offset = offset,
size = size,
native_layer_name = native_layer_name)
return Module(self,
module_name = module_name,
layer_name = layer_name,
offset = offset,
native_layer_name = native_layer_name)
def get_module_wrapper(method: str) -> Callable:
@@ -195,12 +192,11 @@ class Module(interfaces.context.ModuleInterface):
# Ensure we don't use a layer_name other than the module's, why would anyone do that?
if 'layer_name' in kwargs:
del kwargs['layer_name']
return self._context.object(
object_type = object_type,
layer_name = self._layer_name,
offset = offset,
native_layer_name = native_layer_name or self._native_layer_name,
**kwargs)
return self._context.object(object_type = object_type,
layer_name = self._layer_name,
offset = offset,
native_layer_name = native_layer_name or self._native_layer_name,
**kwargs)
def object_from_symbol(self,
symbol_name: str,
@@ -238,12 +234,11 @@ class Module(interfaces.context.ModuleInterface):
del kwargs['layer_name']
# Since type may be a template, we don't just call our own module method
return self._context.object(
object_type = symbol_val.type,
layer_name = self._layer_name,
offset = offset,
native_layer_name = native_layer_name or self._native_layer_name,
**kwargs)
return self._context.object(object_type = symbol_val.type,
layer_name = self._layer_name,
offset = offset,
native_layer_name = native_layer_name or self._native_layer_name,
**kwargs)
get_symbol = get_module_wrapper('get_symbol')
get_type = get_module_wrapper('get_type')
@@ -263,13 +258,12 @@ class SizedModule(Module):
size: int,
symbol_table_name: Optional[str] = None,
native_layer_name: Optional[str] = None) -> None:
super().__init__(
context,
module_name = module_name,
layer_name = layer_name,
offset = offset,
native_layer_name = native_layer_name,
symbol_table_name = symbol_table_name)
super().__init__(context,
module_name = module_name,
layer_name = layer_name,
offset = offset,
native_layer_name = native_layer_name,
symbol_table_name = symbol_table_name)
self._size = size
@property
@@ -300,8 +294,9 @@ class SizedModule(Module):
if offset > self._offset + self.size:
return []
return list(
self._context.symbol_space.get_symbols_by_location(
offset = offset - self._offset, size = size, table_name = self.symbol_table_name))
self._context.symbol_space.get_symbols_by_location(offset = offset - self._offset,
size = size,
table_name = self.symbol_table_name))
class ModuleCollection:
+6 -8
View File
@@ -246,9 +246,8 @@ class DataLayerInterface(interfaces.configuration.ConfigurableInterface, metacla
scan_chunk = functools.partial(self._scan_chunk, scanner, progress)
for value in scan_iterator():
if progress_callback:
progress_callback(
scan_metric(progress.value),
"Scanning {} using {}".format(self.name, scanner.__class__.__name__))
progress_callback(scan_metric(progress.value),
"Scanning {} using {}".format(self.name, scanner.__class__.__name__))
yield from scan_chunk(value)
else:
progress = multiprocessing.Manager().Value("Q", 0)
@@ -262,9 +261,8 @@ class DataLayerInterface(interfaces.configuration.ConfigurableInterface, metacla
while not result.ready():
if progress_callback:
# Run the progress_callback
progress_callback(
scan_metric(progress.value),
"Scanning {} using {}".format(self.name, scanner.__class__.__name__))
progress_callback(scan_metric(progress.value),
"Scanning {} using {}".format(self.name, scanner.__class__.__name__))
# Ensures we don't burn CPU cycles going round in a ready waiting loop
# without delaying the user too long between progress updates/results
result.wait(0.1)
@@ -421,8 +419,8 @@ class TranslationLayerInterface(DataLayerInterface, metaclass = ABCMeta):
# The layer_offset can be less than the current_offset in non-linearly mapped layers
# it does not suggest an overlap, but that the data is in an encoded block
if mapped_length > 0:
processed_data = self._decode(
self._context.layers.read(layer, mapped_offset, mapped_length, pad), mapped_offset, layer_offset)
processed_data = self._decode(self._context.layers.read(layer, mapped_offset, mapped_length, pad),
mapped_offset, layer_offset)
# Chop off anything unnecessary at the start
processed_data = processed_data[current_offset - layer_offset:]
# Chop off anything unnecessary at the end
+5 -6
View File
@@ -163,12 +163,11 @@ class ObjectInterface(metaclass = ABCMeta):
object_template = self._context.symbol_space.get_type(new_type_name)
object_template = object_template.clone()
object_template.update_vol(**additional)
object_info = ObjectInformation(
layer_name = self.vol.layer_name,
offset = self.vol.offset,
member_name = self.vol.member_name,
parent = self.vol.parent,
native_layer_name = self.vol.native_layer_name)
object_info = ObjectInformation(layer_name = self.vol.layer_name,
offset = self.vol.offset,
member_name = self.vol.member_name,
parent = self.vol.parent,
native_layer_name = self.vol.native_layer_name)
return object_template(context = self._context, object_info = object_info)
def has_member(self, member_name: str) -> bool:
+3 -2
View File
@@ -45,8 +45,9 @@ class WindowsCrashDump32Layer(segmented.SegmentedLayer):
self._check_header(hdr_layer, hdr_offset)
# Need to create a header object
self.header = self.context.object(
self._crash_table_name + constants.BANG + "_DMP_HEADER", offset = hdr_offset, layer_name = self._base_layer)
self.header = self.context.object(self._crash_table_name + constants.BANG + "_DMP_HEADER",
offset = hdr_offset,
layer_name = self._base_layer)
# Extract the DTB
self.dtb = self.header.DirectoryTableBase
+7 -9
View File
@@ -28,9 +28,8 @@ class Intel(linear.LinearlyMappedLayer):
_maxphyaddr = 32
_maxvirtaddr = _maxphyaddr
_structure = [('page directory', 10, False), ('page table', 10, True)]
_direct_metadata = collections.ChainMap({
'architecture': 'Intel32'
}, interfaces.layers.TranslationLayerInterface._direct_metadata)
_direct_metadata = collections.ChainMap({'architecture': 'Intel32'},
interfaces.layers.TranslationLayerInterface._direct_metadata)
def __init__(self,
context: interfaces.context.ContextInterface,
@@ -289,12 +288,11 @@ class WindowsMixin(Intel):
interfaces.configuration.path_join('swap_layers', 'swap_layers' + str(n)), None)
if swap_layer_name:
return swap_offset, 1 << excp.invalid_bits, swap_layer_name
raise exceptions.SwappedInvalidAddressException(
layer_name = excp.layer_name,
invalid_address = excp.invalid_address,
invalid_bits = excp.invalid_bits,
entry = excp.entry,
swap_offset = swap_offset)
raise exceptions.SwappedInvalidAddressException(layer_name = excp.layer_name,
invalid_address = excp.invalid_address,
invalid_bits = excp.invalid_bits,
entry = excp.entry,
swap_offset = swap_offset)
raise
+18 -16
View File
@@ -47,24 +47,27 @@ class PdbMultiStreamFormat(linear.LinearlyMappedLayer):
root_table_num_pages = math.ceil(self._header.StreamInfo.StreamInfoSize / self._header.PageSize)
root_index_size = math.ceil((root_table_num_pages * entry_size) / self._header.PageSize)
root_index = module.object(
object_type = "array",
offset = self._header.vol.size,
count = root_index_size,
subtype = module.get_type("unsigned long"))
root_index = module.object(object_type = "array",
offset = self._header.vol.size,
count = root_index_size,
subtype = module.get_type("unsigned long"))
root_index_layer_name = self.create_stream_from_pages("root_index", self._header.StreamInfo.StreamInfoSize,
[x for x in root_index])
module = self.context.module(self.pdb_symbol_table, root_index_layer_name, offset = 0)
root_pages = module.object(
object_type = "array", offset = 0, count = root_table_num_pages, subtype = module.get_type("unsigned long"))
root_pages = module.object(object_type = "array",
offset = 0,
count = root_table_num_pages,
subtype = module.get_type("unsigned long"))
root_layer_name = self.create_stream_from_pages("root", self._header.StreamInfo.StreamInfoSize,
[x for x in root_pages])
module = self.context.module(self.pdb_symbol_table, root_layer_name, offset = 0)
num_streams = module.object(object_type = "unsigned long", offset = 0)
stream_sizes = module.object(
object_type = "array", offset = entry_size, count = num_streams, subtype = module.get_type("unsigned long"))
stream_sizes = module.object(object_type = "array",
offset = entry_size,
count = num_streams,
subtype = module.get_type("unsigned long"))
current_offset = (num_streams + 1) * entry_size
@@ -73,11 +76,10 @@ class PdbMultiStreamFormat(linear.LinearlyMappedLayer):
if list_size == 0 or stream_sizes[stream] == 0xffffffff:
self._streams[stream] = None
else:
stream_page_list = module.object(
object_type = "array",
offset = current_offset,
count = list_size,
subtype = module.get_type("unsigned long"))
stream_page_list = module.object(object_type = "array",
offset = current_offset,
count = list_size,
subtype = module.get_type("unsigned long"))
current_offset += (list_size * entry_size)
self._streams[stream] = self.create_stream_from_pages("stream" + str(stream), stream_sizes[stream],
[x for x in stream_page_list])
@@ -185,8 +187,8 @@ class PdbMSFStream(linear.LinearlyMappedLayer):
chunk_size = min(page_size - page_position, length)
if page >= self._pages_len:
if not ignore_errors:
raise exceptions.InvalidAddressException(
layer_name = self.name, invalid_address = offset + returned)
raise exceptions.InvalidAddressException(layer_name = self.name,
invalid_address = offset + returned)
else:
yield (offset + returned, (self._pages[page] * page_size) + page_position, chunk_size, self._base_layer)
returned += chunk_size
+3 -2
View File
@@ -57,8 +57,9 @@ class BufferDataLayer(interfaces.layers.DataLayerInterface):
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
# No real requirements (only the buffer). Need to figure out if there's a better way of representing this
return [
requirements.BytesRequirement(
name = 'buffer', description = "The direct bytes to interact with", optional = False)
requirements.BytesRequirement(name = 'buffer',
description = "The direct bytes to interact with",
optional = False)
]
+10 -11
View File
@@ -101,10 +101,9 @@ class RegistryHive(linear.LinearlyMappedLayer):
def get_cell(self, cell_offset: int) -> 'objects.StructType':
"""Returns the appropriate Cell value for a cell offset."""
# This would be an _HCELL containing CELL_DATA, but to save time we skip the size of the HCELL
cell = self._context.object(
object_type = self._table_name + constants.BANG + "_CELL_DATA",
offset = cell_offset + 4,
layer_name = self.name)
cell = self._context.object(object_type = self._table_name + constants.BANG + "_CELL_DATA",
offset = cell_offset + 4,
layer_name = self.name)
return cell
def get_node(self, cell_offset: int) -> 'objects.StructType':
@@ -181,14 +180,14 @@ class RegistryHive(linear.LinearlyMappedLayer):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
IntRequirement(
name = 'hive_offset',
description = 'Offset within the base layer at which the hive lives',
default = 0,
optional = False),
IntRequirement(name = 'hive_offset',
description = 'Offset within the base layer at which the hive lives',
default = 0,
optional = False),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
TranslationLayerRequirement(
name = 'base_layer', description = 'Layer in which the registry hive lives', optional = False)
TranslationLayerRequirement(name = 'base_layer',
description = 'Layer in which the registry hive lives',
optional = False)
]
def _translate(self, offset: int) -> int:
+12 -12
View File
@@ -68,23 +68,23 @@ class VmwareLayer(segmented.SegmentedLayer):
name_len = ord(meta_layer.read(offset + 1, 1))
tags_read = (flags == 0) and (name_len == 0)
if not tags_read:
name = self._context.object(
"vmware!string", layer_name = self._meta_layer, offset = offset + 2, max_length = name_len)
name = self._context.object("vmware!string",
layer_name = self._meta_layer,
offset = offset + 2,
max_length = name_len)
indicies_len = (flags >> 6) & 3
indicies = []
for index in range(indicies_len):
indicies.append(
self._context.object(
"vmware!unsigned int",
offset = offset + name_len + 2 + (index * index_len),
layer_name = self._meta_layer))
data = self._context.object(
"vmware!unsigned int",
layer_name = self._meta_layer,
offset = offset + 2 + name_len + (indicies_len * index_len))
self._context.object("vmware!unsigned int",
offset = offset + name_len + 2 + (index * index_len),
layer_name = self._meta_layer))
data = self._context.object("vmware!unsigned int",
layer_name = self._meta_layer,
offset = offset + 2 + name_len + (indicies_len * index_len))
tags[(name, tuple(indicies))] = (flags, data)
offset += 2 + name_len + (
indicies_len * index_len) + self._context.symbol_space.get_type("vmware!unsigned int").size
offset += 2 + name_len + (indicies_len *
index_len) + self._context.symbol_space.get_type("vmware!unsigned int").size
if tags[("regionsCount", ())][1] == 0:
raise ValueError("VMware VMEM is not split into regions")
+7 -4
View File
@@ -20,10 +20,13 @@ class ConfigWriter(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.BooleanRequirement(
name = 'extra', description = 'Outputs whole configuration tree', default = False, optional = True)
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.BooleanRequirement(name = 'extra',
description = 'Outputs whole configuration tree',
default = False,
optional = True)
]
def _generator(self):
+15 -14
View File
@@ -23,20 +23,21 @@ class LayerWriter(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.StringRequirement(
name = 'layer_name', description = 'Name of the layer to write out', default = None, optional = True),
requirements.StringRequirement(
name = 'output',
description = 'Filename to output the chosen layer',
optional = True,
default = cls.default_output_name),
requirements.IntRequirement(
name = 'block_size',
description = "Size of blocks to copy over",
default = cls.default_block_size,
optional = True)
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.StringRequirement(name = 'layer_name',
description = 'Name of the layer to write out',
default = None,
optional = True),
requirements.StringRequirement(name = 'output',
description = 'Filename to output the chosen layer',
optional = True,
default = cls.default_output_name),
requirements.IntRequirement(name = 'block_size',
description = "Size of blocks to copy over",
default = cls.default_block_size,
optional = True)
]
def _generator(self):
+20 -21
View File
@@ -24,8 +24,9 @@ class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols"),
requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0)),
]
@@ -58,22 +59,19 @@ class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface):
bang_addrs = []
# find '#' values on the heap
for address in proc_layer.scan(
self.context,
scanners.BytesScanner(b"#"),
sections = task.get_process_memory_sections(heap_only = True)):
for address in proc_layer.scan(self.context,
scanners.BytesScanner(b"#"),
sections = task.get_process_memory_sections(heap_only = True)):
bang_addrs.append(struct.pack(pack_format, address))
history_entries = []
for address, _ in proc_layer.scan(
self.context,
scanners.MultiStringScanner(bang_addrs),
sections = task.get_process_memory_sections(heap_only = True)):
hist = self.context.object(
bash_table_name + constants.BANG + "hist_entry",
offset = address - ts_offset,
layer_name = proc_layer_name)
for address, _ in proc_layer.scan(self.context,
scanners.MultiStringScanner(bang_addrs),
sections = task.get_process_memory_sections(heap_only = True)):
hist = self.context.object(bash_table_name + constants.BANG + "hist_entry",
offset = address - ts_offset,
layer_name = proc_layer_name)
if hist.is_valid():
history_entries.append(hist)
@@ -87,18 +85,19 @@ class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface):
return renderers.TreeGrid([("PID", int), ("Process", str), ("CommandTime", datetime.datetime),
("Command", str)],
self._generator(
pslist.PsList.list_tasks(
self.context,
self.config['primary'],
self.config['vmlinux'],
filter_func = filter_func)))
pslist.PsList.list_tasks(self.context,
self.config['primary'],
self.config['vmlinux'],
filter_func = filter_func)))
def generate_timeline(self):
filter_func = pslist.PsList.create_pid_filter([self.config.get('pid', None)])
for row in self._generator(
pslist.PsList.list_tasks(
self.context, self.config['primary'], self.config['vmlinux'], filter_func = filter_func)):
pslist.PsList.list_tasks(self.context,
self.config['primary'],
self.config['vmlinux'],
filter_func = filter_func)):
_depth, row_data = row
description = "{} ({}): \"{}\"".format(row_data[0], row_data[1], row_data[3])
yield (description, timeliner.TimeLinerType.CREATED, row_data[2])
@@ -22,8 +22,9 @@ class Check_afinfo(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols")
]
@@ -63,8 +64,11 @@ class Check_afinfo(plugins.PluginInterface):
def _generator(self):
linux.LinuxUtilities.aslr_mask_symbol_table(self.context, self.config['vmlinux'], self.config['primary'])
vmlinux = contexts.Module(
self.context, self.config['vmlinux'], self.config['primary'], 0, absolute_symbol_addresses = True)
vmlinux = contexts.Module(self.context,
self.config['vmlinux'],
self.config['primary'],
0,
absolute_symbol_addresses = True)
op_members = vmlinux.get_type('file_operations').members
seq_members = vmlinux.get_type('seq_operations').members
@@ -29,8 +29,9 @@ class Check_syscall(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols")
]
@@ -123,8 +124,11 @@ class Check_syscall(plugins.PluginInterface):
def _generator(self):
linux.LinuxUtilities.aslr_mask_symbol_table(self.context, self.config['vmlinux'], self.config['primary'])
vmlinux = contexts.Module(
self.context, self.config['vmlinux'], self.config['primary'], 0, absolute_symbol_addresses = True)
vmlinux = contexts.Module(self.context,
self.config['vmlinux'],
self.config['primary'],
0,
absolute_symbol_addresses = True)
ptr_sz = vmlinux.get_type("pointer").size
if ptr_sz == 4:
@@ -153,8 +157,10 @@ class Check_syscall(plugins.PluginInterface):
tables.append(("32bit", ia32_info))
for (table_name, (tableaddr, tblsz)) in tables:
table = vmlinux.object(
object_type = "array", subtype = vmlinux.get_type("pointer"), offset = tableaddr, count = tblsz)
table = vmlinux.object(object_type = "array",
subtype = vmlinux.get_type("pointer"),
offset = tableaddr,
count = tblsz)
for (i, call_addr) in enumerate(table):
if not call_addr:
+7 -7
View File
@@ -20,8 +20,9 @@ class Elfs(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols"),
requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0))
]
@@ -51,8 +52,7 @@ class Elfs(plugins.PluginInterface):
return renderers.TreeGrid([("PID", int), ("Process", str), ("Start", format_hints.Hex),
("End", format_hints.Hex), ("File Path", str)],
self._generator(
pslist.PsList.list_tasks(
self.context,
self.config['primary'],
self.config['vmlinux'],
filter_func = filter_func)))
pslist.PsList.list_tasks(self.context,
self.config['primary'],
self.config['vmlinux'],
filter_func = filter_func)))
+3 -2
View File
@@ -21,8 +21,9 @@ class Lsmod(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols")
]
+7 -7
View File
@@ -22,8 +22,9 @@ class Lsof(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols"),
requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0))
]
@@ -44,8 +45,7 @@ class Lsof(plugins.PluginInterface):
return renderers.TreeGrid([("PID", int), ("Process", str), ("FD", int), ("Path", str)],
self._generator(
pslist.PsList.list_tasks(
self.context,
self.config['primary'],
self.config['vmlinux'],
filter_func = filter_func)))
pslist.PsList.list_tasks(self.context,
self.config['primary'],
self.config['vmlinux'],
filter_func = filter_func)))
@@ -20,8 +20,9 @@ class Malfind(interfaces_plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols")
]
@@ -68,8 +69,7 @@ class Malfind(interfaces_plugins.PluginInterface):
("End", format_hints.Hex), ("Protection", str), ("Hexdump", format_hints.HexBytes),
("Disasm", interfaces_renderers.Disassembly)],
self._generator(
pslist.PsList.list_tasks(
self.context,
self.config['primary'],
self.config['vmlinux'],
filter_func = filter_func)))
pslist.PsList.list_tasks(self.context,
self.config['primary'],
self.config['vmlinux'],
filter_func = filter_func)))
+7 -7
View File
@@ -19,8 +19,9 @@ class Maps(plugins.PluginInterface):
def get_requirements(cls):
# Since we're calling the plugin, make sure we have the plugin's requirements
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols"),
requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0))
]
@@ -60,8 +61,7 @@ class Maps(plugins.PluginInterface):
("PgOff", format_hints.Hex), ("Major", int), ("Minor", int), ("Inode", int),
("File Path", str)],
self._generator(
pslist.PsList.list_tasks(
self.context,
self.config['primary'],
self.config['vmlinux'],
filter_func = filter_func)))
pslist.PsList.list_tasks(self.context,
self.config['primary'],
self.config['vmlinux'],
filter_func = filter_func)))
+7 -7
View File
@@ -19,8 +19,9 @@ class PsList(interfaces_plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "vmlinux", description = "Linux kernel symbols")
]
@@ -47,11 +48,10 @@ class PsList(interfaces_plugins.PluginInterface):
return lambda _: False
def _generator(self):
for task in self.list_tasks(
self.context,
self.config['primary'],
self.config['vmlinux'],
filter_func = self.create_pid_filter([self.config.get('pid', None)])):
for task in self.list_tasks(self.context,
self.config['primary'],
self.config['vmlinux'],
filter_func = self.create_pid_filter([self.config.get('pid', None)])):
pid = task.pid
ppid = 0
if task.parent:
+24 -23
View File
@@ -24,8 +24,9 @@ class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols"),
requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0))
]
@@ -58,24 +59,23 @@ class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface):
bang_addrs = []
# find '#' values on the heap
for address in proc_layer.scan(
self.context,
scanners.BytesScanner(b"#"),
sections = task.get_process_memory_sections(self.context, self.config['darwin'],
rw_no_file = True)):
for address in proc_layer.scan(self.context,
scanners.BytesScanner(b"#"),
sections = task.get_process_memory_sections(self.context,
self.config['darwin'],
rw_no_file = True)):
bang_addrs.append(struct.pack(pack_format, address))
history_entries = []
for address, _ in proc_layer.scan(
self.context,
scanners.MultiStringScanner(bang_addrs),
sections = task.get_process_memory_sections(self.context, self.config['darwin'],
rw_no_file = True)):
hist = self.context.object(
bash_table_name + constants.BANG + "hist_entry",
offset = address - ts_offset,
layer_name = proc_layer_name)
for address, _ in proc_layer.scan(self.context,
scanners.MultiStringScanner(bang_addrs),
sections = task.get_process_memory_sections(self.context,
self.config['darwin'],
rw_no_file = True)):
hist = self.context.object(bash_table_name + constants.BANG + "hist_entry",
offset = address - ts_offset,
layer_name = proc_layer_name)
if hist.is_valid():
history_entries.append(hist)
@@ -89,18 +89,19 @@ class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface):
return renderers.TreeGrid([("PID", int), ("Process", str), ("CommandTime", datetime.datetime),
("Command", str)],
self._generator(
pslist.PsList.list_tasks(
self.context,
self.config['primary'],
self.config['darwin'],
filter_func = filter_func)))
pslist.PsList.list_tasks(self.context,
self.config['primary'],
self.config['darwin'],
filter_func = filter_func)))
def generate_timeline(self):
filter_func = pslist.PsList.create_pid_filter([self.config.get('pid', None)])
for row in self._generator(
pslist.PsList.list_tasks(
self.context, self.config['primary'], self.config['darwin'], filter_func = filter_func)):
pslist.PsList.list_tasks(self.context,
self.config['primary'],
self.config['darwin'],
filter_func = filter_func)):
_depth, row_data = row
description = "{} ({}): \"{}\"".format(row_data[0], row_data[1], row_data[3])
yield (description, timeliner.TimeLinerType.CREATED, row_data[2])
@@ -20,8 +20,9 @@ class Check_syscall(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols")
]
@@ -22,8 +22,9 @@ class Check_sysctl(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols")
]
@@ -21,8 +21,9 @@ class Check_trap_table(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols")
]
+3 -2
View File
@@ -19,8 +19,9 @@ class Lsmod(plugins.PluginInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "darwin", description = "Linux kernel symbols")
]
+7 -7
View File
@@ -19,8 +19,9 @@ class lsof(plugins.PluginInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Kernel Address Space', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Kernel Address Space',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "darwin", description = "Mac Kernel"),
requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0))
]
@@ -38,8 +39,7 @@ class lsof(plugins.PluginInterface):
return renderers.TreeGrid([("PID", int), ("File Descriptor", int), ("File Path", str)],
self._generator(
pslist.PsList.list_tasks(
self.context,
self.config['primary'],
self.config['darwin'],
filter_func = filter_func)))
pslist.PsList.list_tasks(self.context,
self.config['primary'],
self.config['darwin'],
filter_func = filter_func)))
+7 -7
View File
@@ -18,8 +18,9 @@ class Malfind(interfaces_plugins.PluginInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "darwin", description = "Linux kernel symbols")
]
@@ -66,8 +67,7 @@ class Malfind(interfaces_plugins.PluginInterface):
("End", format_hints.Hex), ("Protection", str), ("Hexdump", format_hints.HexBytes),
("Disasm", interfaces_renderers.Disassembly)],
self._generator(
pslist.PsList.list_tasks(
self.context,
self.config['primary'],
self.config['darwin'],
filter_func = filter_func)))
pslist.PsList.list_tasks(self.context,
self.config['primary'],
self.config['darwin'],
filter_func = filter_func)))
+7 -7
View File
@@ -21,8 +21,9 @@ class Netstat(plugins.PluginInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Kernel Address Space', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Kernel Address Space',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "darwin", description = "Mac Kernel"),
requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0))
]
@@ -78,8 +79,7 @@ class Netstat(plugins.PluginInterface):
return renderers.TreeGrid([("Offset", format_hints.Hex), ("Proto", str), ("Local IP", str), ("Local Port", int),
("Remote IP", str), ("Remote Port", int), ("State", str), ("Process", str)],
self._generator(
pslist.PsList.list_tasks(
self.context,
self.config['primary'],
self.config['darwin'],
filter_func = filter_func)))
pslist.PsList.list_tasks(self.context,
self.config['primary'],
self.config['darwin'],
filter_func = filter_func)))
@@ -17,8 +17,9 @@ class Maps(interfaces_plugins.PluginInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "darwin", description = "Linux kernel symbols"),
requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0))
]
@@ -42,8 +43,7 @@ class Maps(interfaces_plugins.PluginInterface):
return renderers.TreeGrid([("PID", int), ("Process", str), ("Start", format_hints.Hex),
("End", format_hints.Hex), ("Protection", str), ("Map Name", str)],
self._generator(
pslist.PsList.list_tasks(
self.context,
self.config['primary'],
self.config['darwin'],
filter_func = filter_func)))
pslist.PsList.list_tasks(self.context,
self.config['primary'],
self.config['darwin'],
filter_func = filter_func)))
+7 -7
View File
@@ -17,8 +17,9 @@ class Psaux(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols"),
requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0))
]
@@ -89,8 +90,7 @@ class Psaux(plugins.PluginInterface):
return renderers.TreeGrid([("PID", int), ("Process", str), ("Argc", int), ("Arguments", str)],
self._generator(
pslist.PsList.list_tasks(
self.context,
self.config['primary'],
self.config['darwin'],
filter_func = filter_func)))
pslist.PsList.list_tasks(self.context,
self.config['primary'],
self.config['darwin'],
filter_func = filter_func)))
+7 -7
View File
@@ -21,8 +21,9 @@ class PsList(interfaces.plugins.PluginInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols")
]
@@ -42,11 +43,10 @@ class PsList(interfaces.plugins.PluginInterface):
return filter_func
def _generator(self):
for task in self.list_tasks(
self.context,
self.config['primary'],
self.config['darwin'],
filter_func = self.create_pid_filter([self.config.get('pid', None)])):
for task in self.list_tasks(self.context,
self.config['primary'],
self.config['darwin'],
filter_func = self.create_pid_filter([self.config.get('pid', None)])):
pid = task.p_pid
ppid = task.p_ppid
name = utility.array_to_string(task.p_comm)
+3 -2
View File
@@ -22,8 +22,9 @@ class PsTree(plugins.PluginInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols"),
requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0))
]
@@ -23,8 +23,9 @@ class Check_syscall(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "darwin", description = "Mac kernel symbols"),
requirements.PluginRequirement(name = 'lsmod', plugin = lsmod.Lsmod, version = (1, 0, 0))
]
@@ -36,11 +37,10 @@ class Check_syscall(plugins.PluginInterface):
policy_list = kernel.object_from_symbol(symbol_name = "_mac_policy_list").cast("mac_policy_list")
entries = kernel.object(
object_type = "array",
offset = policy_list.entries.dereference().vol.offset,
subtype = kernel.get_type('mac_policy_list_element'),
count = policy_list.staticmax + 1)
entries = kernel.object(object_type = "array",
offset = policy_list.entries.dereference().vol.offset,
subtype = kernel.get_type('mac_policy_list_element'),
count = policy_list.staticmax + 1)
mask = self.context.layers[self.config['primary']].address_mask
mods_list = [(mod.name, mod.address & mask, (mod.address & mask) + mod.size) for mod in mods]
+8 -10
View File
@@ -72,11 +72,10 @@ class Timeliner(interfaces.plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.StringRequirement(
name = 'plugins',
description = "Comma separated list of plugins to run",
optional = True,
default = None),
requirements.StringRequirement(name = 'plugins',
description = "Comma separated list of plugins to run",
optional = True,
default = None),
requirements.BooleanRequirement(
name = 'record-config',
description = "Whether to record the state of all the plugins once complete",
@@ -150,11 +149,10 @@ class Timeliner(interfaces.plugins.PluginInterface):
json.dump(total_config, fp, sort_keys = True, indent = 2)
self.produce_file(filedata)
return renderers.TreeGrid(
columns = [("Plugin", str), ("Description", str), ("Created Date", datetime.datetime),
("Modified Date", datetime.datetime), ("Accessed Date", datetime.datetime),
("Changed Date", datetime.datetime)],
generator = self._generator(runable_plugins))
return renderers.TreeGrid(columns = [("Plugin", str), ("Description", str), ("Created Date", datetime.datetime),
("Modified Date", datetime.datetime), ("Accessed Date", datetime.datetime),
("Changed Date", datetime.datetime)],
generator = self._generator(runable_plugins))
def build_configuration(self):
"""Builds the configuration to save for the plugin such that it can be
@@ -24,8 +24,9 @@ class Callbacks(interfaces_plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
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 = 'ssdt', plugin = ssdt.SSDT, version = (1, 0, 0)),
requirements.PluginRequirement(name = 'svcscan', plugin = svcscan.SvcScan, version = (1, 0, 0))
@@ -52,13 +53,12 @@ class Callbacks(interfaces_plugins.PluginInterface):
else:
symbol_filename = "callbacks-x86"
return intermed.IntermediateSymbolTable.create(
context,
config_path,
"windows",
symbol_filename,
native_types = native_types,
table_mapping = table_mapping)
return intermed.IntermediateSymbolTable.create(context,
config_path,
"windows",
symbol_filename,
native_types = native_types,
table_mapping = table_mapping)
@classmethod
def list_notify_routines(cls, context: interfaces.context.ContextInterface, layer_name: str, symbol_table: str,
@@ -97,11 +97,10 @@ class Callbacks(interfaces_plugins.PluginInterface):
else:
count = 8
fast_refs = ntkrnlmp.object(
object_type = "array",
offset = symbol_offset,
subtype = ntkrnlmp.get_type("_EX_FAST_REF"),
count = count)
fast_refs = ntkrnlmp.object(object_type = "array",
offset = symbol_offset,
subtype = ntkrnlmp.get_type("_EX_FAST_REF"),
count = count)
for fast_ref in fast_refs:
try:
@@ -143,11 +142,10 @@ class Callbacks(interfaces_plugins.PluginInterface):
if callback_count == 0:
return
fast_refs = ntkrnlmp.object(
object_type = "array",
offset = symbol_offset,
subtype = ntkrnlmp.get_type("_EX_FAST_REF"),
count = callback_count)
fast_refs = ntkrnlmp.object(object_type = "array",
offset = symbol_offset,
subtype = ntkrnlmp.get_type("_EX_FAST_REF"),
count = callback_count)
for fast_ref in fast_refs:
try:
@@ -183,8 +181,9 @@ class Callbacks(interfaces_plugins.PluginInterface):
return
full_type_name = callback_table_name + constants.BANG + "_KBUGCHECK_REASON_CALLBACK_RECORD"
callback_record = context.object(
object_type = full_type_name, offset = kvo + list_offset, layer_name = layer_name)
callback_record = context.object(object_type = full_type_name,
offset = kvo + list_offset,
layer_name = layer_name)
for callback in callback_record.Entry:
@@ -233,12 +232,11 @@ class Callbacks(interfaces_plugins.PluginInterface):
continue
try:
component = context.object(
symbol_table + constants.BANG + "string",
layer_name = layer_name,
offset = callback.Component,
max_length = 64,
errors = "replace")
component = context.object(symbol_table + constants.BANG + "string",
layer_name = layer_name,
offset = callback.Component,
max_length = 64,
errors = "replace")
except exceptions.InvalidAddressException:
component = renderers.UnreadableValue()
+13 -13
View File
@@ -18,12 +18,14 @@ class CmdLine(interfaces_plugins.PluginInterface):
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
# Since we're calling the plugin, make sure we have the plugin's requirements
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
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 = 'pslist', plugin = pslist.PsList, version = (1, 0, 0)),
requirements.IntRequirement(
name = 'pid', description = "Process ID to include (all other processes are excluded)", optional = True)
requirements.IntRequirement(name = 'pid',
description = "Process ID to include (all other processes are excluded)",
optional = True)
]
def _generator(self, procs):
@@ -34,10 +36,9 @@ class CmdLine(interfaces_plugins.PluginInterface):
proc_layer_name = proc.add_process_layer()
try:
peb = self._context.object(
self.config["nt_symbols"] + constants.BANG + "_PEB",
layer_name = proc_layer_name,
offset = proc.Peb)
peb = self._context.object(self.config["nt_symbols"] + constants.BANG + "_PEB",
layer_name = proc_layer_name,
offset = proc.Peb)
result_text = peb.ProcessParameters.CommandLine.get_string()
@@ -54,8 +55,7 @@ class CmdLine(interfaces_plugins.PluginInterface):
return renderers.TreeGrid([("PID", int), ("Process", str), ("Args", str)],
self._generator(
pslist.PsList.list_processes(
context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func)))
pslist.PsList.list_processes(context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func)))
+12 -11
View File
@@ -43,8 +43,11 @@ class DllDump(interfaces_plugins.PluginInterface):
]
def _generator(self, procs):
pe_table_name = intermed.IntermediateSymbolTable.create(
self.context, self.config_path, "windows", "pe", class_types = extensions.pe.class_types)
pe_table_name = intermed.IntermediateSymbolTable.create(self.context,
self.config_path,
"windows",
"pe",
class_types = extensions.pe.class_types)
filter_func = lambda _: False
if self.config.get('address', None) is not None:
@@ -80,10 +83,9 @@ class DllDump(interfaces_plugins.PluginInterface):
filedata = interfaces_plugins.FileInterface("pid.{0}.{1}.{2:#x}.dmp".format(
proc.UniqueProcessId, ntpath.basename(vad.get_file_name()), vad.get_start()))
dos_header = self.context.object(
pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
offset = vad.get_start(),
layer_name = proc_layer_name)
dos_header = self.context.object(pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
offset = vad.get_start(),
layer_name = proc_layer_name)
for offset, data in dos_header.reconstruct():
filedata.data.seek(offset)
@@ -101,8 +103,7 @@ class DllDump(interfaces_plugins.PluginInterface):
return renderers.TreeGrid([("PID", int), ("Process", str), ("Result", str)],
self._generator(
pslist.PsList.list_processes(
context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func)))
pslist.PsList.list_processes(context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func)))
+14 -13
View File
@@ -18,12 +18,14 @@ class DllList(interfaces_plugins.PluginInterface):
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
# Since we're calling the plugin, make sure we have the plugin's requirements
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
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 = 'pslist', plugin = pslist.PsList, version = (1, 0, 0)),
requirements.IntRequirement(
name = 'pid', description = "Process ID to include (all other processes are excluded)", optional = True)
requirements.IntRequirement(name = 'pid',
description = "Process ID to include (all other processes are excluded)",
optional = True)
]
def _generator(self, procs):
@@ -41,10 +43,10 @@ class DllList(interfaces_plugins.PluginInterface):
pass
yield (0, (proc.UniqueProcessId,
proc.ImageFileName.cast(
"string", max_length = proc.ImageFileName.vol.count, errors = 'replace'),
format_hints.Hex(entry.DllBase), format_hints.Hex(entry.SizeOfImage), BaseDllName,
FullDllName))
proc.ImageFileName.cast("string",
max_length = proc.ImageFileName.vol.count,
errors = 'replace'), format_hints.Hex(entry.DllBase),
format_hints.Hex(entry.SizeOfImage), BaseDllName, FullDllName))
def run(self):
filter_func = pslist.PsList.create_pid_filter([self.config.get('pid', None)])
@@ -52,8 +54,7 @@ class DllList(interfaces_plugins.PluginInterface):
return renderers.TreeGrid([("PID", int), ("Process", str), ("Base", format_hints.Hex),
("Size", format_hints.Hex), ("Name", str), ("Path", str)],
self._generator(
pslist.PsList.list_processes(
context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func)))
pslist.PsList.list_processes(context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func)))
@@ -28,8 +28,9 @@ class DriverIrp(plugins.PluginInterface):
return [
requirements.PluginRequirement(name = 'ssdt', plugin = ssdt.SSDT, version = (1, 0, 0)),
requirements.PluginRequirement(name = 'driverscan', plugin = driverscan.DriverScan, version = (1, 0, 0)),
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
]
@@ -20,8 +20,9 @@ class DriverScan(plugins.PluginInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
]
@@ -18,8 +18,9 @@ class FileScan(plugins.PluginInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
]
+30 -21
View File
@@ -37,11 +37,13 @@ class Handles(interfaces_plugins.PluginInterface):
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
# Since we're calling the plugin, make sure we have the plugin's requirements
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
requirements.IntRequirement(
name = 'pid', description = "Process ID to include (all other processes are excluded)", optional = True)
requirements.IntRequirement(name = 'pid',
description = "Process ID to include (all other processes are excluded)",
optional = True)
]
def _decode_pointer(self, value, magic):
@@ -86,8 +88,9 @@ class Handles(interfaces_plugins.PluginInterface):
offset = self._decode_pointer(handle_table_entry.LowValue, magic)
# print("LowValue: {0:#x} Magic: {1:#x} Offset: {2:#x}".format(handle_table_entry.InfoTable, magic, offset))
object_header = self.context.object(
self.config["nt_symbols"] + constants.BANG + "_OBJECT_HEADER", virtual, offset = offset)
object_header = self.context.object(self.config["nt_symbols"] + constants.BANG + "_OBJECT_HEADER",
virtual,
offset = offset)
object_header.GrantedAccess = handle_table_entry.GrantedAccessBits
object_header.HandleValue = handle_value
@@ -163,8 +166,10 @@ class Handles(interfaces_plugins.PluginInterface):
except exceptions.SymbolError:
table_addr = ntkrnlmp.get_symbol("ObpObjectTypes").address
ptrs = ntkrnlmp.object(
object_type = "array", offset = table_addr, subtype = ntkrnlmp.get_type("pointer"), count = 100)
ptrs = ntkrnlmp.object(object_type = "array",
offset = table_addr,
subtype = ntkrnlmp.get_type("pointer"),
count = 100)
for i, ptr in enumerate(ptrs): # type: ignore
# the first entry in the table is always null. break the
@@ -216,8 +221,11 @@ class Handles(interfaces_plugins.PluginInterface):
if not self.context.layers[virtual].is_valid(offset):
return
table = ntkrnlmp.object(
object_type = "array", offset = offset, subtype = subtype, count = int(count), absolute = True)
table = ntkrnlmp.object(object_type = "array",
offset = offset,
subtype = subtype,
count = int(count),
absolute = True)
layer_object = self.context.layers[virtual]
masked_offset = (offset & layer_object.maximum_address)
@@ -232,8 +240,8 @@ class Handles(interfaces_plugins.PluginInterface):
handle_multiplier = 4
handle_level_base = depth * count * handle_multiplier
handle_value = (
(entry.vol.offset - masked_offset) / (subtype.size / handle_multiplier)) + handle_level_base
handle_value = ((entry.vol.offset - masked_offset) /
(subtype.size / handle_multiplier)) + handle_level_base
item = self._get_item(entry, handle_value)
@@ -263,10 +271,12 @@ class Handles(interfaces_plugins.PluginInterface):
def _generator(self, procs):
type_map = self.get_type_map(
context = self.context, layer_name = self.config["primary"], symbol_table = self.config["nt_symbols"])
cookie = self.find_cookie(
context = self.context, layer_name = self.config["primary"], symbol_table = self.config["nt_symbols"])
type_map = self.get_type_map(context = self.context,
layer_name = self.config["primary"],
symbol_table = self.config["nt_symbols"])
cookie = self.find_cookie(context = self.context,
layer_name = self.config["primary"],
symbol_table = self.config["nt_symbols"])
for proc in procs:
@@ -321,8 +331,7 @@ class Handles(interfaces_plugins.PluginInterface):
("HandleValue", format_hints.Hex), ("Type", str),
("GrantedAccess", format_hints.Hex), ("Name", str)],
self._generator(
pslist.PsList.list_processes(
self.context,
self.config['primary'],
self.config['nt_symbols'],
filter_func = filter_func)))
pslist.PsList.list_processes(self.context,
self.config['primary'],
self.config['nt_symbols'],
filter_func = filter_func)))
+30 -23
View File
@@ -20,8 +20,9 @@ class Info(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols")
]
@@ -57,16 +58,18 @@ class Info(plugins.PluginInterface):
native_types = self.context.symbol_space[self.config["nt_symbols"]].natives
kdbg_table_name = intermed.IntermediateSymbolTable.create(
self.context,
self.config_path,
"windows",
"kdbg",
native_types = native_types,
class_types = extensions.kdbg.class_types)
kdbg_table_name = intermed.IntermediateSymbolTable.create(self.context,
self.config_path,
"windows",
"kdbg",
native_types = native_types,
class_types = extensions.kdbg.class_types)
pe_table_name = intermed.IntermediateSymbolTable.create(
self.context, self.config_path, "windows", "pe", class_types = extensions.pe.class_types)
pe_table_name = intermed.IntermediateSymbolTable.create(self.context,
self.config_path,
"windows",
"pe",
class_types = extensions.pe.class_types)
kvo = virtual_layer.config["kernel_virtual_offset"]
@@ -74,10 +77,9 @@ class Info(plugins.PluginInterface):
kdbg_offset = ntkrnlmp.get_symbol("KdDebuggerDataBlock").address
kdbg = self.context.object(
kdbg_table_name + constants.BANG + "_KDDEBUGGER_DATA64",
offset = kvo + kdbg_offset,
layer_name = virtual_layer_name)
kdbg = self.context.object(kdbg_table_name + constants.BANG + "_KDDEBUGGER_DATA64",
offset = kvo + kdbg_offset,
layer_name = virtual_layer_name)
yield (0, ("Kernel Base", hex(self.config["primary.kernel_virtual_offset"])))
yield (0, ("DTB", hex(self.config["primary.page_map_offset"])))
@@ -94,8 +96,9 @@ class Info(plugins.PluginInterface):
vers_offset = ntkrnlmp.get_symbol("KdVersionBlock").address
vers = ntkrnlmp.object(
object_type = "_DBGKD_GET_VERSION64", layer_name = virtual_layer_name, offset = vers_offset)
vers = ntkrnlmp.object(object_type = "_DBGKD_GET_VERSION64",
layer_name = virtual_layer_name,
offset = vers_offset)
yield (0, ("KdVersionBlock", hex(vers.vol.offset)))
yield (0, ("Major/Minor", "{0}.{1}".format(vers.MajorVersion, vers.MinorVersion)))
@@ -103,8 +106,9 @@ class Info(plugins.PluginInterface):
cpu_count_offset = ntkrnlmp.get_symbol("KeNumberProcessors").address
cpu_count = ntkrnlmp.object(
object_type = "unsigned int", layer_name = virtual_layer_name, offset = cpu_count_offset)
cpu_count = ntkrnlmp.object(object_type = "unsigned int",
layer_name = virtual_layer_name,
offset = cpu_count_offset)
yield (0, ("KeNumberProcessors", str(cpu_count)))
@@ -114,8 +118,10 @@ class Info(plugins.PluginInterface):
else:
kuser_addr = 0xFFFFF78000000000
kuser = ntkrnlmp.object(
object_type = "_KUSER_SHARED_DATA", layer_name = virtual_layer_name, offset = kuser_addr, absolute = True)
kuser = ntkrnlmp.object(object_type = "_KUSER_SHARED_DATA",
layer_name = virtual_layer_name,
offset = kuser_addr,
absolute = True)
yield (0, ("SystemTime", str(kuser.SystemTime.get_time())))
yield (0, ("NtSystemRoot",
@@ -126,8 +132,9 @@ class Info(plugins.PluginInterface):
# yield (0, ("KdDebuggerEnabled", "True" if kuser.KdDebuggerEnabled else "False"))
# yield (0, ("SafeBootMode", "True" if kuser.SafeBootMode else "False"))
dos_header = self.context.object(
pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER", offset = kvo, layer_name = virtual_layer_name)
dos_header = self.context.object(pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
offset = kvo,
layer_name = virtual_layer_name)
nt_header = dos_header.get_nt_header()
@@ -20,11 +20,13 @@ class Malfind(interfaces.plugins.PluginInterface):
def get_requirements(cls):
# Since we're calling the plugin, make sure we have the plugin's requirements
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
requirements.IntRequirement(
name = 'pid', description = "Process ID to include (all other processes are excluded)", optional = True)
requirements.IntRequirement(name = 'pid',
description = "Process ID to include (all other processes are excluded)",
optional = True)
]
@classmethod
@@ -125,8 +127,7 @@ class Malfind(interfaces.plugins.PluginInterface):
("CommitCharge", int), ("PrivateMemory", int), ("Hexdump", format_hints.HexBytes),
("Disasm", interfaces.renderers.Disassembly)],
self._generator(
pslist.PsList.list_processes(
context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func)))
pslist.PsList.list_processes(context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func)))
+21 -16
View File
@@ -26,8 +26,9 @@ class ModDump(interfaces.plugins.PluginInterface):
return [
requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0)),
requirements.PluginRequirement(name = 'modules', plugin = modules.Modules, version = (1, 0, 0)),
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols")
]
@@ -53,15 +54,18 @@ class ModDump(interfaces.plugins.PluginInterface):
seen_ids = [] # type: List[interfaces.objects.ObjectInterface]
filter_func = pslist.PsList.create_pid_filter(pids or [])
for proc in pslist.PsList.list_processes(
context = context, layer_name = layer_name, symbol_table = symbol_table, filter_func = filter_func):
for proc in pslist.PsList.list_processes(context = context,
layer_name = layer_name,
symbol_table = symbol_table,
filter_func = filter_func):
proc_layer_name = proc.add_process_layer()
try:
# create the session space object in the process' own layer.
# not all processes have a valid session pointer.
session_space = context.object(
symbol_table + constants.BANG + "_MM_SESSION_SPACE", layer_name = layer_name, offset = proc.Session)
session_space = context.object(symbol_table + constants.BANG + "_MM_SESSION_SPACE",
layer_name = layer_name,
offset = proc.Session)
if session_space.SessionId in seen_ids:
continue
@@ -101,8 +105,11 @@ class ModDump(interfaces.plugins.PluginInterface):
def _generator(self, mods):
session_layers = list(self.get_session_layers(self.context, self.config['primary'], self.config['nt_symbols']))
pe_table_name = intermed.IntermediateSymbolTable.create(
self.context, self.config_path, "windows", "pe", class_types = pe.class_types)
pe_table_name = intermed.IntermediateSymbolTable.create(self.context,
self.config_path,
"windows",
"pe",
class_types = pe.class_types)
for mod in mods:
try:
@@ -115,10 +122,9 @@ class ModDump(interfaces.plugins.PluginInterface):
result_text = "Cannot find a viable session layer for {0:#x}".format(mod.DllBase)
else:
try:
dos_header = self.context.object(
pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
offset = mod.DllBase,
layer_name = session_layer_name)
dos_header = self.context.object(pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
offset = mod.DllBase,
layer_name = session_layer_name)
filedata = interfaces.plugins.FileInterface("module.{0:#x}.dmp".format(mod.DllBase))
@@ -143,7 +149,6 @@ class ModDump(interfaces.plugins.PluginInterface):
def run(self):
return renderers.TreeGrid([("Base", format_hints.Hex), ("Name", str), ("Result", str)],
self._generator(
modules.Modules.list_modules(
context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'])))
modules.Modules.list_modules(context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'])))
@@ -18,8 +18,9 @@ class ModScan(plugins.PluginInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
]
@@ -19,8 +19,9 @@ class Modules(interfaces.plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols")
]
@@ -18,8 +18,9 @@ class MutantScan(plugins.PluginInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
]
@@ -27,17 +27,22 @@ class ProcDump(interfaces_plugins.PluginInterface):
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
# Since we're calling the plugin, make sure we have the plugin's requirements
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
requirements.IntRequirement(
name = 'pid', description = "Process ID to include (all other processes are excluded)", optional = True)
requirements.IntRequirement(name = 'pid',
description = "Process ID to include (all other processes are excluded)",
optional = True)
]
def _generator(self, procs):
pe_table_name = intermed.IntermediateSymbolTable.create(
self.context, self.config_path, "windows", "pe", class_types = pe.class_types)
pe_table_name = intermed.IntermediateSymbolTable.create(self.context,
self.config_path,
"windows",
"pe",
class_types = pe.class_types)
for proc in procs:
process_name = utility.array_to_string(proc.ImageFileName)
@@ -45,15 +50,13 @@ class ProcDump(interfaces_plugins.PluginInterface):
proc_layer_name = proc.add_process_layer()
try:
peb = self._context.object(
self.config["nt_symbols"] + constants.BANG + "_PEB",
layer_name = proc_layer_name,
offset = proc.Peb)
peb = self._context.object(self.config["nt_symbols"] + constants.BANG + "_PEB",
layer_name = proc_layer_name,
offset = proc.Peb)
dos_header = self.context.object(
pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
offset = peb.ImageBaseAddress,
layer_name = proc_layer_name)
dos_header = self.context.object(pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
offset = peb.ImageBaseAddress,
layer_name = proc_layer_name)
filedata = interfaces_plugins.FileInterface("pid.{0}.{1:#x}.dmp".format(
proc.UniqueProcessId, peb.ImageBaseAddress))
@@ -81,8 +84,7 @@ class ProcDump(interfaces_plugins.PluginInterface):
return renderers.TreeGrid([("PID", int), ("Process", str), ("Result", str)],
self._generator(
pslist.PsList.list_processes(
context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func)))
pslist.PsList.list_processes(context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func)))
+14 -14
View File
@@ -22,17 +22,18 @@ class PsList(plugins.PluginInterface, timeliner.TimeLinerInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
# TODO: Convert this to a ListRequirement so that people can filter on sets of pids
requirements.BooleanRequirement(
name = 'physical',
description = 'Display physical offsets instead of virtual',
default = cls.PHYSICAL_DEFAULT,
optional = True),
requirements.IntRequirement(
name = 'pid', description = "Process ID to include (all other processes are excluded)", optional = True)
requirements.BooleanRequirement(name = 'physical',
description = 'Display physical offsets instead of virtual',
default = cls.PHYSICAL_DEFAULT,
optional = True),
requirements.IntRequirement(name = 'pid',
description = "Process ID to include (all other processes are excluded)",
optional = True)
]
@classmethod
@@ -124,11 +125,10 @@ class PsList(plugins.PluginInterface, timeliner.TimeLinerInterface):
if not isinstance(memory, layers.intel.Intel):
raise TypeError("Primary layer is not an intel layer")
for proc in self.list_processes(
self.context,
self.config['primary'],
self.config['nt_symbols'],
filter_func = self.create_pid_filter([self.config.get('pid', None)])):
for proc in self.list_processes(self.context,
self.config['primary'],
self.config['nt_symbols'],
filter_func = self.create_pid_filter([self.config.get('pid', None)])):
if not self.config.get('physical', self.PHYSICAL_DEFAULT):
offset = proc.vol.offset
@@ -19,8 +19,9 @@ class PsScan(plugins.PluginInterface, timeliner.TimeLinerInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
]
@@ -21,19 +21,21 @@ class HiveList(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
requirements.StringRequirement(
name = 'filter', description = "String to filter hive names returned", optional = True, default = None)
requirements.StringRequirement(name = 'filter',
description = "String to filter hive names returned",
optional = True,
default = None)
]
def _generator(self) -> Iterator[Tuple[int, Tuple[int, str]]]:
for hive in self.list_hive_objects(
context = self.context,
layer_name = self.config["primary"],
symbol_table = self.config["nt_symbols"],
filter_string = self.config.get('filter', None)):
for hive in self.list_hive_objects(context = self.context,
layer_name = self.config["primary"],
symbol_table = self.config["nt_symbols"],
filter_string = self.config.get('filter', None)):
yield (0, (format_hints.Hex(hive.vol.offset), hive.get_name() or ""))
@@ -69,12 +71,11 @@ class HiveList(plugins.PluginInterface):
for hive_offset in hive_offsets:
# Construct the hive
reg_config_path = cls.make_subconfig(
context = context,
base_config_path = base_config_path,
hive_offset = hive_offset,
base_layer = layer_name,
nt_symbols = symbol_table)
reg_config_path = cls.make_subconfig(context = context,
base_config_path = base_config_path,
hive_offset = hive_offset,
base_layer = layer_name,
nt_symbols = symbol_table)
try:
hive = registry.RegistryHive(context, reg_config_path, name = 'hive' + hex(hive_offset))
@@ -19,8 +19,9 @@ class HiveScan(plugins.PluginInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
]
@@ -24,15 +24,20 @@ class PrintKey(interfaces.plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
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.IntRequirement(name = 'offset', description = "Hive Offset", default = None, optional = True),
requirements.StringRequirement(
name = 'key', description = "Key to start from", default = None, optional = True),
requirements.BooleanRequirement(
name = 'recurse', description = 'Recurses through keys', default = False, optional = True)
requirements.StringRequirement(name = 'key',
description = "Key to start from",
default = None,
optional = True),
requirements.BooleanRequirement(name = 'recurse',
description = 'Recurses through keys',
default = False,
optional = True)
]
@classmethod
@@ -134,12 +139,11 @@ class PrintKey(interfaces.plugins.PluginInterface):
key: str = None,
recurse: bool = False):
for hive in hivelist.HiveList.list_hives(
self.context,
self.config_path,
layer_name = layer_name,
symbol_table = symbol_table,
hive_offsets = hive_offsets):
for hive in hivelist.HiveList.list_hives(self.context,
self.config_path,
layer_name = layer_name,
symbol_table = symbol_table,
hive_offsets = hive_offsets):
try:
# Walk it
@@ -164,12 +168,10 @@ class PrintKey(interfaces.plugins.PluginInterface):
def run(self):
offset = self.config.get('offset', None)
return TreeGrid(
columns = [('Last Write Time', datetime.datetime), ('Hive Offset', format_hints.Hex), ('Type', str),
('Key', str), ('Name', str), ('Data', str), ('Volatile', bool)],
generator = self._registry_walker(
self.config['primary'],
self.config['nt_symbols'],
hive_offsets = None if offset is None else [offset],
key = self.config.get('key', None),
recurse = self.config.get('recurse', None)))
return TreeGrid(columns = [('Last Write Time', datetime.datetime), ('Hive Offset', format_hints.Hex),
('Type', str), ('Key', str), ('Name', str), ('Data', str), ('Volatile', bool)],
generator = self._registry_walker(self.config['primary'],
self.config['nt_symbols'],
hive_offsets = None if offset is None else [offset],
key = self.config.get('key', None),
recurse = self.config.get('recurse', None)))
@@ -36,8 +36,9 @@ class UserAssist(interfaces.plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
requirements.IntRequirement(name = 'offset', description = "Hive Offset", default = None, optional = True),
requirements.PluginRequirement(name = 'hivelist', plugin = hivelist.HiveList, version = (1, 0, 0))
@@ -130,8 +131,8 @@ class UserAssist(interfaces.plugins.PluginInterface):
self._determine_userassist_type()
userassist_node_path = hive.get_key(
"software\\microsoft\\windows\\currentversion\\explorer\\userassist", return_list = True)
userassist_node_path = hive.get_key("software\\microsoft\\windows\\currentversion\\explorer\\userassist",
return_list = True)
if not userassist_node_path:
vollog.warning("list_userassist did not find a valid node_path (or None)")
@@ -215,13 +216,12 @@ class UserAssist(interfaces.plugins.PluginInterface):
hive_offsets = [self.config.get('offset', None)]
# get all the user hive offsets or use the one specified
for hive in hivelist.HiveList.list_hives(
context = self.context,
base_config_path = self.config_path,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_string = 'ntuser.dat',
hive_offsets = hive_offsets):
for hive in hivelist.HiveList.list_hives(context = self.context,
base_config_path = self.config_path,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_string = 'ntuser.dat',
hive_offsets = hive_offsets):
try:
yield from self.list_userassist(hive)
continue
+13 -9
View File
@@ -24,8 +24,9 @@ class SSDT(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
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 = 'modules', plugin = modules.Modules, version = (1, 0, 0)),
]
@@ -61,8 +62,12 @@ class SSDT(plugins.PluginInterface):
if module_name in windows_constants.KERNEL_MODULE_NAMES:
symbol_table_name = symbol_table
context_module = contexts.SizedModule(
context, module_name, layer_name, mod.DllBase, mod.SizeOfImage, symbol_table_name = symbol_table_name)
context_module = contexts.SizedModule(context,
module_name,
layer_name,
mod.DllBase,
mod.SizeOfImage,
symbol_table_name = symbol_table_name)
context_modules.append(context_module)
@@ -102,11 +107,10 @@ class SSDT(plugins.PluginInterface):
find_address = passthrough
functions = ntkrnlmp.object(
object_type = "array",
offset = service_table_address,
subtype = ntkrnlmp.get_type(array_subtype),
count = service_limit)
functions = ntkrnlmp.object(object_type = "array",
offset = service_table_address,
subtype = ntkrnlmp.get_type(array_subtype),
count = service_limit)
for idx, function_obj in enumerate(functions):
@@ -21,8 +21,9 @@ class Strings(interfaces.plugins.PluginInterface):
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0)),
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
requirements.URIRequirement(name = "strings_file", description = "Strings file")
]
+40 -44
View File
@@ -21,33 +21,34 @@ class SvcScan(interfaces.plugins.PluginInterface):
_version = (1, 0, 0)
is_vista_or_later = poolscanner.os_distinguisher(
version_check = lambda x: x >= (6, 0), fallback_checks = [("KdCopyDataBlock", None, True)])
is_vista_or_later = poolscanner.os_distinguisher(version_check = lambda x: x >= (6, 0),
fallback_checks = [("KdCopyDataBlock", None, True)])
is_windows_xp = poolscanner.os_distinguisher(
version_check = lambda x: (5, 1) <= x < (5, 2),
fallback_checks = [("KdCopyDataBlock", None, False), ("_HANDLE_TABLE", "HandleCount", True)])
is_windows_xp = poolscanner.os_distinguisher(version_check = lambda x: (5, 1) <= x < (5, 2),
fallback_checks = [("KdCopyDataBlock", None, False),
("_HANDLE_TABLE", "HandleCount", True)])
is_xp_or_2003 = poolscanner.os_distinguisher(
version_check = lambda x: (5, 1) <= x < (6, 0),
fallback_checks = [("KdCopyDataBlock", None, False), ("_HANDLE_TABLE", "HandleCount", True)])
is_xp_or_2003 = poolscanner.os_distinguisher(version_check = lambda x: (5, 1) <= x < (6, 0),
fallback_checks = [("KdCopyDataBlock", None, False),
("_HANDLE_TABLE", "HandleCount", True)])
is_win10_up_to_15063 = poolscanner.os_distinguisher(
version_check = lambda x: (10, 0) <= x < (10, 0, 16299),
fallback_checks = [("ObHeaderCookie", None, True), ("_HANDLE_TABLE", "HandleCount", False),
("ObHeaderCookie", None, True)])
is_win10_up_to_15063 = poolscanner.os_distinguisher(version_check = lambda x: (10, 0) <= x < (10, 0, 16299),
fallback_checks = [("ObHeaderCookie", None, True),
("_HANDLE_TABLE", "HandleCount", False),
("ObHeaderCookie", None, True)])
is_win10_16299_or_later = poolscanner.os_distinguisher(
version_check = lambda x: x >= (10, 0, 16299),
fallback_checks = [("ObHeaderCookie", None, True), ("_HANDLE_TABLE", "HandleCount", False),
("ObHeaderCookie", None, True)])
is_win10_16299_or_later = poolscanner.os_distinguisher(version_check = lambda x: x >= (10, 0, 16299),
fallback_checks = [("ObHeaderCookie", None, True),
("_HANDLE_TABLE", "HandleCount", False),
("ObHeaderCookie", None, True)])
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
# Since we're calling the plugin, make sure we have the plugin's requirements
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
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 = 'pslist', plugin = pslist.PsList, version = (1, 0, 0)),
requirements.PluginRequirement(name = 'poolscanner', plugin = poolscanner.PoolScanner, version = (1, 0, 0)),
@@ -82,8 +83,8 @@ class SvcScan(interfaces.plugins.PluginInterface):
symbol_filename = "services-xp-2003-x64"
elif poolscanner.PoolScanner.is_windows_8_or_later(context = context, symbol_table = symbol_table) and is_64bit:
symbol_filename = "services-win8-x64"
elif poolscanner.PoolScanner.is_windows_8_or_later(
context = context, symbol_table = symbol_table) and not is_64bit:
elif poolscanner.PoolScanner.is_windows_8_or_later(context = context,
symbol_table = symbol_table) and not is_64bit:
symbol_filename = "services-win8-x86"
elif SvcScan.is_win10_up_to_15063(context = context, symbol_table = symbol_table) and is_64bit:
symbol_filename = "services-win10-15063-x64"
@@ -100,13 +101,12 @@ class SvcScan(interfaces.plugins.PluginInterface):
else:
raise NotImplementedError("This version of Windows is not supported!")
return intermed.IntermediateSymbolTable.create(
context,
config_path,
"windows",
symbol_filename,
class_types = services.class_types,
native_types = native_types)
return intermed.IntermediateSymbolTable.create(context,
config_path,
"windows",
symbol_filename,
class_types = services.class_types,
native_types = native_types)
def _generator(self):
@@ -126,35 +126,31 @@ class SvcScan(interfaces.plugins.PluginInterface):
seen = []
for task in pslist.PsList.list_processes(
context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func):
for task in pslist.PsList.list_processes(context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func):
proc_layer_name = task.add_process_layer()
layer = self.context.layers[proc_layer_name]
for offset in layer.scan(
context = self.context,
scanner = scanners.BytesScanner(needle = service_tag),
sections = vadyarascan.VadYaraScan.get_vad_maps(task)):
for offset in layer.scan(context = self.context,
scanner = scanners.BytesScanner(needle = service_tag),
sections = vadyarascan.VadYaraScan.get_vad_maps(task)):
if not is_vista_or_later:
service_record = self.context.object(
service_table_name + constants.BANG + "_SERVICE_RECORD",
offset = offset - relative_tag_offset,
layer_name = proc_layer_name)
service_record = self.context.object(service_table_name + constants.BANG + "_SERVICE_RECORD",
offset = offset - relative_tag_offset,
layer_name = proc_layer_name)
if not service_record.is_valid():
continue
yield (0, self.get_record_tuple(service_record))
else:
service_header = self.context.object(
service_table_name + constants.BANG + "_SERVICE_HEADER",
offset = offset,
layer_name = proc_layer_name)
service_header = self.context.object(service_table_name + constants.BANG + "_SERVICE_HEADER",
offset = offset,
layer_name = proc_layer_name)
if not service_header.is_valid():
continue
@@ -18,8 +18,9 @@ class SymlinkScan(plugins.PluginInterface, timeliner.TimeLinerInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
]
@@ -79,8 +79,7 @@ class VadDump(interfaces_plugins.PluginInterface):
return renderers.TreeGrid([("PID", int), ("Process", str), ("Result", str)],
self._generator(
pslist.PsList.list_processes(
context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func)))
pslist.PsList.list_processes(context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func)))
@@ -126,8 +126,7 @@ class VadInfo(interfaces.plugins.PluginInterface):
("Protection", str), ("CommitCharge", int), ("PrivateMemory", int),
("Parent", format_hints.Hex), ("File", str)],
self._generator(
pslist.PsList.list_processes(
context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func)))
pslist.PsList.list_processes(context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func)))
@@ -26,22 +26,26 @@ class VadYaraScan(interfaces.plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = "Memory layer for the kernel", architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = "Memory layer for the kernel",
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
requirements.BooleanRequirement(
name = "wide", description = "Match wide (unicode) strings", default = False, optional = True),
requirements.StringRequirement(
name = "yara_rules", description = "Yara rules (as a string)", optional = True),
requirements.BooleanRequirement(name = "wide",
description = "Match wide (unicode) strings",
default = False,
optional = True),
requirements.StringRequirement(name = "yara_rules",
description = "Yara rules (as a string)",
optional = True),
requirements.URIRequirement(name = "yara_file", description = "Yara rules (as a file)", optional = True),
requirements.IntRequirement(
name = "max_size",
default = 0x40000000,
description = "Set the maximum size (default is 1GB)",
optional = True),
requirements.IntRequirement(name = "max_size",
default = 0x40000000,
description = "Set the maximum size (default is 1GB)",
optional = True),
requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0)),
requirements.IntRequirement(
name = 'pid', description = "Process ID to include (all other processes are excluded)", optional = True)
requirements.IntRequirement(name = 'pid',
description = "Process ID to include (all other processes are excluded)",
optional = True)
]
def _generator(self):
@@ -64,15 +68,13 @@ class VadYaraScan(interfaces.plugins.PluginInterface):
filter_func = pslist.PsList.create_pid_filter([self.config.get('pid', None)])
for task in pslist.PsList.list_processes(
context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func):
for offset, name in layer.scan(
context = self.context,
scanner = yarascan.YaraScanner(rules = rules),
sections = self.get_vad_maps(task)):
for task in pslist.PsList.list_processes(context = self.context,
layer_name = self.config['primary'],
symbol_table = self.config['nt_symbols'],
filter_func = filter_func):
for offset, name in layer.scan(context = self.context,
scanner = yarascan.YaraScanner(rules = rules),
sections = self.get_vad_maps(task)):
yield format_hints.Hex(offset), name
@staticmethod
@@ -34,8 +34,9 @@ class VerInfo(interfaces_plugins.PluginInterface):
## TODO: and we don't want any CLI options from pslist, modules, or moddump
return [
requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (1, 0, 0)),
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"),
]
@@ -56,8 +57,9 @@ class VerInfo(interfaces_plugins.PluginInterface):
pe_data = io.BytesIO()
dos_header = context.object(
pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER", offset = base_address, layer_name = layer_name)
dos_header = context.object(pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
offset = base_address,
layer_name = layer_name)
for offset, data in dos_header.reconstruct():
pe_data.seek(offset)
@@ -94,8 +96,11 @@ class VerInfo(interfaces_plugins.PluginInterface):
session_layers: <generator> of layers in the session to be checked
"""
pe_table_name = intermed.IntermediateSymbolTable.create(
self.context, self.config_path, "windows", "pe", class_types = extensions.pe.class_types)
pe_table_name = intermed.IntermediateSymbolTable.create(self.context,
self.config_path,
"windows",
"pe",
class_types = extensions.pe.class_types)
for mod in mods:
try:
@@ -136,9 +141,10 @@ class VerInfo(interfaces_plugins.PluginInterface):
(major, minor, product, build) = [renderers.UnreadableValue()] * 4
yield (0, (proc.UniqueProcessId,
proc.ImageFileName.cast(
"string", max_length = proc.ImageFileName.vol.count, errors = "replace"),
format_hints.Hex(entry.DllBase), BaseDllName, major, minor, product, build))
proc.ImageFileName.cast("string",
max_length = proc.ImageFileName.vol.count,
errors = "replace"), format_hints.Hex(entry.DllBase), BaseDllName,
major, minor, product, build))
def run(self):
procs = pslist.PsList.list_processes(self.context, self.config["primary"], self.config["nt_symbols"])
+19 -15
View File
@@ -23,8 +23,9 @@ class VirtMap(interfaces.plugins.PluginInterface):
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
# Since we're calling the plugin, make sure we have the plugin's requirements
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols")
]
@@ -50,30 +51,32 @@ class VirtMap(interfaces.plugins.PluginInterface):
if module.has_symbol('MiVisibleState'):
symbol = module.get_symbol('MiVisibleState')
visible_state = module.object(
object_type = 'pointer', offset = symbol.address,
subtype = module.get_type('_MI_VISIBLE_STATE')).dereference()
visible_state = module.object(object_type = 'pointer',
offset = symbol.address,
subtype = module.get_type('_MI_VISIBLE_STATE')).dereference()
if hasattr(visible_state, 'SystemVaRegions'):
for i in range(visible_state.SystemVaRegions.count):
lookup = system_va_type.lookup(i)
region_range = result.get(lookup, [])
region_range.append((visible_state.SystemVaRegions[i].BaseAddress,
visible_state.SystemVaRegions[i].NumberOfBytes))
region_range.append(
(visible_state.SystemVaRegions[i].BaseAddress, visible_state.SystemVaRegions[i].NumberOfBytes))
result[lookup] = region_range
elif hasattr(visible_state, 'SystemVaType'):
system_range_start = module.object(
object_type = "pointer", offset = module.get_symbol("MmSystemRangeStart").address)
system_range_start = module.object(object_type = "pointer",
offset = module.get_symbol("MmSystemRangeStart").address)
result = cls._enumerate_system_va_type(large_page_size, system_range_start, module,
visible_state.SystemVaType)
else:
raise exceptions.SymbolError("Required structures not found")
elif module.has_symbol('MiSystemVaType'):
system_range_start = module.object(
object_type = "pointer", offset = module.get_symbol("MmSystemRangeStart").address)
system_range_start = module.object(object_type = "pointer",
offset = module.get_symbol("MmSystemRangeStart").address)
symbol = module.get_symbol('MiSystemVaType')
array_count = (0xFFFFFFFF + 1 - system_range_start) // large_page_size
type_array = module.object(
object_type = 'array', offset = symbol.address, count = array_count, subtype = module.get_type('char'))
type_array = module.object(object_type = 'array',
offset = symbol.address,
count = array_count,
subtype = module.get_type('char'))
result = cls._enumerate_system_va_type(large_page_size, system_range_start, module, type_array)
else:
@@ -114,8 +117,9 @@ class VirtMap(interfaces.plugins.PluginInterface):
def run(self):
layer = self.context.layers[self.config['primary']]
module = self.context.module(
self.config['nt_symbols'], layer_name = layer.name, offset = layer.config['kernel_virtual_offset'])
module = self.context.module(self.config['nt_symbols'],
layer_name = layer.name,
offset = layer.config['kernel_virtual_offset'])
return renderers.TreeGrid([("Region", str), ("Start offset", format_hints.Hex),
("End offset", format_hints.Hex)],
+26 -20
View File
@@ -40,27 +40,33 @@ class YaraScan(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = "Memory layer for the kernel", architectures = ["Intel32", "Intel64"]),
requirements.BooleanRequirement(
name = "all", description = "Scan both process and kernel memory", default = False, optional = True),
requirements.BooleanRequirement(
name = "insensitive",
description = "Makes the search case insensitive",
default = False,
optional = True),
requirements.BooleanRequirement(
name = "kernel", description = "Scan kernel modules", default = False, optional = True),
requirements.BooleanRequirement(
name = "wide", description = "Match wide (unicode) strings", default = False, optional = True),
requirements.StringRequirement(
name = "yara_rules", description = "Yara rules (as a string)", optional = True),
requirements.TranslationLayerRequirement(name = 'primary',
description = "Memory layer for the kernel",
architectures = ["Intel32", "Intel64"]),
requirements.BooleanRequirement(name = "all",
description = "Scan both process and kernel memory",
default = False,
optional = True),
requirements.BooleanRequirement(name = "insensitive",
description = "Makes the search case insensitive",
default = False,
optional = True),
requirements.BooleanRequirement(name = "kernel",
description = "Scan kernel modules",
default = False,
optional = True),
requirements.BooleanRequirement(name = "wide",
description = "Match wide (unicode) strings",
default = False,
optional = True),
requirements.StringRequirement(name = "yara_rules",
description = "Yara rules (as a string)",
optional = True),
requirements.URIRequirement(name = "yara_file", description = "Yara rules (as a file)", optional = True),
requirements.IntRequirement(
name = "max_size",
default = 0x40000000,
description = "Set the maximum size (default is 1GB)",
optional = True)
requirements.IntRequirement(name = "max_size",
default = 0x40000000,
description = "Set the maximum size (default is 1GB)",
optional = True)
]
def _generator(self):
+4 -5
View File
@@ -245,11 +245,10 @@ def mask_symbol_table(symbol_table: interfaces.symbols.SymbolTableInterface,
# This is speedy, but may not be very efficient from a memory perspective
if symbol in cached_symbols:
return cached_symbols[symbol]
new_symbol = interfaces.symbols.SymbolInterface(
name = symbol.name,
address = address_mask & (symbol.address + table_aslr_shift),
type = symbol.type,
constant_data = symbol.constant_data)
new_symbol = interfaces.symbols.SymbolInterface(name = symbol.name,
address = address_mask & (symbol.address + table_aslr_shift),
type = symbol.type,
constant_data = symbol.constant_data)
cached_symbols[symbol] = new_symbol
return new_symbol
+32 -34
View File
@@ -118,13 +118,12 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface):
table_mapping)
# Inherit
super().__init__(
context,
config_path,
name,
native_types or self._delegate.natives,
table_mapping = table_mapping,
class_types = class_types)
super().__init__(context,
config_path,
name,
native_types or self._delegate.natives,
table_mapping = table_mapping,
class_types = class_types)
@staticmethod
def _closest_version(version: str, versions: Dict[Tuple[int, int, int], Type['ISFormatTable']]) \
@@ -227,14 +226,13 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface):
if not urls:
raise ValueError("No symbol files found at provided filename: {}", filename)
table_name = context.symbol_space.free_table_name(filename)
table = cls(
context = context,
config_path = config_path,
name = table_name,
isf_url = urls[0],
native_types = native_types,
table_mapping = table_mapping,
class_types = class_types)
table = cls(context = context,
config_path = config_path,
name = table_name,
isf_url = urls[0],
native_types = native_types,
table_mapping = table_mapping,
class_types = class_types)
context.symbol_space.append(table)
return table_name
@@ -411,11 +409,10 @@ class Version1Format(ISFormatTable):
curdict = self._json_object['enums'][enum_name]
base_type = self.natives.get_type(curdict['base'])
# The size isn't actually used, the base-type defines it.
return objects.templates.ObjectTemplate(
type_name = self.name + constants.BANG + enum_name,
object_class = objects.Enumeration,
base_type = base_type,
choices = curdict['constants'])
return objects.templates.ObjectTemplate(type_name = self.name + constants.BANG + enum_name,
object_class = objects.Enumeration,
base_type = base_type,
choices = curdict['constants'])
def get_type(self, type_name: str) -> interfaces.objects.Template:
"""Resolves an individual symbol."""
@@ -435,11 +432,10 @@ class Version1Format(ISFormatTable):
for clazz in objects.AggregateTypes:
if objects.AggregateTypes[clazz] == curdict['kind']:
object_class = clazz
return objects.templates.ObjectTemplate(
type_name = self.name + constants.BANG + type_name,
object_class = object_class,
size = curdict['length'],
members = members)
return objects.templates.ObjectTemplate(type_name = self.name + constants.BANG + type_name,
object_class = object_class,
size = curdict['length'],
members = members)
class Version2Format(Version1Format):
@@ -485,11 +481,10 @@ class Version2Format(Version1Format):
for clazz in objects.AggregateTypes:
if objects.AggregateTypes[clazz] == curdict['kind']:
object_class = clazz
return objects.templates.ObjectTemplate(
type_name = self.name + constants.BANG + type_name,
object_class = object_class,
size = curdict['size'],
members = members)
return objects.templates.ObjectTemplate(type_name = self.name + constants.BANG + type_name,
object_class = object_class,
size = curdict['size'],
members = members)
class Version3Format(Version2Format):
@@ -506,8 +501,9 @@ class Version3Format(Version2Format):
symbol_type = None
if 'type' in symbol:
symbol_type = self._interdict_to_template(symbol['type'])
self._symbol_cache[name] = interfaces.symbols.SymbolInterface(
name = name, address = symbol['address'], type = symbol_type)
self._symbol_cache[name] = interfaces.symbols.SymbolInterface(name = name,
address = symbol['address'],
type = symbol_type)
return self._symbol_cache[name]
@@ -560,8 +556,10 @@ class Version5Format(Version4Format):
symbol_constant_data = None
if 'constant_data' in symbol:
symbol_constant_data = base64.b64decode(symbol.get('constant_data'))
self._symbol_cache[name] = interfaces.symbols.SymbolInterface(
name = name, address = symbol['address'], type = symbol_type, constant_data = symbol_constant_data)
self._symbol_cache[name] = interfaces.symbols.SymbolInterface(name = name,
address = symbol['address'],
type = symbol_type,
constant_data = symbol_constant_data)
return self._symbol_cache[name]
@@ -21,4 +21,3 @@ class MacKernelIntermedSymbols(intermed.IntermediateSymbolTable):
self.set_type_class('socket', extensions.socket)
self.set_type_class('inpcb', extensions.inpcb)
self.set_type_class('queue_entry', extensions.queue_entry)
@@ -256,10 +256,9 @@ class vm_map_entry(objects.StructType):
break
if found:
vpager = context.object(
config_prefix + constants.BANG + "vnode_pager",
layer_name = vnode_object.vol.layer_name,
offset = vnode_object.pager)
vpager = context.object(config_prefix + constants.BANG + "vnode_pager",
layer_name = vnode_object.vol.layer_name,
offset = vnode_object.pager)
ret = vpager.vnode_handle
else:
ret = None
@@ -48,11 +48,10 @@ class _POOL_HEADER(objects.StructType):
# if there is no object type, then just instantiate a structure
if object_type is None:
mem_object = self._context.object(
symbol_table_name + constants.BANG + type_name,
layer_name = self.vol.layer_name,
offset = self.vol.offset + pool_header_size,
native_layer_name = native_layer_name)
mem_object = self._context.object(symbol_table_name + constants.BANG + type_name,
layer_name = self.vol.layer_name,
offset = self.vol.offset + pool_header_size,
native_layer_name = native_layer_name)
return mem_object
# otherwise we have an executive object in the pool
@@ -72,11 +71,10 @@ class _POOL_HEADER(objects.StructType):
end_offset = start_offset + min(max_optional_headers_length, self.BlockSize * alignment)
for addr in range(start_offset, end_offset, alignment):
object_header = self._context.object(
symbol_table_name + constants.BANG + "_OBJECT_HEADER",
layer_name = self.vol.layer_name,
offset = addr,
native_layer_name = native_layer_name)
object_header = self._context.object(symbol_table_name + constants.BANG + "_OBJECT_HEADER",
layer_name = self.vol.layer_name,
offset = addr,
native_layer_name = native_layer_name)
if not object_header.is_valid():
continue
@@ -97,11 +95,10 @@ class _POOL_HEADER(objects.StructType):
type_size = self._context.symbol_space.get_type(symbol_table_name + constants.BANG + type_name).size
rounded_size = conversion.round(type_size, alignment, up = True)
mem_object = self._context.object(
symbol_table_name + constants.BANG + type_name,
layer_name = self.vol.layer_name,
offset = self.vol.offset + self.BlockSize * alignment - rounded_size,
native_layer_name = native_layer_name)
mem_object = self._context.object(symbol_table_name + constants.BANG + type_name,
layer_name = self.vol.layer_name,
offset = self.vol.offset + self.BlockSize * alignment - rounded_size,
native_layer_name = native_layer_name)
object_header = mem_object.object_header()
@@ -144,12 +141,11 @@ class _MMVAD_SHORT(objects.StructType):
try:
# TODO: instantiate a _POOL_HEADER and return PoolTag
bytesobj = self._context.object(
symbol_table_name + constants.BANG + "bytes",
layer_name = self.vol.layer_name,
offset = vad_address,
native_layer_name = self.vol.native_layer_name,
length = 4)
bytesobj = self._context.object(symbol_table_name + constants.BANG + "bytes",
layer_name = self.vol.layer_name,
offset = vad_address,
native_layer_name = self.vol.native_layer_name,
length = 4)
return bytesobj.decode()
except exceptions.InvalidAddressException:
@@ -401,11 +397,10 @@ class _EX_FAST_REF(objects.StructType):
else:
max_fast_ref = 15
return self._context.object(
symbol_table_name + constants.BANG + "pointer",
layer_name = self.vol.layer_name,
offset = self.Object & ~max_fast_ref,
native_layer_name = self.vol.native_layer_name)
return self._context.object(symbol_table_name + constants.BANG + "pointer",
layer_name = self.vol.layer_name,
offset = self.Object & ~max_fast_ref,
native_layer_name = self.vol.native_layer_name)
class ExecutiveObject(interfaces.objects.ObjectInterface):
@@ -418,11 +413,10 @@ class ExecutiveObject(interfaces.objects.ObjectInterface):
symbol_table_name = self.vol.type_name.split(constants.BANG)[0]
body_offset = self._context.symbol_space.get_type(symbol_table_name + constants.BANG +
"_OBJECT_HEADER").relative_child_offset("Body")
return self._context.object(
symbol_table_name + constants.BANG + "_OBJECT_HEADER",
layer_name = self.vol.layer_name,
offset = self.vol.offset - body_offset,
native_layer_name = self.vol.native_layer_name)
return self._context.object(symbol_table_name + constants.BANG + "_OBJECT_HEADER",
layer_name = self.vol.layer_name,
offset = self.vol.offset - body_offset,
native_layer_name = self.vol.native_layer_name)
class _DEVICE_OBJECT(objects.StructType, ExecutiveObject):
@@ -556,16 +550,14 @@ class _OBJECT_HEADER(objects.StructType):
address = ntkrnlmp.get_symbol("ObpInfoMaskToOffset").address
calculated_index = self.InfoMask & (name_info_bit | (name_info_bit - 1))
header_offset = self._context.object(
symbol_table_name + constants.BANG + "unsigned char",
layer_name = self.vol.native_layer_name,
offset = kvo + address + calculated_index)
header_offset = self._context.object(symbol_table_name + constants.BANG + "unsigned char",
layer_name = self.vol.native_layer_name,
offset = kvo + address + calculated_index)
header = self._context.object(
symbol_table_name + constants.BANG + "_OBJECT_HEADER_NAME_INFO",
layer_name = self.vol.layer_name,
offset = self.vol.offset - header_offset,
native_layer_name = self.vol.native_layer_name)
header = self._context.object(symbol_table_name + constants.BANG + "_OBJECT_HEADER_NAME_INFO",
layer_name = self.vol.layer_name,
offset = self.vol.offset - header_offset,
native_layer_name = self.vol.native_layer_name)
return header
@@ -584,8 +576,10 @@ class _UNICODE_STRING(objects.StructType):
# We explicitly do *not* catch errors here, we allow an exception to be thrown
# (otherwise there's no way to determine anything went wrong)
# It's up to the user of this method to catch exceptions
return self.Buffer.dereference().cast(
"string", max_length = self.Length, errors = "replace", encoding = "utf16")
return self.Buffer.dereference().cast("string",
max_length = self.Length,
errors = "replace",
encoding = "utf16")
String = property(get_string)
@@ -664,8 +658,9 @@ class _EPROCESS(generic.GenericIntelProcess, ExecutiveObject):
return
sym_table = self.vol.type_name.split(constants.BANG)[0]
peb = self._context.object(
"{}{}_PEB".format(sym_table, constants.BANG), layer_name = proc_layer_name, offset = self.Peb)
peb = self._context.object("{}{}_PEB".format(sym_table, constants.BANG),
layer_name = proc_layer_name,
offset = self.Peb)
for entry in peb.Ldr.InLoadOrderModuleList.to_list(
"{}{}_LDR_DATA_TABLE_ENTRY".format(sym_table, constants.BANG), "InLoadOrderLinks"):
@@ -691,11 +686,10 @@ class _EPROCESS(generic.GenericIntelProcess, ExecutiveObject):
symbol_table_name = self.get_symbol_table().name
kvo = self._context.layers[self.vol.native_layer_name].config['kernel_virtual_offset']
ntkrnlmp = self._context.module(
symbol_table_name,
layer_name = self.vol.native_layer_name,
offset = kvo,
native_layer_name = self.vol.native_layer_name)
ntkrnlmp = self._context.module(symbol_table_name,
layer_name = self.vol.native_layer_name,
offset = kvo,
native_layer_name = self.vol.native_layer_name)
session = ntkrnlmp.object(object_type = "_MM_SESSION_SPACE", offset = self.Session, absolute = True)
if session.has_member("SessionId"):
@@ -766,20 +760,18 @@ class _LIST_ENTRY(objects.StructType, collections.abc.Iterable):
link = getattr(self, direction).dereference()
if not sentinel:
yield self._context.object(
symbol_type,
layer,
offset = self.vol.offset - relative_offset,
native_layer_name = layer or self.vol.native_layer_name)
yield self._context.object(symbol_type,
layer,
offset = self.vol.offset - relative_offset,
native_layer_name = layer or self.vol.native_layer_name)
seen = {self.vol.offset}
while link.vol.offset not in seen:
obj = self._context.object(
symbol_type,
layer,
offset = link.vol.offset - relative_offset,
native_layer_name = layer or self.vol.native_layer_name)
obj = self._context.object(symbol_type,
layer,
offset = link.vol.offset - relative_offset,
native_layer_name = layer or self.vol.native_layer_name)
yield obj
seen.add(link.vol.offset)
@@ -14,12 +14,11 @@ class _KDDEBUGGER_DATA64(objects.StructType):
layer_name = self.vol.layer_name
symbol_table_name = self.get_symbol_table().name
return self._context.object(
symbol_table_name + constants.BANG + "string",
layer_name = layer_name,
offset = self.NtBuildLab,
max_length = 32,
errors = "replace")
return self._context.object(symbol_table_name + constants.BANG + "string",
layer_name = layer_name,
offset = self.NtBuildLab,
max_length = 32,
errors = "replace")
def get_csdversion(self):
"""Returns the CSDVersion as an integer (i.e. Service Pack number)"""
@@ -27,8 +26,9 @@ class _KDDEBUGGER_DATA64(objects.StructType):
layer_name = self.vol.layer_name
symbol_table_name = self.get_symbol_table().name
csdresult = self._context.object(
symbol_table_name + constants.BANG + "unsigned long", layer_name = layer_name, offset = self.CmNtCSDVersion)
csdresult = self._context.object(symbol_table_name + constants.BANG + "unsigned long",
layer_name = layer_name,
offset = self.CmNtCSDVersion)
return (csdresult >> 8) & 0xffffffff
@@ -25,10 +25,9 @@ class _IMAGE_DOS_HEADER(objects.StructType):
layer_name = self.vol.layer_name
symbol_table_name = self.get_symbol_table().name
nt_header = self._context.object(
symbol_table_name + constants.BANG + "_IMAGE_NT_HEADERS",
layer_name = layer_name,
offset = self.vol.offset + self.e_lfanew)
nt_header = self._context.object(symbol_table_name + constants.BANG + "_IMAGE_NT_HEADERS",
layer_name = layer_name,
offset = self.vol.offset + self.e_lfanew)
if nt_header.Signature != 0x4550:
raise ValueError("NT header signature {0:04X} is not a valid".format(nt_header.Signature))
@@ -163,10 +162,9 @@ class _IMAGE_NT_HEADERS(objects.StructType):
for i in range(self.FileHeader.NumberOfSections):
sect_addr = start_addr + (i * sect_header_size)
yield self._context.object(
symbol_table_name + constants.BANG + "_IMAGE_SECTION_HEADER",
offset = sect_addr,
layer_name = layer_name)
yield self._context.object(symbol_table_name + constants.BANG + "_IMAGE_SECTION_HEADER",
offset = sect_addr,
layer_name = layer_name)
class_types = {
@@ -119,8 +119,10 @@ class _CM_KEY_BODY(objects.StructType):
break
output.append(
kcb.NameBlock.Name.cast(
"string", encoding = "utf8", max_length = kcb.NameBlock.NameLength, errors = "replace"))
kcb.NameBlock.Name.cast("string",
encoding = "utf8",
max_length = kcb.NameBlock.NameLength,
errors = "replace"))
kcb = kcb.ParentKcb
return "\\".join(reversed(output))
@@ -8,6 +8,7 @@ from volatility.framework.symbols.wrappers import Flags
from volatility.framework import renderers
from typing import Union
class _SERVICE_RECORD(objects.StructType):
"""A service record structure."""
@@ -112,6 +113,7 @@ class _SERVICE_RECORD(objects.StructType):
except exceptions.InvalidAddressException:
raise StopIteration
class _SERVICE_HEADER(objects.StructType):
"""A service header structure."""
@@ -122,7 +124,5 @@ class _SERVICE_HEADER(objects.StructType):
except exceptions.InvalidAddressException:
return False
class_types = {
'_SERVICE_RECORD': _SERVICE_RECORD,
'_SERVICE_HEADER': _SERVICE_HEADER
}
class_types = {'_SERVICE_RECORD': _SERVICE_RECORD, '_SERVICE_HEADER': _SERVICE_HEADER}
+31 -24
View File
@@ -404,10 +404,9 @@ class PdbReader:
section_orig_layer_name = self._layer_name + "_stream" + str(self._dbidbgheader.snSectionHdrOrig)
consumed, length = 0, self.context.layers[section_orig_layer_name].maximum_address
while consumed < length:
section = self.context.object(
dbi_layer.pdb_symbol_table + constants.BANG + "IMAGE_SECTION_HEADER",
offset = consumed,
layer_name = section_orig_layer_name)
section = self.context.object(dbi_layer.pdb_symbol_table + constants.BANG + "IMAGE_SECTION_HEADER",
offset = consumed,
layer_name = section_orig_layer_name)
self._sections.append(section)
consumed += section.vol.size
@@ -417,16 +416,16 @@ class PdbReader:
data = self.context.layers[omap_layer_name].read(0, length)
# For speed we don't use the framework to read this (usually sizeable) data
for i in range(0, length, 8):
self._omap_mapping.append((int.from_bytes(data[i:i + 4], byteorder = 'little'),
int.from_bytes(data[i + 4:i + 8], byteorder = 'little')))
self._omap_mapping.append(
(int.from_bytes(data[i:i + 4],
byteorder = 'little'), int.from_bytes(data[i + 4:i + 8], byteorder = 'little')))
elif self._dbidbgheader.snSectionHdr != -1:
section_layer_name = self._layer_name + "_stream" + str(self._dbidbgheader.snSectionHdr)
consumed, length = 0, self.context.layers[section_layer_name].maximum_address
while consumed < length:
section = self.context.object(
dbi_layer.pdb_symbol_table + constants.BANG + "IMAGE_SECTION_HEADER",
offset = consumed,
layer_name = section_layer_name)
section = self.context.object(dbi_layer.pdb_symbol_table + constants.BANG + "IMAGE_SECTION_HEADER",
offset = consumed,
layer_name = section_layer_name)
self._sections.append(section)
consumed += section.vol.size
@@ -442,8 +441,9 @@ class PdbReader:
symrec_layer = self._context.layers.get(self._layer_name + "_stream" + str(self._dbiheader.symrecStream), None)
if not symrec_layer:
raise ValueError("No SymRec stream available")
module = self._context.module(
module_name = symrec_layer.pdb_symbol_table, layer_name = symrec_layer.name, offset = 0)
module = self._context.module(module_name = symrec_layer.pdb_symbol_table,
layer_name = symrec_layer.name,
offset = 0)
offset = 0
max_address = symrec_layer.maximum_address
@@ -483,8 +483,9 @@ class PdbReader:
pdb_info_layer = self._context.layers.get(self._layer_name + "_stream1", None)
if not pdb_info_layer:
raise ValueError("No PDB Info Stream available")
module = self._context.module(
module_name = pdb_info_layer.pdb_symbol_table, layer_name = pdb_info_layer.name, offset = 0)
module = self._context.module(module_name = pdb_info_layer.pdb_symbol_table,
layer_name = pdb_info_layer.name,
offset = 0)
pdb_info = module.object(object_type = "PDB_INFORMATION", offset = 0)
self.metadata['windows']['pdb'] = {
@@ -705,8 +706,9 @@ class PdbReader:
"""Returns a (leaf_type, name, object) Tuple for a type, and the number
of bytes consumed."""
result = None, None, None # type: Tuple[Optional[interfaces.objects.ObjectInterface], Optional[str], Optional[Union[List, interfaces.objects.ObjectInterface]]]
leaf_type = self.context.object(
module.get_enumeration("LEAF_TYPE"), layer_name = module._layer_name, offset = offset)
leaf_type = self.context.object(module.get_enumeration("LEAF_TYPE"),
layer_name = module._layer_name,
offset = offset)
consumed = leaf_type.vol.base_type.size
remaining = length - consumed
@@ -857,10 +859,9 @@ class PdbReader:
value."""
excess = 0
if value >= leaf_type.LF_CHAR:
sub_leaf_type = self.context.object(
self.context.symbol_space.get_enumeration(leaf_type.vol.type_name),
layer_name = leaf_type.vol.layer_name,
offset = value.vol.offset)
sub_leaf_type = self.context.object(self.context.symbol_space.get_enumeration(leaf_type.vol.type_name),
layer_name = leaf_type.vol.layer_name,
offset = value.vol.offset)
# Set the offset at just after the previous size type
offset = value.vol.offset + value.vol.data_format.length
if sub_leaf_type in [leaf_type.LF_CHAR]:
@@ -952,10 +953,16 @@ if __name__ == '__main__':
file_group.add_argument("-f", "--file", metavar = "FILE", help = "PDB file to translate to ISF")
data_group = parser.add_argument_group("data", description = "Convert based on a GUID and filename pattern")
data_group.add_argument("-p", "--pattern", metavar = "PATTERN", help = "Filename pattern to recover PDB file")
data_group.add_argument(
"-g", "--guid", metavar = "GUID", help = "GUID + Age string for the required PDB file", default = None)
data_group.add_argument(
"-k", "--keep", action = "store_true", default = False, help = "Keep the downloaded PDB file")
data_group.add_argument("-g",
"--guid",
metavar = "GUID",
help = "GUID + Age string for the required PDB file",
default = None)
data_group.add_argument("-k",
"--keep",
action = "store_true",
default = False,
help = "Keep the downloaded PDB file")
args = parser.parse_args()
pg_cb = PrintedProgress()
@@ -13,8 +13,9 @@ class Certificates(interfaces.plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"]),
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))
@@ -33,20 +34,20 @@ class Certificates(interfaces.plugins.PluginInterface):
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 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",
]:
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):
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
@@ -54,8 +55,8 @@ class Certificates(interfaces.plugins.PluginInterface):
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 = 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))
+3 -2
View File
@@ -15,8 +15,9 @@ class Statistics(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.TranslationLayerRequirement(
name = 'primary', description = 'Memory layer for the kernel', architectures = ["Intel32", "Intel64"])
requirements.TranslationLayerRequirement(name = 'primary',
description = 'Memory layer for the kernel',
architectures = ["Intel32", "Intel64"])
]
def _generator(self):