From e44094fb7389bab38e80f632d9d483847e14f07c Mon Sep 17 00:00:00 2001 From: cstation Date: Tue, 19 Jan 2021 21:55:01 +0100 Subject: [PATCH 1/2] Fix VMware layer tag reading The VMware layer did not handle tags having a different data-size. This fixes the majority of cases, since the needed tags for determining the memory regions will often be located in the regular-sized tags. --- volatility/framework/layers/vmware.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/volatility/framework/layers/vmware.py b/volatility/framework/layers/vmware.py index fc412fb2e0..d7b74332fe 100644 --- a/volatility/framework/layers/vmware.py +++ b/volatility/framework/layers/vmware.py @@ -48,8 +48,7 @@ def _read_header(self) -> None: if magic not in [b"\xD2\xBE\xD2\xBE"]: raise VmwareFormatException(self.name, "Wrong magic bytes for Vmware layer: {}".format(repr(magic))) - # TODO: Change certain structure sizes based on the version - # version = magic[1] & 0xf + version = magic[0] & 0xf group_size = struct.calcsize(self.group_structure) @@ -81,12 +80,20 @@ def _read_header(self) -> None: self._context.object("vmware!unsigned int", offset = offset + name_len + 2 + (index * index_len), layer_name = self._meta_layer)) - data = self._context.object("vmware!unsigned int", + data_len = flags & 0x3f + + # TODO: Read special data sizes (signalling a longer data stream) properly instead of skipping them + if data_len in (62, 63): + data_len = 4 if version == 0 else 8 + offset += 2 + name_len + (indicies_len * index_len) + 2 * data_len + continue + + data = self._context.object("vmware!unsigned int" if data_len == 4 else "vmware!unsigned long long", layer_name = self._meta_layer, offset = offset + 2 + name_len + (indicies_len * index_len)) tags[(name, tuple(indicies))] = (flags, data) offset += 2 + name_len + (indicies_len * - index_len) + self._context.symbol_space.get_type("vmware!unsigned int").size + index_len) + data_len if tags[("regionsCount", ())][1] == 0: raise VmwareFormatException(self.name, "VMware VMEM is not split into regions") From 9ef341907f102a77d36958d70565b7634a314ac8 Mon Sep 17 00:00:00 2001 From: cstation Date: Thu, 21 Jan 2021 10:08:20 +0100 Subject: [PATCH 2/2] Improve VMware Tag reading Fix magic headers and properly read irregular-sized tags --- volatility/framework/layers/vmware.py | 50 ++++++++++++++++++--------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/volatility/framework/layers/vmware.py b/volatility/framework/layers/vmware.py index d7b74332fe..2150edc982 100644 --- a/volatility/framework/layers/vmware.py +++ b/volatility/framework/layers/vmware.py @@ -36,6 +36,10 @@ def _load_segments(self) -> None: """Loads up the segments from the meta_layer.""" self._read_header() + @staticmethod + def _choose_type(size: int) -> str: + return "vmware!unsigned int" if size == 4 else "vmware!unsigned long long" + def _read_header(self) -> None: """Checks the vmware header to make sure it's valid.""" if "vmware" not in self._context.symbol_space: @@ -45,11 +49,10 @@ def _read_header(self) -> None: header_size = struct.calcsize(self.header_structure) data = meta_layer.read(0, header_size) magic, unknown, groupCount = struct.unpack(self.header_structure, data) - if magic not in [b"\xD2\xBE\xD2\xBE"]: + if magic not in [b"\xD0\xBE\xD2\xBE", b"\xD1\xBA\xD1\xBA", b"\xD2\xBE\xD2\xBE", b"\xD3\xBE\xD3\xBE"]: raise VmwareFormatException(self.name, "Wrong magic bytes for Vmware layer: {}".format(repr(magic))) version = magic[0] & 0xf - group_size = struct.calcsize(self.group_structure) groups = {} @@ -73,27 +76,40 @@ def _read_header(self) -> None: layer_name = self._meta_layer, offset = offset + 2, max_length = name_len) - indicies_len = (flags >> 6) & 3 - indicies = [] - for index in range(indicies_len): - indicies.append( + indices_len = (flags >> 6) & 3 + indices = [] + for index in range(indices_len): + indices.append( self._context.object("vmware!unsigned int", offset = offset + name_len + 2 + (index * index_len), layer_name = self._meta_layer)) data_len = flags & 0x3f - - # TODO: Read special data sizes (signalling a longer data stream) properly instead of skipping them - if data_len in (62, 63): + + if data_len in [62, 63]: # Handle special data sizes that indicate a longer data stream data_len = 4 if version == 0 else 8 - offset += 2 + name_len + (indicies_len * index_len) + 2 * data_len - continue - - data = self._context.object("vmware!unsigned int" if data_len == 4 else "vmware!unsigned long long", + # Read the size of the data + data_size = self._context.object(self._choose_type(data_len), + layer_name = self._meta_layer, + offset = offset + 2 + name_len + (indices_len * index_len)) + # Read the size of the data when it would be decompressed + data_mem_size = self._context.object(self._choose_type(data_len), layer_name = self._meta_layer, - offset = offset + 2 + name_len + (indicies_len * index_len)) - tags[(name, tuple(indicies))] = (flags, data) - offset += 2 + name_len + (indicies_len * - index_len) + data_len + offset = offset + 2 + name_len + (indices_len * index_len) + data_len) + # Skip two bytes of padding (as it seems?) + # Read the actual data + data = self._context.object("vmware!bytes", + layer_name = self._meta_layer, + offset = offset + 2 + name_len + (indices_len * index_len) + + 2 * data_len + 2, + length = data_size) + offset += 2 + name_len + (indices_len * index_len) + 2 * data_len + 2 + data_size + else: # Handle regular cases + data = self._context.object(self._choose_type(data_len), + layer_name = self._meta_layer, + offset = offset + 2 + name_len + (indices_len * index_len)) + offset += 2 + name_len + (indices_len * index_len) + data_len + + tags[(name, tuple(indices))] = (flags, data) if tags[("regionsCount", ())][1] == 0: raise VmwareFormatException(self.name, "VMware VMEM is not split into regions")