diff --git a/volatility3/cli/text_renderer.py b/volatility3/cli/text_renderer.py index 1453c0ea1..39abb265e 100644 --- a/volatility3/cli/text_renderer.py +++ b/volatility3/cli/text_renderer.py @@ -159,42 +159,12 @@ class LayerDataRenderer(CLITypeRenderer): def render( data: Union[renderers.LayerData, interfaces.renderers.BaseAbsentValue], - ): + ) -> str: if isinstance(data, interfaces.renderers.BaseAbsentValue): # FIXME: Do something cleverer here return "" - context_byte_len = self.context_byte_len if not data.no_surrounding else 0 - - layer = data.context.layers[data.layer_name] - # Map of the holes - error_bytes = set() - start_offset = data.offset - context_byte_len - end_offset = data.offset + data.length + 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, - ) + specific_data, error_bytes = self.render_bytes(data) printables = "" output = "\n" @@ -224,6 +194,46 @@ class LayerDataRenderer(CLITypeRenderer): render_func = render return super().__init__(render_func) + def render_bytes(self, data: renderers.LayerData) -> tuple[bytes, set[int]]: + """Renders a valid LayerData into bytes (with context bytes)""" + context_byte_len = self.context_byte_len if not data.no_surrounding else 0 + + layer = data.context.layers[data.layer_name] + # Map of the holes + error_bytes = set() + start_offset = data.offset - context_byte_len + end_offset = data.offset + data.length + 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, + ) + + import pdb + + pdb.set_trace() + + return specific_data, error_bytes + class CLIRenderer(interfaces.renderers.Renderer): """Class to add specific requirements for CLI renderers.""" @@ -525,9 +535,10 @@ class PrettyTextRenderer(CLIRenderer): class JsonRenderer(CLIRenderer): _type_renderers = { - format_hints.HexBytes: quoted_optional(hex_bytes_as_text), + format_hints.HexBytes: lambda x: x.hex(" "), renderers.Disassembly: quoted_optional(display_disassembly), format_hints.MultiTypeData: quoted_optional(multitypedata_as_text), + renderers.LayerData: lambda x: LayerDataRenderer().render_bytes(x)[0].hex(" "), bytes: optional(lambda x: " ".join(f"{b:02x}" for b in x)), datetime.datetime: lambda x: ( x.isoformat()