Add in a very rudimentary kernel PDB finding plugin that identifies and automatically loads the appropriate kernel for the image.

This commit is contained in:
Mike Auty
2016-11-27 23:40:19 +00:00
parent b2c3c76954
commit c86f0ddef4
2 changed files with 59 additions and 11 deletions
+7 -4
View File
@@ -58,10 +58,13 @@ class CommandLine(object):
ctx.config["ui.single_location"] = "file:///run/media/mike/disk/memory/private/jon-fres.dmp"
ctx.config["plugins.pslist.offset"] = 0x01bcc830
ctx.config[
"plugins.pslist.ntkrnlmp.class"] = "volatility.framework.symbols.windows.WindowsKernelIntermedSymbols"
ctx.config[
"plugins.pslist.ntkrnlmp.idd_filepath"] = "file:///home/mike/workspace/volatility3/aux/ntoskrnl.pdb.json"
# ctx.config[
# "plugins.pslist.ntkrnlmp.class"] = "volatility.framework.symbols.windows.WindowsKernelIntermedSymbols"
# ctx.config[
# "plugins.pslist.ntkrnlmp.idd_filepath"] = "file:///home/mike/workspace/volatility3/aux/ntoskrnl.pdb.json"
# ctx.config["ui.single_location"] = "file:///run/media/mike/disk/memory/private/win10-x64-2016-05-28.lime"
# ctx.config["plugins.pslist.offset"] = 0xfe001608573c0
###
# BACK TO THE FRAMEWORK
+52 -7
View File
@@ -1,15 +1,18 @@
# pdbscan.py -- Scan Volatility Layers for Windows kernel PDB signatures
#
import logging
import os
import struct
if __name__ == "__main__":
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))
import struct
from volatility.framework import interfaces
vollog = logging.getLogger(__name__)
PAGE_SIZE = 0x1000
@@ -76,9 +79,12 @@ def scan(ctx, layer_name):
break
min_pfn = sig_pfn
results.append((GUID, age, pdb_name, signature_offset, mz_offset))
results.append({'GUID': GUID,
'age': age,
'pdb_name': str(pdb_name, "utf-8"),
'signature_offset': signature_offset,
'mz_offset': mz_offset})
print(results)
return results
@@ -90,8 +96,13 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
"""Looks for all Intel address spaces and attempts to identify the PDB guid required for the space"""
priority = 30
def __call__(self, context, config_path, requirement):
def __init__(self):
super().__init__()
self.potential_kernels = []
def recurse_pdb_finder(self, context, config_path, requirement):
sub_config_path = interfaces.configuration.path_join(config_path, requirement.name)
results = []
if isinstance(requirement, interfaces.configuration.TranslationLayerRequirement):
# Check for symbols in this layer
# FIXME: optionally allow a full (slow) scan
@@ -102,4 +113,38 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
results = scan(context, layer_name)
else:
for subreq in requirement.requirements.values():
self(context, sub_config_path, subreq)
results += self.recurse_pdb_finder(context, sub_config_path, subreq)
return results
def recurse_symbol_fulfiller(self, context, config_path, requirement):
sub_config_path = interfaces.configuration.path_join(config_path, requirement.name)
if isinstance(requirement, interfaces.configuration.SymbolRequirement):
# TODO: Check that the symbols for this kernel will fulfill the requirement
# TODO: Potentially think about multiple symbol requirements in both the same and different levels of the requirement tree
# TODO: Consider whether a single found kernel can fulfill multiple requirements
if self.potential_kernels:
kernel = self.potential_kernels[0]
suffix = kernel['pdb_name'] + "-" + kernel['GUID'] + "-" + str(kernel['age']) + ".json"
# Check user symbol directory first, then fallback to the framework's library to allow for overloading
prefixes = [os.path.join(os.path.dirname(__file__), "..", "..", "symbols", "windows"),
os.path.join(os.path.dirname(__file__), "..", "symbols", "windows")]
idd_path = None
for prefix in prefixes:
if os.path.exists(os.path.join(prefix, suffix)):
idd_path = "file://" + os.path.abspath(os.path.join(prefix, suffix))
if idd_path:
clazz = "volatility.framework.symbols.windows.WindowsKernelIntermedSymbols"
# Set the discovered options
context.config[interfaces.configuration.path_join(sub_config_path, "class")] = clazz
context.config[interfaces.configuration.path_join(sub_config_path, "idd_filepath")] = idd_path
# Construct the appropriate symbol table
requirement.construct(context, config_path)
else:
vollog.debug("Symbol library path not found: {}".format(suffix))
else:
for subreq in requirement.requirements.values():
self.recurse_symbol_fulfiller(context, sub_config_path, subreq)
def __call__(self, context, config_path, requirement):
self.potential_kernels = list(self.recurse_pdb_finder(context, config_path, requirement))
self.recurse_symbol_fulfiller(context, config_path, requirement)