mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-12 20:57:39 +02:00
Yapf-0.28.0 rerun across the whole codebase.
This commit is contained in:
+55
-63
@@ -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()
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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")
|
||||
]
|
||||
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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,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")
|
||||
]
|
||||
|
||||
|
||||
@@ -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")
|
||||
]
|
||||
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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"),
|
||||
]
|
||||
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
]
|
||||
|
||||
@@ -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"])
|
||||
|
||||
@@ -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)],
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user