From ba82067dac96ebf3845e37addf3d0d71f0a84462 Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sat, 15 Feb 2025 20:29:59 +0000 Subject: [PATCH] CLI: Add in initial LayerData renderer --- volatility3/cli/text_renderer.py | 61 ++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/volatility3/cli/text_renderer.py b/volatility3/cli/text_renderer.py index a13c64d0d..a0b45e353 100644 --- a/volatility3/cli/text_renderer.py +++ b/volatility3/cli/text_renderer.py @@ -1,3 +1,5 @@ +from volatility3.framework.interfaces.layers import TranslationLayerInterface + # This file is Copyright 2019 Volatility Foundation and licensed under the Volatility Software License 1.0 # which is available at https://www.volatilityfoundation.org/license/vsl-v1.0 # @@ -150,12 +152,67 @@ class LayerDataRenderer(CLITypeRenderer): """Renders a LayerData object into data/bytes""" def __init__(self): + self.context_byte_len = 0 + self.width = 16 + self.display_offset = False + self.display_hex = True + self.display_ascii = True + def render(data: Union[interfaces.renderers.LayerData, BaseAbsentValue]): if isinstance(data, BaseAbsentValue): # FIXME: Do something cleverer here return "" - data = data.context.layers[data.layer_name].read(data.offset, data.length) - return " ".join(f"{b:02x}" for b in data) + + layer = data.context.layers[data.layer_name] + # Map of the holes + error_bytes = set() + start_offset = data.offset - self.context_byte_len + end_offset = data.offset + data.length + self.context_byte_len + if isinstance(layer, interfaces.layers.TranslationLayerInterface): + error_bytes = set() + mapping = iter(layer.mapping(start_offset, end_offset, True)) + current_map = next(mapping) + for i in range(start_offset, end_offset): + # Run through the bytes, check if they're present + offset, sublength, _, _, _ = current_map + if i < offset: + error_bytes.add(i - start_offset) + if i > offset + sublength: + try: + current_map = next(mapping) + except StopIteration: + pass + offset, sublength, _, _, _ = current_map + if i > offset + sublength: + error_bytes.add(i - start_offset) + + # Padded data + specific_data = data.context.layers[data.layer_name].read( + start_offset, + end_offset - start_offset, + True, + ) + + printables = "" + output = "\n" + for count, byte in enumerate(specific_data): + output += f"{byte:02x} " + char = chr(byte) + printables += char if 0x20 <= byte <= 0x7E else "." + if count % self.width == self.width - 1: + output += printables + if count < len(specific_data) - 1: + output += "\n" + printables = "" + + # Handle leftovers when the length is not mutiple of width + if printables: + padding = self.width - len(printables) + output += " " * padding + output += printables + output += " " * padding + + return output render_func = render return super().__init__(render_func)