diff --git a/volatility/framework/layers/vmware.py b/volatility/framework/layers/vmware.py index ea449f7b65..a5047c42b9 100644 --- a/volatility/framework/layers/vmware.py +++ b/volatility/framework/layers/vmware.py @@ -39,6 +39,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: @@ -48,12 +52,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))) - # TODO: Change certain structure sizes based on the version - # version = magic[1] & 0xf - + version = magic[0] & 0xf group_size = struct.calcsize(self.group_structure) groups = {} @@ -77,19 +79,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 = self._context.object("vmware!unsigned int", + data_len = flags & 0x3f + + if data_len in [62, 63]: # Handle special data sizes that indicate a longer data stream + data_len = 4 if version == 0 else 8 + # 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) + self._context.symbol_space.get_type("vmware!unsigned int").size + 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")