From f9a950bb3930459c752290f18e3c968c520da56b Mon Sep 17 00:00:00 2001 From: "Nick L. Petroni, Jr" Date: Wed, 25 May 2016 20:52:46 -0400 Subject: [PATCH 1/3] added LIME translation layer --- volatility/framework/layers/lime.py | 118 ++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 volatility/framework/layers/lime.py diff --git a/volatility/framework/layers/lime.py b/volatility/framework/layers/lime.py new file mode 100644 index 0000000000..bdbac4a9d9 --- /dev/null +++ b/volatility/framework/layers/lime.py @@ -0,0 +1,118 @@ +""" +Created on 6 Apr 2016 + +@author: npetroni@volexity.com +""" + +import struct + +from volatility.framework import interfaces, exceptions +from volatility.framework.configuration import requirements + +class LimeFormatException(exceptions.LayerException): + """Thrown when an error occurs with the underlying Lime file format""" + +class LimeLayer(interfaces.layers.TranslationLayerInterface): + """A Lime format TranslationLayer. Lime is generally used to store + physical memory images where there are large holes in the physical + address space""" + + provides = {"type": "physical"} + priority = 21 + + MAGIC = 0x4c694d45 + VERSION = 1 + + # Magic[4], Version[4], Start[8], End[8], Reserved[8] + # XXX move this to a custom SymbolSpace? + _header_struct = struct.Struct('= logical_start and offset < (logical_start + size): + return (logical_start, base_start, size) + + raise exceptions.InvalidAddressException("Lime fault at address " + hex(offset)) + + + def is_valid(self, offset, length = 1): + """Returns whether the address offset can be translated to a valid address""" + try: + return all([self._context.memory[self._base_layer].is_valid(mapped_offset) for _, mapped_offset, _, _ in + self.mapping(offset, length)]) + except exceptions.InvalidAddressException: + return False + + def mapping(self, offset, length): + """Returns a sorted list of (offset, mapped_offset, length, layer) mappings""" + if length == 0: + logical_start, base_start, size = self._find_segment(offset) + mapped_offset = offset - logical_start + base_start + return [(offset, mapped_offset, 0, self._base_layer)] + result = [] + while length > 0: + logical_start, base_start, size = self._find_segment(offset) + chunk_offset = offset - logical_start + base_start + chunk_size = size - (offset - logical_start) + result.append((offset, chunk_offset, chunk_size, self._base_layer)) + length -= chunk_size + offset += chunk_size + return result + + @property + def dependencies(self): + """Returns a list of the lower layers that this layer is dependent upon""" + return [self._base_layer] + + @classmethod + def get_schema(cls): + return [requirements.TranslationLayerRequirement(name = 'base_layer', + constraints = {"type": "physical"}, + optional = False)] From 2686487e6f5df0601fae1edae565ad8ad38df6fd Mon Sep 17 00:00:00 2001 From: "Nick L. Petroni, Jr" Date: Thu, 26 May 2016 06:44:09 -0400 Subject: [PATCH 2/3] lime.py: first working version - moved segment loading out of __init__(), now happens on first use - fixed mapping() to return the correct chunk_size - self._base_layer is a string, not a layer --- volatility/framework/layers/lime.py | 36 ++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/volatility/framework/layers/lime.py b/volatility/framework/layers/lime.py index bdbac4a9d9..f022e50834 100644 --- a/volatility/framework/layers/lime.py +++ b/volatility/framework/layers/lime.py @@ -33,13 +33,27 @@ def __init__(self, context, config_path, name, base_layer): self._base_layer = base_layer # list of tuples (logical start, base start, size) - segments = [] + # loaded by _load_segments() on first access + self._segments = [] + self._minaddr = 0 + self._maxaddr = 0 - # logical end of physical memory + @property + def minimum_address(self): + return self._minaddr + + @property + def maximum_address(self): + return self._maxaddr + + def _load_segments(self): + base_layer = self._context.memory[self._base_layer] base_maxaddr = base_layer.maximum_address maxaddr = 0 offset = 0 header_size = self._header_struct.size + segments = [] + while offset < base_maxaddr: header_data = base_layer.read(offset, header_size) @@ -54,20 +68,17 @@ def __init__(self, context, config_path, name, base_layer): raise LimeFormatException("bad start/end 0x%x/0x%x at file offset 0x%x" % (start, end, offset)) segment_length = end - start + 1 - segments.append((start, offset, segment_length)) + segments.append((start, offset + header_size, segment_length)) maxaddr = end offset = offset + header_size + segment_length + if len(segments) == 0: + raise LimeFormatException("No LiME segments defined in " + self._base_layer) + self._segments = segments + self._minaddr = segments[0][0] self._maxaddr = maxaddr - @property - def minimum_address(self): - return self._segments[0][0] - - @property - def maximum_address(self): - return self._maxaddr def _find_segment(self, offset): """Finds the segment containing a given offset @@ -75,6 +86,9 @@ def _find_segment(self, offset): Returns the segment tuple """ + if self._segments == []: + self._load_segments() + for logical_start, base_start, size in self._segments: if offset >= logical_start and offset < (logical_start + size): return (logical_start, base_start, size) @@ -100,7 +114,7 @@ def mapping(self, offset, length): while length > 0: logical_start, base_start, size = self._find_segment(offset) chunk_offset = offset - logical_start + base_start - chunk_size = size - (offset - logical_start) + chunk_size = min(size - (offset - logical_start), length) result.append((offset, chunk_offset, chunk_size, self._base_layer)) length -= chunk_size offset += chunk_size From 02f26e78294094afc604afa9b1279625584c4619 Mon Sep 17 00:00:00 2001 From: "Nick L. Petroni, Jr" Date: Thu, 26 May 2016 09:24:36 -0400 Subject: [PATCH 3/3] lime.py: improve check -- empty lists evaluate to False --- volatility/framework/layers/lime.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/volatility/framework/layers/lime.py b/volatility/framework/layers/lime.py index f022e50834..c125390414 100644 --- a/volatility/framework/layers/lime.py +++ b/volatility/framework/layers/lime.py @@ -86,7 +86,7 @@ def _find_segment(self, offset): Returns the segment tuple """ - if self._segments == []: + if not self._segments: self._load_segments() for logical_start, base_start, size in self._segments: