From 19b2a06964b5840e78755d12c36344c17d0b86b2 Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Wed, 11 Aug 2021 22:02:08 +0100 Subject: [PATCH] Layers: Coalesce intel mapping responses --- volatility3/framework/layers/intel.py | 35 +++++++++++++++++-- .../framework/plugins/windows/memmap.py | 31 +--------------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/volatility3/framework/layers/intel.py b/volatility3/framework/layers/intel.py index 48fa205bd..4a582f1fb 100644 --- a/volatility3/framework/layers/intel.py +++ b/volatility3/framework/layers/intel.py @@ -193,6 +193,38 @@ class Intel(linear.LinearlyMappedLayer): """Returns a sorted iterable of (offset, sublength, mapped_offset, mapped_length, layer) mappings. + This allows translation layers to provide maps of contiguous + regions in one layer + """ + stashed_offset = stashed_mapped_offset = stashed_size = stashed_mapped_size = stashed_map_layer = None + for offset, size, mapped_offset, mapped_size, map_layer in self._mapping(offset, length, ignore_errors): + if stashed_offset is None or (stashed_offset + stashed_size != offset) or ( + stashed_mapped_offset + stashed_mapped_size != mapped_offset) or (stashed_map_layer != map_layer): + # The block isn't contiguous + if stashed_offset is not None: + yield stashed_offset, stashed_size, stashed_mapped_offset, stashed_mapped_size, stashed_map_layer + # Update all the stashed values after output + stashed_offset = offset + stashed_mapped_offset = mapped_offset + stashed_size = size + stashed_mapped_size = mapped_size + stashed_map_layer = map_layer + else: + # Part of an existing block + stashed_size += size + stashed_mapped_size += mapped_size + # Yield whatever's left + if (stashed_offset is not None and stashed_mapped_offset is not None and stashed_size is not None + and stashed_mapped_size is not None and stashed_map_layer is not None): + yield stashed_offset, stashed_size, stashed_mapped_offset, stashed_mapped_size, stashed_map_layer + + def _mapping(self, + offset: int, + length: int, + ignore_errors: bool = False) -> Iterable[Tuple[int, int, int, int, str]]: + """Returns a sorted iterable of (offset, sublength, mapped_offset, mapped_length, layer) + mappings. + This allows translation layers to provide maps of contiguous regions in one layer """ @@ -328,12 +360,11 @@ class WindowsIntelPAE(WindowsMixin, IntelPAE): class WindowsIntel32e(WindowsMixin, Intel32e): - # TODO: Fix appropriately in a future release. # Currently just a temprorary workaround to deal with custom bit flag # in the PFN field for pages in transition state. # See https://github.com/volatilityfoundation/volatility3/pull/475 _maxphyaddr = 45 - + def _translate(self, offset: int) -> Tuple[int, int, str]: return self._translate_swap(self, offset, self._bits_per_register // 2) diff --git a/volatility3/framework/plugins/windows/memmap.py b/volatility3/framework/plugins/windows/memmap.py index e67a6a877..c303a8e7b 100644 --- a/volatility3/framework/plugins/windows/memmap.py +++ b/volatility3/framework/plugins/windows/memmap.py @@ -27,8 +27,6 @@ class Memmap(interfaces.plugins.PluginInterface): architectures = ["Intel32", "Intel64"]), requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"), requirements.PluginRequirement(name = 'pslist', plugin = pslist.PsList, version = (2, 0, 0)), - requirements.BooleanRequirement(name = 'coalesce', description = 'Clump output where possible', - default = False, optional = True), requirements.IntRequirement(name = 'pid', description = "Process ID to include (all other processes are excluded)", optional = True), @@ -38,29 +36,6 @@ class Memmap(interfaces.plugins.PluginInterface): optional = True) ] - @classmethod - def coalesce(cls, mapping_generator): - stashed_offset = stashed_mapped_offset = stashed_size = stashed_mapped_size = stashed_mapped_layer = None - for offset, size, mapped_offset, mapped_size, map_layer in mapping_generator: - if stashed_offset is None or (stashed_offset + stashed_size != offset) or ( - stashed_mapped_offset + stashed_mapped_size != mapped_offset) or (stashed_map_layer != map_layer): - # The block isn't contiguous - if stashed_offset is not None: - yield stashed_offset, stashed_size, stashed_mapped_offset, stashed_mapped_size, stashed_map_layer - # Update all the stashed values after output - stashed_offset = offset - stashed_mapped_offset = mapped_offset - stashed_size = size - stashed_mapped_size = mapped_size - stashed_map_layer = map_layer - else: - # Part of an existing block - stashed_size += size - stashed_mapped_size += mapped_size - # Yield whatever's left - if stashed_offset is not None: - yield stashed_offset, stashed_size, stashed_mapped_offset, stashed_mapped_size, stashed_map_layer - def _generator(self, procs): for proc in procs: pid = "Unknown" @@ -74,10 +49,6 @@ class Memmap(interfaces.plugins.PluginInterface): excp.layer_name)) continue - if self.config['coalesce']: - coalesce = self.coalesce - else: - coalesce = lambda x: x if self.config['dump']: file_handle = self.open(f"pid.{pid}.dmp") else: @@ -85,7 +56,7 @@ class Memmap(interfaces.plugins.PluginInterface): file_handle = contextlib.ExitStack() with file_handle as file_data: file_offset = 0 - for mapval in coalesce(proc_layer.mapping(0x0, proc_layer.maximum_address, ignore_errors = True)): + for mapval in proc_layer.mapping(0x0, proc_layer.maximum_address, ignore_errors = True): offset, size, mapped_offset, mapped_size, maplayer = mapval file_output = "Disabled"