Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix VMware layer tag reading #429

Merged
merged 2 commits into from
Jan 21, 2021
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions volatility/framework/layers/vmware.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ def _read_header(self) -> None:
if magic not in [b"\xD2\xBE\xD2\xBE"]:
cstation marked this conversation as resolved.
Show resolved Hide resolved
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)

Expand Down Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this confuses me, since it looks like we'd be doing this twice? Can you walk me through what's going on here please?

Copy link
Contributor Author

@cstation cstation Jan 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to clearify this a bit more in the next commit. Most tags have a data_len of 4 or 8, which are the regular cases and easy to handle. The layout looks as follows:

flags name_len name indices data
1 1 name_len 4 * indices_len data_len

Some tags however, have a data_len of 62 or 63, which indicate a longer datastream. The layout is than as follows:

flags name_len name indices data_size data_mem_size padding? data
1 1 name_len 4 * indices_len 4 or 8 4 or 8 2 data_size

The 4 or 8 (which I set as data_len) is version dependent, so this is where the version comes in. Difference between data_size and data_mem_size should occur in cases where the data is compressed (data_size < data_mem_size).

I based this mostly on Volatility 2.x-code and the original parser of the same author.

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")
Expand Down