From f4dee3c5f01019306abdd30e321eadf03e9b4577 Mon Sep 17 00:00:00 2001 From: iMHLv2 Date: Tue, 30 Mar 2021 15:27:09 -0500 Subject: [PATCH] sync with fa1c03d of jxwegner/volatility3 --- volatility3/framework/layers/crash.py | 60 ++++++++++++------- .../framework/plugins/windows/crashinfo.py | 33 ++++++++++ 2 files changed, 70 insertions(+), 23 deletions(-) create mode 100644 volatility3/framework/plugins/windows/crashinfo.py diff --git a/volatility3/framework/layers/crash.py b/volatility3/framework/layers/crash.py index 8909eceb8..96c66d483 100644 --- a/volatility3/framework/layers/crash.py +++ b/volatility3/framework/layers/crash.py @@ -1,14 +1,15 @@ -# This file is Copyright 2019 Volatility Foundation and licensed under the Volatility Software License 1.0 + + +# This file is Copyright 2021 Volatility Foundation and licensed under the Volatility Software License 1.0 # which is available at https://www.volatilityfoundation.org/license/vsl-v1.0 # - import logging import struct -from typing import Tuple, Optional +from typing import Tuple, Optional, Iterable -from volatility3.framework import constants, exceptions, interfaces -from volatility3.framework.layers import segmented -from volatility3.framework.symbols import intermed +from volatility.framework import constants, exceptions, interfaces +from volatility.framework.layers import segmented +from volatility.framework.symbols import intermed vollog = logging.getLogger(__name__) @@ -19,7 +20,6 @@ class WindowsCrashDumpFormatException(exceptions.LayerException): class WindowsCrashDump32Layer(segmented.SegmentedLayer): """A Windows crash format TranslationLayer. - This TranslationLayer supports Microsoft complete memory dump files. It currently does not support kernel or small memory dump files. """ @@ -42,7 +42,11 @@ class WindowsCrashDump32Layer(segmented.SegmentedLayer): self._context = context self._config_path = config_path self._page_size = 0x1000 - self._base_layer = self.config["base_layer"] + try: + self._base_layer = self.config["base_layer"] + except KeyError: + self._base_layer = 'base_layer' + self.config['base_layer']='base_layer' # Create a custom SymbolSpace self._crash_table_name = intermed.IntermediateSymbolTable.create(context, self._config_path, 'windows', @@ -71,30 +75,34 @@ class WindowsCrashDump32Layer(segmented.SegmentedLayer): def _load_segments(self) -> None: """Loads up the segments from the meta_layer.""" - header = self.context.object(self._crash_table_name + constants.BANG + self.dump_header_name, - offset = 0, - layer_name = self._base_layer) + segments = [] offset = self.headerpages + header = self.context.object(self._crash_table_name + constants.BANG + self.dump_header_name, + offset = 0, + layer_name = self._base_layer) + offset = self.headerpages header.PhysicalMemoryBlockBuffer.Run.count = header.PhysicalMemoryBlockBuffer.NumberOfRuns for x in header.PhysicalMemoryBlockBuffer.Run: segments.append((x.BasePage * 0x1000, offset * 0x1000, x.PageCount * 0x1000, x.PageCount * 0x1000)) - # print("Segments {:x} {:x} {:x}".format(x.BasePage * 0x1000, - # offset * 0x1000, - # x.PageCount * 0x1000)) + # print("Segments {:x} {:x} {:x}".format(x.BasePage * 0x1000, + # offset * 0x1000, + # x.PageCount * 0x1000)) offset += x.PageCount + if len(segments) == 0: raise WindowsCrashDumpFormatException(self.name, "No Crash segments defined in {}".format(self._base_layer)) - self._segments = segments + + @classmethod def check_header(cls, base_layer: interfaces.layers.DataLayerInterface, offset: int = 0) -> Tuple[int, int]: # Verify the Window's crash dump file magic - + try: header_data = base_layer.read(offset, cls._magic_struct.size) except exceptions.InvalidAddressException: @@ -114,7 +122,6 @@ class WindowsCrashDump32Layer(segmented.SegmentedLayer): class WindowsCrashDump64Layer(WindowsCrashDump32Layer): """A Windows crash format TranslationLayer. - This TranslationLayer supports Microsoft complete memory dump files. It currently does not support kernel or small memory dump files. """ @@ -133,7 +140,6 @@ class WindowsCrashDump64Layer(WindowsCrashDump32Layer): summary_header = self.context.object(self._crash_table_name + constants.BANG + "_SUMMARY_DUMP64", offset = 0x2000, layer_name = self._base_layer) - if self.dump_type == 0x1: header = self.context.object(self._crash_table_name + constants.BANG + self.dump_header_name, offset = 0, @@ -146,16 +152,19 @@ class WindowsCrashDump64Layer(WindowsCrashDump32Layer): offset += x.PageCount elif self.dump_type == 0x05: - summary_header.BufferLong.count = (summary_header.BitmapSize + 31) // 32 + #Add 0x2000 as some bitmaps are too short by one offset + summary_header.BufferLong.count = (summary_header.BitmapSize + 31) // 32 + 0x2000 previous_bit = 0 start_position = 0 # We cast as an int because we don't want to carry the context around with us for infinite loop reasons mapped_offset = int(summary_header.HeaderSize) current_word = None - for bit_position in range(len(summary_header.BufferLong) * 32): + bitmap_len=len(summary_header.BufferLong) * 32 + for bit_position in range(bitmap_len): if (bit_position % 32) == 0: current_word = summary_header.BufferLong[bit_position // 32] current_bit = (current_word >> (bit_position % 32)) & 1 + if current_bit != previous_bit: if previous_bit == 0: # Start @@ -166,11 +175,15 @@ class WindowsCrashDump64Layer(WindowsCrashDump32Layer): segments.append((start_position * 0x1000, mapped_offset, length, length)) mapped_offset += length - # Finish it off - if bit_position == (len(summary_header.BufferLong) * 32) - 1 and current_bit == 1: + + # Find the last segment in a file which will be at the end or two pages from the end. We multiply by 32 as we want to offset bby words rather than bits + if (bit_position == bitmap_len - 1 or bit_position == bitmap_len - 1 -32*0x2000) and current_bit == 1: length = (bit_position - start_position) * 0x1000 segments.append((start_position * 0x1000, mapped_offset, length, length)) mapped_offset += length + break + + previous_bit = current_bit else: @@ -179,7 +192,7 @@ class WindowsCrashDump64Layer(WindowsCrashDump32Layer): if len(segments) == 0: raise WindowsCrashDumpFormatException(self.name, "No Crash segments defined in {}".format(self._base_layer)) - + self._segments = segments @@ -200,3 +213,4 @@ class WindowsCrashDumpStacker(interfaces.automagic.StackerLayerInterface): except WindowsCrashDumpFormatException: pass return None + diff --git a/volatility3/framework/plugins/windows/crashinfo.py b/volatility3/framework/plugins/windows/crashinfo.py new file mode 100644 index 000000000..22a8e16c0 --- /dev/null +++ b/volatility3/framework/plugins/windows/crashinfo.py @@ -0,0 +1,33 @@ + +# This file is Copyright 2021 Volatility Foundation and licensed under the Volatility Software License 1.0 +# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0 +# + +import logging +from volatility.framework import interfaces, renderers +from volatility.framework.configuration import requirements +from volatility.framework.layers import crash +from volatility.framework import exceptions + +vollog = logging.getLogger(__name__) + +class Crashinfo(interfaces.plugins.PluginInterface): + _required_framework_version = (2, 0, 0) + + @classmethod + def get_requirements(cls): + return [ + requirements.TranslationLayerRequirement(name = 'primary', + description = 'Memory layer for the kernel', + architectures = ["Intel32", "Intel64"]), + ] + + def _generator(self, layer): + for offset, length, mapped_offset in layer.mapping(0x0, layer.maximum_address, ignore_errors = True): + yield(0,(offset,length,mapped_offset)) + + def run(self): + + layer = self._context.layers[self.config['primary.memory_layer']] + + return renderers.TreeGrid([("StartAddress", int),("FileOffset", int),("Length", int)],self._generator(layer)) \ No newline at end of file