Files
volatility3/volatility/framework/layers/vmware.py
T

122 lines
5.8 KiB
Python

import os
import struct
from urllib import parse
from volatility.framework import interfaces
from volatility.framework.configuration import requirements
from volatility.framework.layers import physical, segmented
class VmwareLayer(segmented.SegmentedLayer):
provides = {"type": "physical"}
priority = 22
header_structure = "<4sII"
group_structure = "64sQQ"
def __init__(self, context, config_path, name):
# Construct these so we can use self.config
self._context = context
self._config_path = config_path
self._base_layer, self._meta_layer = self.config["base_layer"], self.config["meta_layer"]
# Then call the super, which will call load_segments (which needs the base_layer before it'll work)
super().__init__(context, config_path = config_path, name = name)
def _load_segments(self):
"""Loads up the segments from the meta_layer"""
self._read_header()
def _read_header(self):
"""Checks the vmware header to make sure it's valid"""
meta_layer = self.context.memory.get(self._meta_layer, 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"]:
raise ValueError("Wrong magic bytes for Vmware layer: {}".format(repr(magic)))
version = magic[1] & 0xf
group_size = struct.calcsize(self.group_structure)
groups = {}
for group in range(groupCount):
name, tag_location, _unknown = struct.unpack(self.group_structure,
meta_layer.read(header_size + (group * group_size),
group_size))
name = name.rstrip(b"\x00")
groups[name] = tag_location
memory = groups[b"memory"]
tags_read = False
offset = memory
tags = {}
while not tags_read:
flags = ord(meta_layer.read(offset, 1))
name_len = ord(meta_layer.read(offset + 1, 1))
tags_read = (flags == 0) and (name_len == 0)
if not tags_read:
name = self._context.object("string", layer_name = self._meta_layer, offset = offset + 2,
max_length = name_len)
indicies_len = (flags >> 6) & 3
indicies = self._context.object("array",
count = indicies_len,
subtype = self.context.symbol_space.get_type("unsigned int"),
offset = 2 + name_len,
layer_name = self._meta_layer)
offset += 2 + name_len + (indicies_len * struct.calcsize("I"))
data = self._context.object("unsigned int", layer_name = self._meta_layer, offset = offset)
offset += self._context.symbol_space.get_type("unsigned int").size
tags[name] = (flags, indicies, data)
for region in range(tags["regionsCount"][2]):
offset = tags["regionPPN"][1][region]
mapped_offset = tags["regionPageNum"][1][region]
length = tags["regionSize"][1][region]
self._segments.append((offset, mapped_offset, length))
@property
def dependencies(self):
return [self._base_layer, self._meta_layer]
@classmethod
def get_requirements(cls):
"""This vmware translation layer always requires a separate metadata layer"""
return [requirements.TranslationLayerRequirement(name = 'base_layer',
optional = False),
requirements.TranslationLayerRequirement(name = 'meta_layer',
optional = False)
]
class VmwareStacker(interfaces.automagic.StackerLayerInterface):
@classmethod
def stack(cls, context, layer_name):
"""Attempt to stack this based on the starting information"""
if not isinstance(context.memory[layer_name], physical.FileLayer):
return
if not context.config.get("automagic.general.single_location", None):
return
location = parse.urlparse(context.config["automagic.general.single_location"])
if location.path.endswith(".vmem"):
vmss = location.path[:-5] + ".vmss"
vmsn = location.path[:-5] + ".vmsn"
current_layer_name = context.memory.free_layer_name("VmwareMetaLayer")
current_config_path = interfaces.configuration.path_join("automagic", "layer_stacker", "stack",
current_layer_name)
if os.path.exists(vmss):
context.config[interfaces.configuration.path_join(current_config_path, "filename")] = vmss
context.memory.add_layer(physical.FileLayer(context, current_config_path, current_layer_name))
elif os.path.exists(vmsn):
context.config[interfaces.configuration.path_join(current_config_path, "filename")] = vmss
context.memory.add_layer(physical.FileLayer(context, current_config_path, current_layer_name))
else:
return
new_layer_name = context.memory.free_layer_name("VmwareLayer")
context.config[interfaces.configuration.path_join(current_config_path, "base_layer")] = layer_name
context.config[
interfaces.configuration.path_join(current_config_path, "meta_layer")] = current_layer_name
new_layer = VmwareLayer(context, current_config_path, new_layer_name)
return new_layer