-
Notifications
You must be signed in to change notification settings - Fork 1.3k
VMware Snapshot File
Volatility can analyze VMware saved state (.vmss) and VMware snapshot (.vmsn) files. This capability was researched and introduced by Nir Izraeli and the AS is modeled after his vmsnparser project. Saved state and snapshot files are not the same as typical .vmem files that most everyone is familiar with. Rather, these .vmss/.vmsn contain a fairly complex structure layout which contains the physical memory runs, the VM configuration data, CPU registers, and even PNG thumbnails of the VM's screen.
While some VMware products store guest memory in .vmem files, other products (such as ESX) create these .vmsn or .vmss files when you suspend or take snapshots of running virtual machines. Since ESX is typically used for larger virtualization environments (compared to VMware Fusion or VMware Desktop), the capability to analyze .vmss/.vmsn can be critical in corporate IR/forensics.
You can convert a .vmss/.vmsn to a raw dd-style memory dump by extracting the physical memory runs to a separate file. To do this, use the imagecopy plugin.
At offset 0 of the .vmss/.vmsn file, there's a _VMWARE_HEADER
structure, which looks like this:
>>> dt("_VMWARE_HEADER")
'_VMWARE_HEADER' (12 bytes)
0x0 : Magic ['unsigned int']
0x8 : GroupCount ['unsigned int']
0xc : Groups ['array', <function <lambda> at 0x1046b7320>, ['_VMWARE_GROUP']]
As you can see, there's a magic value which must be 0xbed2bed0, 0xbad1bad1, 0xbed2bed2, or 0xbed3bed3 for the file to be considered valid. There is an array of _VMWARE_GROUP
structures, which look like this:
>>> dt("_VMWARE_GROUP")
'_VMWARE_GROUP' (80 bytes)
0x0 : Name ['String', {'length': 64, 'encoding': 'utf8'}]
0x40 : TagsOffset ['unsigned long long']
Thus the groups have a name and a 64-bit offset to an array of _VMWARE_TAG
structures:
>>> dt("_VMWARE_TAG")
'_VMWARE_TAG' (None bytes)
0x0 : Flags ['unsigned char']
0x1 : NameLength ['unsigned char']
0x2 : Name ['String', {'length': <function <lambda> at 0x1046b7398>, 'encoding': 'utf8'}]
The tag structures are a bit more complex than others. They have a name, a Flags field which devotes some bits to the length of the data associated with the tag, and a set of indices (not shown) which allow you to distinguish between multiple tags with the same name within a group.
The data for a tag follows the _VMWARE_TAG
structure, however there are a few intricacies that Nir researched. If you need details, see the source code. If the system has less than 4 GB of RAM, there will be a single physical memory run stored in a group named "memory" and a tag named "Memory" using indices [0][0]
. For systems with greater than 4 GB of RAM, there will be multiple runs, also in a group named "memory" but including tags named "Memory", "regionPPN", "regionPageNum", and "regionSize."
You can dump meta-data from .vmss/.vmsn files using the vmwareinfo plugin. If the data in a tag is 1, 2, 4, or 8 bytes, it's formatted as a number. If its more than 8 bytes and you supply --verbose to the plugin, you'll get a hexdump.
$ python vol.py -f ~/Desktop/Win7SP1x64-d8737a34.vmss vmwareinfo --verbose | less
Magic: 0xbad1bad1 (Version 1)
Group count: 0x5c
File Offset PhysMem Offset Size
----------- -------------- ----------
0x000010000 0x000000000000 0xc0000000
0x0c0010000 0x000100000000 0xc0000000
DataOffset DataSize Name Value
---------- ---------- -------------------------------------------------- -----
0x00001cd9 0x4 Checkpoint/fileversion 0xa
0x00001cfc 0x100 Checkpoint/ProductName
0x00001cfc 56 4d 77 61 72 65 20 45 53 58 00 00 00 00 00 00 VMware.ESX......
0x00001d0c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
[snip]
0x00001e1d 0x100 Checkpoint/VersionNumber
0x00001e1d 34 2e 31 2e 30 00 00 00 00 00 00 00 00 00 00 00 4.1.0...........
0x00001e2d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
[snip]
0x00002046 0x4 Checkpoint/Platform 0x1
0x00002055 0x4 Checkpoint/usageMode 0x1
0x00002062 0x4 Checkpoint/memSize 0x1800
0x00002071 0x4 Checkpoint/maxFBSize 0x800000
0x00002085 0x4 cpu/cpu:numVCPUs 0x1
0x00002095 0x4 cpu/eflags[0] 0x86
0x000020a2 0x8 cpu/rip[0] 0xfffff80002c1c0ba
0x000020b3 0x4 cpu/eip[0] 0x2c1c0ba
0x000020c3 0x1 cpu/halted[0] 0
[snip]
0x00005eea 0x4 cpu/CR[0][0] 0x80050031
0x00005efa 0x4 cpu/CR[0][1] 0x0
0x00005f0a 0x4 cpu/CR[0][2] 0x865eb08
0x00005f1a 0x4 cpu/CR[0][3] 0x187000
0x00005f2a 0x4 cpu/CR[0][4] 0x6f8
0x00005f3c 0x8 cpu/DR64[0][0] 0x0
[snip]
0x00006020 0x8 cpu/DR64[0][6] 0xffff0ff0
0x00006034 0x4 cpu/DR[0][6] 0xffff0ff0
0x00006046 0x8 cpu/DR64[0][7] 0x400
0x0000605a 0x4 cpu/DR[0][7] 0x400
0x0000606c 0x2 cpu/GDTR[0][0] 127
0x0000607c 0x4 cpu/GDTR[0][1] 0x3cd5000
0x0000608e 0x4 cpu/GDTR[0][2] 0xfffff800
0x000060a0 0x2 cpu/IDTR[0][0] 4095
0x000060b0 0x4 cpu/IDTR[0][1] 0x3cd5080
0x000060c2 0x4 cpu/IDTR[0][2] 0xfffff800
[snip]
0x180011963 0x2c29 Snapshot/cfgFile
0x180011953 2e 65 6e 63 6f 64 69 6e 67 20 3d 20 22 55 54 46 .encoding.=."UTF
0x180011963 2d 38 22 0a 63 6f 6e 66 69 67 2e 76 65 72 73 69 -8".config.versi
0x180011973 6f 6e 20 3d 20 22 38 22 0a 76 69 72 74 75 61 6c on.=."8".virtual
0x180011983 48 57 2e 76 65 72 73 69 6f 6e 20 3d 20 22 37 22 HW.version.=."7"
0x180011993 0a 70 63 69 42 72 69 64 67 65 30 2e 70 72 65 73 .pciBridge0.pres
0x1800119a3 65 6e 74 20 3d 20 22 74 72 75 65 22 0a 70 63 69 ent.=."true".pci
0x1800119b3 42 72 69 64 67 65 34 2e 70 72 65 73 65 6e 74 20 Bridge4.present.
0x1800119c3 3d 20 22 74 72 75 65 22 0a 70 63 69 42 72 69 64 =."true".pciBrid
0x1800119d3 67 65 34 2e 76 69 72 74 75 61 6c 44 65 76 20 3d ge4.virtualDev.=
0x1800119e3 20 22 70 63 69 65 52 6f 6f 74 50 6f 72 74 22 0a ."pcieRootPort".
Volatility Foundation
Getting Started
- FAQ
- Installation
- Linux
- Mac
- Android
- Basic Usage
- 2.6 Win Profiles
- Encrypted KDBG
- Pyinstaller Builds
- Unified Output
Command References
Development
Miscellaneous
Physical Address Spaces