dissect.hypervisor 3.21.dev2__tar.gz → 3.21.dev4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/PKG-INFO +1 -1
- dissect_hypervisor-3.21.dev4/dissect/hypervisor/descriptor/vbox.py +226 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/vmdk.py +4 -2
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect.hypervisor.egg-info/PKG-INFO +1 -1
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect.hypervisor.egg-info/SOURCES.txt +3 -1
- dissect_hypervisor-3.21.dev4/tests/_data/descriptor/vbox/GOAD-DC01.vbox +201 -0
- dissect_hypervisor-3.21.dev4/tests/_data/descriptor/vbox/encrypted.vbox +103 -0
- dissect_hypervisor-3.21.dev4/tests/_util.py +7 -0
- dissect_hypervisor-3.21.dev4/tests/descriptor/test_hyperv.py +64 -0
- dissect_hypervisor-3.21.dev4/tests/descriptor/test_vbox.py +69 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/descriptor/test_vmx.py +3 -4
- dissect_hypervisor-3.21.dev4/tests/disk/test_asif.py +19 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/disk/test_hdd.py +18 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/disk/test_qcow2.py +44 -31
- dissect_hypervisor-3.21.dev4/tests/disk/test_vhd.py +65 -0
- dissect_hypervisor-3.21.dev4/tests/disk/test_vhdx.py +110 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/disk/test_vmdk.py +55 -14
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/util/test_envelope.py +12 -9
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/util/test_vmtar.py +19 -18
- dissect_hypervisor-3.21.dev2/dissect/hypervisor/descriptor/vbox.py +0 -22
- dissect_hypervisor-3.21.dev2/tests/conftest.py +0 -133
- dissect_hypervisor-3.21.dev2/tests/descriptor/test_hyperv.py +0 -63
- dissect_hypervisor-3.21.dev2/tests/descriptor/test_vbox.py +0 -43
- dissect_hypervisor-3.21.dev2/tests/disk/test_asif.py +0 -17
- dissect_hypervisor-3.21.dev2/tests/disk/test_vhd.py +0 -62
- dissect_hypervisor-3.21.dev2/tests/disk/test_vhdx.py +0 -104
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/.git-blame-ignore-revs +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/COPYRIGHT +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/LICENSE +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/MANIFEST.in +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/README.md +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/__init__.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/descriptor/__init__.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/descriptor/c_hyperv.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/descriptor/hyperv.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/descriptor/ovf.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/descriptor/pvs.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/descriptor/vmx.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/__init__.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/asif.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/c_asif.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/c_asif.pyi +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/c_hdd.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/c_qcow2.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/c_qcow2.pyi +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/c_vdi.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/c_vhd.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/c_vhdx.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/c_vmdk.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/hdd.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/qcow2.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/vdi.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/vhd.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/vhdx.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/exceptions.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/tools/__init__.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/tools/envelope.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/tools/vmtar.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/util/__init__.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/util/envelope.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/util/vmtar.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect.hypervisor.egg-info/dependency_links.txt +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect.hypervisor.egg-info/entry_points.txt +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect.hypervisor.egg-info/requires.txt +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect.hypervisor.egg-info/top_level.txt +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/pyproject.toml +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/setup.cfg +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/__init__.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/descriptor/hyperv/test.VMRS +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/descriptor/hyperv/test.vmcx +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/descriptor/vmx/encrypted.vmx +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/asif/basic.asif.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/hdd/expanding.hdd/DiskDescriptor.xml +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/hdd/expanding.hdd/expanding.hdd +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/hdd/expanding.hdd/expanding.hdd.0.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/hdd/plain.hdd/DiskDescriptor.xml +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/hdd/plain.hdd/plain.hdd +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/hdd/plain.hdd/plain.hdd.0.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/hdd/split.hdd/DiskDescriptor.xml +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/hdd/split.hdd/split.hdd +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/hdd/split.hdd/split.hdd.0.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/hdd/split.hdd/split.hdd.1.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/hdd/split.hdd/split.hdd.2.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/hdd/split.hdd/split.hdd.3.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/hdd/split.hdd/split.hdd.4.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/hdd/split.hdd/split.hdd.5.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/qcow2/backing-chain-1.qcow2.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/qcow2/backing-chain-2.qcow2.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/qcow2/backing-chain-3.qcow2.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/qcow2/basic-zstd.qcow2.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/qcow2/basic.qcow2.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/qcow2/data-file.bin.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/qcow2/data-file.qcow2.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/qcow2/snapshot.qcow2.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/vhd/dynamic.vhd.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/vhd/fixed.vhd.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/vhdx/differencing.avhdx.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/vhdx/dynamic.vhdx.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/vhdx/fixed.vhdx.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/disk/vmdk/sesparse.vmdk.gz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/util/envelope/encryption.info +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/util/envelope/local.tgz.ve +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_data/util/vmtar/test.vgz +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_docs/Makefile +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_docs/conf.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/_docs/index.rst +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/descriptor/__init__.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/descriptor/test_ovf.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/descriptor/test_pvs.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/disk/__init__.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tests/util/__init__.py +0 -0
- {dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dissect.hypervisor
|
|
3
|
-
Version: 3.21.
|
|
3
|
+
Version: 3.21.dev4
|
|
4
4
|
Summary: A Dissect module implementing parsers for various hypervisor disk, backup and configuration files
|
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
|
6
6
|
License-Expression: AGPL-3.0-or-later
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from functools import cached_property
|
|
5
|
+
from typing import TYPE_CHECKING, TextIO
|
|
6
|
+
from uuid import UUID
|
|
7
|
+
|
|
8
|
+
from defusedxml import ElementTree
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from xml.etree.ElementTree import Element
|
|
12
|
+
|
|
13
|
+
NS = "{http://www.virtualbox.org/}"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class VBox:
|
|
17
|
+
"""VirtualBox XML descriptor parser.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
fh: A file-like object of the VirtualBox XML descriptor.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, fh: TextIO):
|
|
24
|
+
self._xml: Element = ElementTree.fromstring(fh.read())
|
|
25
|
+
if self._xml.tag != f"{NS}VirtualBox":
|
|
26
|
+
raise ValueError("Invalid VirtualBox XML descriptor: root element is not VirtualBox")
|
|
27
|
+
|
|
28
|
+
if (machine := self._xml.find(f"./{NS}Machine")) is None:
|
|
29
|
+
raise ValueError("Invalid VirtualBox XML descriptor: no Machine element found")
|
|
30
|
+
|
|
31
|
+
if machine.find(f"./{NS}Hardware") is None:
|
|
32
|
+
raise ValueError("Invalid VirtualBox XML descriptor: no Hardware element found")
|
|
33
|
+
|
|
34
|
+
self.machine = Machine(self, machine)
|
|
35
|
+
|
|
36
|
+
def __repr__(self) -> str:
|
|
37
|
+
return f"<VBox uuid={self.uuid} name={self.name}>"
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def uuid(self) -> UUID | None:
|
|
41
|
+
"""The VM UUID."""
|
|
42
|
+
return self.machine.uuid
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def name(self) -> str | None:
|
|
46
|
+
"""The VM name."""
|
|
47
|
+
return self.machine.name
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def media(self) -> dict[UUID, HardDisk]:
|
|
51
|
+
"""The media (disks) registry."""
|
|
52
|
+
return self.machine.media
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def hardware(self) -> Hardware:
|
|
56
|
+
"""The current machine hardware state."""
|
|
57
|
+
return self.machine.hardware
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def snapshots(self) -> dict[UUID, Snapshot]:
|
|
61
|
+
"""All snapshots."""
|
|
62
|
+
return self.machine.snapshots
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class Machine:
|
|
66
|
+
def __init__(self, vbox: VBox, element: Element):
|
|
67
|
+
self.vbox = vbox
|
|
68
|
+
self.element = element
|
|
69
|
+
|
|
70
|
+
def __repr__(self) -> str:
|
|
71
|
+
return f"<Machine uuid={self.uuid} name={self.name}>"
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def uuid(self) -> UUID:
|
|
75
|
+
"""The machine UUID."""
|
|
76
|
+
return UUID(self.element.get("uuid").strip("{}"))
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def name(self) -> str:
|
|
80
|
+
"""The machine name."""
|
|
81
|
+
return self.element.get("name")
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def current_snapshot(self) -> UUID | None:
|
|
85
|
+
"""The current snapshot UUID."""
|
|
86
|
+
if (value := self.element.get("currentSnapshot")) is not None:
|
|
87
|
+
return UUID(value.strip("{}"))
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
@cached_property
|
|
91
|
+
def media(self) -> dict[UUID, HardDisk]:
|
|
92
|
+
"""The media (disks) registry."""
|
|
93
|
+
result = {}
|
|
94
|
+
|
|
95
|
+
stack = [(None, element) for element in self.element.find(f"./{NS}MediaRegistry/{NS}HardDisks")]
|
|
96
|
+
while stack:
|
|
97
|
+
parent, element = stack.pop()
|
|
98
|
+
hdd = HardDisk(self, element, parent)
|
|
99
|
+
result[hdd.uuid] = hdd
|
|
100
|
+
|
|
101
|
+
stack.extend([(hdd, child) for child in element.findall(f"./{NS}HardDisk")])
|
|
102
|
+
|
|
103
|
+
return result
|
|
104
|
+
|
|
105
|
+
@cached_property
|
|
106
|
+
def hardware(self) -> Hardware:
|
|
107
|
+
"""The machine hardware state."""
|
|
108
|
+
return Hardware(self.vbox, self.element.find(f"./{NS}Hardware"))
|
|
109
|
+
|
|
110
|
+
@cached_property
|
|
111
|
+
def snapshots(self) -> dict[UUID, Snapshot]:
|
|
112
|
+
"""All snapshots."""
|
|
113
|
+
result = {}
|
|
114
|
+
|
|
115
|
+
if (element := self.element.find(f"./{NS}Snapshot")) is None:
|
|
116
|
+
return result
|
|
117
|
+
|
|
118
|
+
stack = [(None, element)]
|
|
119
|
+
while stack:
|
|
120
|
+
parent, element = stack.pop()
|
|
121
|
+
snapshot = Snapshot(self.vbox, element, parent)
|
|
122
|
+
result[snapshot.uuid] = snapshot
|
|
123
|
+
|
|
124
|
+
if (snapshots := element.find(f"./{NS}Snapshots")) is not None:
|
|
125
|
+
stack.extend([(snapshot, child) for child in list(snapshots)])
|
|
126
|
+
|
|
127
|
+
return result
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def parent(self) -> Snapshot | None:
|
|
131
|
+
if (uuid := self.current_snapshot) is not None:
|
|
132
|
+
return self.vbox.snapshots[uuid]
|
|
133
|
+
return None
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class HardDisk:
|
|
137
|
+
def __init__(self, vbox: VBox, element: Element, parent: HardDisk | None = None):
|
|
138
|
+
self.vbox = vbox
|
|
139
|
+
self.element = element
|
|
140
|
+
self.parent = parent
|
|
141
|
+
|
|
142
|
+
def __repr__(self) -> str:
|
|
143
|
+
return f"<HardDisk uuid={self.uuid} location={self.location}>"
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def uuid(self) -> UUID:
|
|
147
|
+
"""The disk UUID."""
|
|
148
|
+
return UUID(self.element.get("uuid").strip("{}"))
|
|
149
|
+
|
|
150
|
+
@property
|
|
151
|
+
def location(self) -> str:
|
|
152
|
+
"""The disk location."""
|
|
153
|
+
return self.element.get("location")
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def type(self) -> str | None:
|
|
157
|
+
"""The disk type."""
|
|
158
|
+
return self.element.get("type")
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def format(self) -> str:
|
|
162
|
+
"""The disk format."""
|
|
163
|
+
return self.element.get("format")
|
|
164
|
+
|
|
165
|
+
@cached_property
|
|
166
|
+
def properties(self) -> dict[str, str]:
|
|
167
|
+
"""The disk properties."""
|
|
168
|
+
return {prop.get("name"): prop.get("value") for prop in self.element.findall(f"./{NS}Property")}
|
|
169
|
+
|
|
170
|
+
@property
|
|
171
|
+
def is_encrypted(self) -> bool:
|
|
172
|
+
"""Whether the disk is encrypted."""
|
|
173
|
+
disk = self
|
|
174
|
+
while disk is not None:
|
|
175
|
+
if "CRYPT/KeyId" in disk.properties or "CRYPT/KeyStore" in disk.properties:
|
|
176
|
+
return True
|
|
177
|
+
disk = disk.parent
|
|
178
|
+
|
|
179
|
+
return False
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
class Snapshot:
|
|
183
|
+
def __init__(self, vbox: VBox, element: Element, parent: Snapshot | Machine | None = None):
|
|
184
|
+
self.vbox = vbox
|
|
185
|
+
self.element = element
|
|
186
|
+
self.parent = parent
|
|
187
|
+
|
|
188
|
+
def __repr__(self) -> str:
|
|
189
|
+
return f"<Snapshot uuid={self.uuid} name={self.name}>"
|
|
190
|
+
|
|
191
|
+
@property
|
|
192
|
+
def uuid(self) -> UUID:
|
|
193
|
+
"""The snapshot UUID."""
|
|
194
|
+
return UUID(self.element.get("uuid").strip("{}"))
|
|
195
|
+
|
|
196
|
+
@property
|
|
197
|
+
def name(self) -> str:
|
|
198
|
+
"""The snapshot name."""
|
|
199
|
+
return self.element.get("name")
|
|
200
|
+
|
|
201
|
+
@property
|
|
202
|
+
def ts(self) -> datetime:
|
|
203
|
+
"""The snapshot timestamp."""
|
|
204
|
+
return datetime.strptime(self.element.get("timeStamp"), "%Y-%m-%dT%H:%M:%S%z")
|
|
205
|
+
|
|
206
|
+
@cached_property
|
|
207
|
+
def hardware(self) -> Hardware:
|
|
208
|
+
"""The snapshot hardware state."""
|
|
209
|
+
return Hardware(self.vbox, self.element.find(f"./{NS}Hardware"))
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
class Hardware:
|
|
213
|
+
def __init__(self, vbox: VBox, element: Element):
|
|
214
|
+
self.vbox = vbox
|
|
215
|
+
self.element = element
|
|
216
|
+
|
|
217
|
+
def __repr__(self) -> str:
|
|
218
|
+
return f"<Hardware disks={len(self.disks)}>"
|
|
219
|
+
|
|
220
|
+
@property
|
|
221
|
+
def disks(self) -> list[HardDisk]:
|
|
222
|
+
"""All attached hard disks."""
|
|
223
|
+
images = self.element.findall(
|
|
224
|
+
f"./{NS}StorageControllers/{NS}StorageController/{NS}AttachedDevice[@type='HardDisk']/{NS}Image"
|
|
225
|
+
)
|
|
226
|
+
return [self.vbox.media[UUID(image.get("uuid").strip("{}"))] for image in images]
|
{dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect/hypervisor/disk/vmdk.py
RENAMED
|
@@ -535,8 +535,10 @@ def open_parent(path: Path, filename_hint: str) -> VMDK:
|
|
|
535
535
|
hint_path, _, filename = filename_hint.rpartition("/")
|
|
536
536
|
filepath = path.joinpath(filename)
|
|
537
537
|
if not filepath.exists():
|
|
538
|
-
|
|
539
|
-
|
|
538
|
+
filepath = path.joinpath(filename_hint)
|
|
539
|
+
if not filepath.exists():
|
|
540
|
+
_, _, hint_path_name = hint_path.rpartition("/")
|
|
541
|
+
filepath = path.parent.joinpath(hint_path_name).joinpath(filename)
|
|
540
542
|
vmdk = VMDK(filepath)
|
|
541
543
|
except Exception as err:
|
|
542
544
|
raise IOError(f"Failed to open parent disk with hint {filename_hint} from path {path}: {err}")
|
{dissect_hypervisor-3.21.dev2 → dissect_hypervisor-3.21.dev4}/dissect.hypervisor.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dissect.hypervisor
|
|
3
|
-
Version: 3.21.
|
|
3
|
+
Version: 3.21.dev4
|
|
4
4
|
Summary: A Dissect module implementing parsers for various hypervisor disk, backup and configuration files
|
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
|
6
6
|
License-Expression: AGPL-3.0-or-later
|
|
@@ -44,9 +44,11 @@ dissect/hypervisor/util/__init__.py
|
|
|
44
44
|
dissect/hypervisor/util/envelope.py
|
|
45
45
|
dissect/hypervisor/util/vmtar.py
|
|
46
46
|
tests/__init__.py
|
|
47
|
-
tests/
|
|
47
|
+
tests/_util.py
|
|
48
48
|
tests/_data/descriptor/hyperv/test.VMRS
|
|
49
49
|
tests/_data/descriptor/hyperv/test.vmcx
|
|
50
|
+
tests/_data/descriptor/vbox/GOAD-DC01.vbox
|
|
51
|
+
tests/_data/descriptor/vbox/encrypted.vbox
|
|
50
52
|
tests/_data/descriptor/vmx/encrypted.vmx
|
|
51
53
|
tests/_data/disk/asif/basic.asif.gz
|
|
52
54
|
tests/_data/disk/hdd/expanding.hdd/DiskDescriptor.xml
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<!--
|
|
3
|
+
** DO NOT EDIT THIS FILE.
|
|
4
|
+
** If you make changes to this file while any VirtualBox related application
|
|
5
|
+
** is running, your changes will be overwritten later, without taking effect.
|
|
6
|
+
** Use VBoxManage or the VirtualBox Manager GUI to make changes.
|
|
7
|
+
**
|
|
8
|
+
** Written by VirtualBox 7.2.4_RPMFUSION (r170995)
|
|
9
|
+
-->
|
|
10
|
+
<VirtualBox xmlns="http://www.virtualbox.org/" version="1.19-linux">
|
|
11
|
+
<Machine uuid="{a6277950-3d1b-45d3-b2fd-dc1f385027e1}" name="GOAD-DC01" OSType="Windows2016_64" currentSnapshot="{264ccd7e-9ffd-45ba-bd0e-4e1968d3355a}" snapshotFolder="Snapshots" lastStateChange="2025-12-19T21:00:43Z">
|
|
12
|
+
<MediaRegistry>
|
|
13
|
+
<HardDisks>
|
|
14
|
+
<HardDisk uuid="{0898f36f-01c3-4b43-8aeb-36ba7adaef95}" location="WindowsServer2019-disk001.vmdk" format="VMDK" type="Normal">
|
|
15
|
+
<HardDisk uuid="{3c72ec80-dc73-4448-a63e-97970cdd87e5}" location="Snapshots/{3c72ec80-dc73-4448-a63e-97970cdd87e5}.vmdk" format="VMDK">
|
|
16
|
+
<HardDisk uuid="{e6800503-8273-4f16-b584-c7ba2c1df698}" location="Snapshots/{e6800503-8273-4f16-b584-c7ba2c1df698}.vmdk" format="VMDK"/>
|
|
17
|
+
</HardDisk>
|
|
18
|
+
<!--
|
|
19
|
+
** I ignored the big warning above and edited this file anyway. Yes, I'm kind of a rebel.
|
|
20
|
+
** Don't tell VirtualBox about it, they get upset.
|
|
21
|
+
** Manually add a "tree" of snapshots for testing purposes.
|
|
22
|
+
-->
|
|
23
|
+
<HardDisk uuid="{35bf5129-1caa-4117-b20a-d73868d9d5d2}" location="Snapshots/{35bf5129-1caa-4117-b20a-d73868d9d5d2}.vmdk" format="VMDK">
|
|
24
|
+
<HardDisk uuid="{706a96fe-0e11-4985-af32-7561d26612d4}" location="Snapshots/{706a96fe-0e11-4985-af32-7561d26612d4}.vmdk" format="VMDK"/>
|
|
25
|
+
</HardDisk>
|
|
26
|
+
</HardDisk>
|
|
27
|
+
</HardDisks>
|
|
28
|
+
</MediaRegistry>
|
|
29
|
+
<Snapshot uuid="{95b1572d-c893-48f0-9bc9-6a01a0fd2cb6}" name="push_1766163705_7292" timeStamp="2025-12-19T17:01:46Z">
|
|
30
|
+
<Hardware>
|
|
31
|
+
<Memory RAMSize="3000"/>
|
|
32
|
+
<Boot>
|
|
33
|
+
<Order position="1" device="HardDisk"/>
|
|
34
|
+
<Order position="2" device="DVD"/>
|
|
35
|
+
<Order position="3" device="None"/>
|
|
36
|
+
<Order position="4" device="None"/>
|
|
37
|
+
</Boot>
|
|
38
|
+
<Display VRAMSize="128"/>
|
|
39
|
+
<RemoteDisplay enabled="true">
|
|
40
|
+
<VRDEProperties>
|
|
41
|
+
<Property name="TCP/Address" value="127.0.0.1"/>
|
|
42
|
+
<Property name="TCP/Ports" value="5902"/>
|
|
43
|
+
</VRDEProperties>
|
|
44
|
+
</RemoteDisplay>
|
|
45
|
+
<Firmware/>
|
|
46
|
+
<BIOS>
|
|
47
|
+
<IOAPIC enabled="true"/>
|
|
48
|
+
<SmbiosUuidLittleEndian enabled="true"/>
|
|
49
|
+
</BIOS>
|
|
50
|
+
<Network>
|
|
51
|
+
<Adapter slot="0" enabled="true" MACAddress="0800277AA2FC" type="82540EM">
|
|
52
|
+
<NAT localhost-reachable="true">
|
|
53
|
+
<DNS use-proxy="true"/>
|
|
54
|
+
<Forwarding name="ssh" proto="1" hostip="127.0.0.1" hostport="2222" guestport="22"/>
|
|
55
|
+
<Forwarding name="winrm" proto="1" hostip="127.0.0.1" hostport="55985" guestport="5985"/>
|
|
56
|
+
<Forwarding name="winrm-ssl" proto="1" hostip="127.0.0.1" hostport="55986" guestport="5986"/>
|
|
57
|
+
</NAT>
|
|
58
|
+
</Adapter>
|
|
59
|
+
<Adapter slot="1" enabled="true" MACAddress="0800278CC821" type="82540EM">
|
|
60
|
+
<DisabledModes>
|
|
61
|
+
<NAT localhost-reachable="true"/>
|
|
62
|
+
<InternalNetwork name="intnet"/>
|
|
63
|
+
<NATNetwork name="NatNetwork"/>
|
|
64
|
+
</DisabledModes>
|
|
65
|
+
<HostOnlyInterface name="vboxnet0"/>
|
|
66
|
+
</Adapter>
|
|
67
|
+
</Network>
|
|
68
|
+
<AudioAdapter driver="ALSA"/>
|
|
69
|
+
<Clipboard mode="Bidirectional"/>
|
|
70
|
+
<StorageControllers>
|
|
71
|
+
<StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
|
|
72
|
+
<AttachedDevice type="HardDisk" hotpluggable="false" port="0" device="0">
|
|
73
|
+
<Image uuid="{0898f36f-01c3-4b43-8aeb-36ba7adaef95}"/>
|
|
74
|
+
</AttachedDevice>
|
|
75
|
+
</StorageController>
|
|
76
|
+
</StorageControllers>
|
|
77
|
+
<RTC localOrUTC="UTC"/>
|
|
78
|
+
<CPU count="2">
|
|
79
|
+
<HardwareVirtExLargePages enabled="false"/>
|
|
80
|
+
<PAE enabled="true"/>
|
|
81
|
+
<LongMode enabled="true"/>
|
|
82
|
+
</CPU>
|
|
83
|
+
</Hardware>
|
|
84
|
+
<Snapshots>
|
|
85
|
+
<Snapshot uuid="{264ccd7e-9ffd-45ba-bd0e-4e1968d3355a}" name="push_1766170151_8843" timeStamp="2025-12-19T18:49:11Z">
|
|
86
|
+
<Hardware>
|
|
87
|
+
<Memory RAMSize="3000"/>
|
|
88
|
+
<Boot>
|
|
89
|
+
<Order position="1" device="HardDisk"/>
|
|
90
|
+
<Order position="2" device="DVD"/>
|
|
91
|
+
<Order position="3" device="None"/>
|
|
92
|
+
<Order position="4" device="None"/>
|
|
93
|
+
</Boot>
|
|
94
|
+
<Display VRAMSize="128"/>
|
|
95
|
+
<RemoteDisplay enabled="true">
|
|
96
|
+
<VRDEProperties>
|
|
97
|
+
<Property name="TCP/Address" value="127.0.0.1"/>
|
|
98
|
+
<Property name="TCP/Ports" value="5902"/>
|
|
99
|
+
</VRDEProperties>
|
|
100
|
+
</RemoteDisplay>
|
|
101
|
+
<Firmware/>
|
|
102
|
+
<BIOS>
|
|
103
|
+
<IOAPIC enabled="true"/>
|
|
104
|
+
<SmbiosUuidLittleEndian enabled="true"/>
|
|
105
|
+
</BIOS>
|
|
106
|
+
<Network>
|
|
107
|
+
<Adapter slot="0" enabled="true" MACAddress="0800277AA2FC" type="82540EM">
|
|
108
|
+
<NAT localhost-reachable="true">
|
|
109
|
+
<DNS use-proxy="true"/>
|
|
110
|
+
<Forwarding name="ssh" proto="1" hostip="127.0.0.1" hostport="2222" guestport="22"/>
|
|
111
|
+
<Forwarding name="winrm" proto="1" hostip="127.0.0.1" hostport="55985" guestport="5985"/>
|
|
112
|
+
<Forwarding name="winrm-ssl" proto="1" hostip="127.0.0.1" hostport="55986" guestport="5986"/>
|
|
113
|
+
</NAT>
|
|
114
|
+
</Adapter>
|
|
115
|
+
<Adapter slot="1" enabled="true" MACAddress="0800278CC821" type="82540EM">
|
|
116
|
+
<DisabledModes>
|
|
117
|
+
<NAT localhost-reachable="true"/>
|
|
118
|
+
<InternalNetwork name="intnet"/>
|
|
119
|
+
<NATNetwork name="NatNetwork"/>
|
|
120
|
+
</DisabledModes>
|
|
121
|
+
<HostOnlyInterface name="vboxnet0"/>
|
|
122
|
+
</Adapter>
|
|
123
|
+
</Network>
|
|
124
|
+
<AudioAdapter driver="ALSA"/>
|
|
125
|
+
<Clipboard mode="Bidirectional"/>
|
|
126
|
+
<StorageControllers>
|
|
127
|
+
<StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
|
|
128
|
+
<AttachedDevice type="HardDisk" hotpluggable="false" port="0" device="0">
|
|
129
|
+
<Image uuid="{3c72ec80-dc73-4448-a63e-97970cdd87e5}"/>
|
|
130
|
+
</AttachedDevice>
|
|
131
|
+
</StorageController>
|
|
132
|
+
</StorageControllers>
|
|
133
|
+
<RTC localOrUTC="UTC"/>
|
|
134
|
+
<CPU count="2">
|
|
135
|
+
<HardwareVirtExLargePages enabled="false"/>
|
|
136
|
+
<PAE enabled="true"/>
|
|
137
|
+
<LongMode enabled="true"/>
|
|
138
|
+
</CPU>
|
|
139
|
+
</Hardware>
|
|
140
|
+
</Snapshot>
|
|
141
|
+
</Snapshots>
|
|
142
|
+
</Snapshot>
|
|
143
|
+
<Hardware>
|
|
144
|
+
<Memory RAMSize="3000"/>
|
|
145
|
+
<Boot>
|
|
146
|
+
<Order position="1" device="HardDisk"/>
|
|
147
|
+
<Order position="2" device="DVD"/>
|
|
148
|
+
<Order position="3" device="None"/>
|
|
149
|
+
<Order position="4" device="None"/>
|
|
150
|
+
</Boot>
|
|
151
|
+
<Display VRAMSize="128"/>
|
|
152
|
+
<RemoteDisplay enabled="true">
|
|
153
|
+
<VRDEProperties>
|
|
154
|
+
<Property name="TCP/Address" value="127.0.0.1"/>
|
|
155
|
+
<Property name="TCP/Ports" value="5902"/>
|
|
156
|
+
</VRDEProperties>
|
|
157
|
+
</RemoteDisplay>
|
|
158
|
+
<Firmware/>
|
|
159
|
+
<BIOS>
|
|
160
|
+
<IOAPIC enabled="true"/>
|
|
161
|
+
<SmbiosUuidLittleEndian enabled="true"/>
|
|
162
|
+
</BIOS>
|
|
163
|
+
<Network>
|
|
164
|
+
<Adapter slot="0" enabled="true" MACAddress="0800277AA2FC" type="82540EM">
|
|
165
|
+
<NAT localhost-reachable="true">
|
|
166
|
+
<DNS use-proxy="true"/>
|
|
167
|
+
<Forwarding name="ssh" proto="1" hostip="127.0.0.1" hostport="2222" guestport="22"/>
|
|
168
|
+
<Forwarding name="winrm" proto="1" hostip="127.0.0.1" hostport="55985" guestport="5985"/>
|
|
169
|
+
<Forwarding name="winrm-ssl" proto="1" hostip="127.0.0.1" hostport="55986" guestport="5986"/>
|
|
170
|
+
</NAT>
|
|
171
|
+
</Adapter>
|
|
172
|
+
<Adapter slot="1" enabled="true" MACAddress="0800278CC821" type="82540EM">
|
|
173
|
+
<DisabledModes>
|
|
174
|
+
<NAT localhost-reachable="true"/>
|
|
175
|
+
<InternalNetwork name="intnet"/>
|
|
176
|
+
<NATNetwork name="NatNetwork"/>
|
|
177
|
+
</DisabledModes>
|
|
178
|
+
<HostOnlyInterface name="vboxnet0"/>
|
|
179
|
+
</Adapter>
|
|
180
|
+
</Network>
|
|
181
|
+
<AudioAdapter driver="ALSA"/>
|
|
182
|
+
<Clipboard mode="Bidirectional"/>
|
|
183
|
+
<StorageControllers>
|
|
184
|
+
<StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
|
|
185
|
+
<AttachedDevice type="HardDisk" hotpluggable="false" port="0" device="0">
|
|
186
|
+
<Image uuid="{e6800503-8273-4f16-b584-c7ba2c1df698}"/>
|
|
187
|
+
</AttachedDevice>
|
|
188
|
+
</StorageController>
|
|
189
|
+
</StorageControllers>
|
|
190
|
+
<RTC localOrUTC="UTC"/>
|
|
191
|
+
<CPU count="2">
|
|
192
|
+
<HardwareVirtExLargePages enabled="false"/>
|
|
193
|
+
<PAE enabled="true"/>
|
|
194
|
+
<LongMode enabled="true"/>
|
|
195
|
+
</CPU>
|
|
196
|
+
</Hardware>
|
|
197
|
+
<Groups>
|
|
198
|
+
<Group name="/GOAD"/>
|
|
199
|
+
</Groups>
|
|
200
|
+
</Machine>
|
|
201
|
+
</VirtualBox>
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<!--
|
|
3
|
+
** DO NOT EDIT THIS FILE.
|
|
4
|
+
** If you make changes to this file while any VirtualBox related application
|
|
5
|
+
** is running, your changes will be overwritten later, without taking effect.
|
|
6
|
+
** Use VBoxManage or the VirtualBox Manager GUI to make changes.
|
|
7
|
+
**
|
|
8
|
+
** Written by VirtualBox 7.2.4 (r170995)
|
|
9
|
+
-->
|
|
10
|
+
<VirtualBox xmlns="http://www.virtualbox.org/" version="1.19-linux">
|
|
11
|
+
<Machine uuid="{366f53dd-1710-434e-8021-1f91b0405b65}" name="encrypted test" OSType="Windows11_64" currentSnapshot="{cfbdc706-6561-44e8-8f3a-236df446b808}" snapshotFolder="Snapshots" lastStateChange="2026-01-20T13:01:05Z">
|
|
12
|
+
<MediaRegistry>
|
|
13
|
+
<HardDisks>
|
|
14
|
+
<HardDisk uuid="{24cdb8e9-35d6-42f2-aa17-c2d78bf1e1de}" location="encrypted test.vdi" format="VDI" type="Normal">
|
|
15
|
+
<Property name="CRYPT/KeyId" value="encrypted test"/>
|
|
16
|
+
<Property name="CRYPT/KeyStore" value="U0NORQABQUVTLVhUUzI1Ni1QTEFJTjY0AAAAAAAAAAAAAAAAAABQQktERjItU0hB MjU2AAAAAAAAAAAAAAAAAAAAAAAAAEAAAACOEfHKuPU9MHJktr3UZAxmuL+epJsk SRfK3vhbPnb4USAAAABCoUSl+kb0+6OzG8N3wo16bru7UNsjHzIsB+OPBfZUPiBO AACa0Cbl1wJz09E5i8U10V3xElnY8iAIwEqSwVWpwFPiYsAJDgBAAAAAgcb2cMho wWkDpje3pQHrn62sH8oTyr4+wXaJoFUEreymEuIXYlnB+jeLjQDWEEIs9DUIXfiP PWw3Fph9h0a3lA=="/>
|
|
17
|
+
<HardDisk uuid="{742e6d0f-8896-4aa6-97f4-e05d70e73029}" location="Snapshots/{742e6d0f-8896-4aa6-97f4-e05d70e73029}.vdi" format="VDI"/>
|
|
18
|
+
</HardDisk>
|
|
19
|
+
<HardDisk uuid="{1db0b9fe-36c2-44e8-9b7c-61fa5b6d1462}" location="encrypted test_1.vdi" format="VDI" type="Normal"/>
|
|
20
|
+
</HardDisks>
|
|
21
|
+
</MediaRegistry>
|
|
22
|
+
<Snapshot uuid="{cfbdc706-6561-44e8-8f3a-236df446b808}" name="Encryption" timeStamp="2026-01-20T13:01:05Z">
|
|
23
|
+
<Hardware>
|
|
24
|
+
<Memory RAMSize="4096"/>
|
|
25
|
+
<HID Pointing="USBTablet"/>
|
|
26
|
+
<Display controller="VBoxSVGA" VRAMSize="128"/>
|
|
27
|
+
<Firmware type="EFI"/>
|
|
28
|
+
<BIOS>
|
|
29
|
+
<IOAPIC enabled="true"/>
|
|
30
|
+
<NVRAM path="Snapshots/2026-01-20T13-01-05-717390000Z.nvram"/>
|
|
31
|
+
<SmbiosUuidLittleEndian enabled="true"/>
|
|
32
|
+
<AutoSerialNumGen enabled="true"/>
|
|
33
|
+
</BIOS>
|
|
34
|
+
<TrustedPlatformModule type="v2_0" location=""/>
|
|
35
|
+
<USB>
|
|
36
|
+
<Controllers>
|
|
37
|
+
<Controller name="XHCI" type="XHCI"/>
|
|
38
|
+
</Controllers>
|
|
39
|
+
</USB>
|
|
40
|
+
<Network>
|
|
41
|
+
<Adapter slot="0" enabled="true" MACAddress="0800274C9CFB" type="82540EM">
|
|
42
|
+
<NAT localhost-reachable="true"/>
|
|
43
|
+
</Adapter>
|
|
44
|
+
</Network>
|
|
45
|
+
<AudioAdapter controller="HDA" useDefault="true" driver="ALSA" enabled="true" enabledOut="true"/>
|
|
46
|
+
<Clipboard/>
|
|
47
|
+
<StorageControllers>
|
|
48
|
+
<StorageController name="SATA" type="AHCI" PortCount="2" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3">
|
|
49
|
+
<AttachedDevice type="HardDisk" hotpluggable="false" port="0" device="0">
|
|
50
|
+
<Image uuid="{24cdb8e9-35d6-42f2-aa17-c2d78bf1e1de}"/>
|
|
51
|
+
</AttachedDevice>
|
|
52
|
+
<AttachedDevice passthrough="false" type="DVD" hotpluggable="false" port="1" device="0"/>
|
|
53
|
+
</StorageController>
|
|
54
|
+
</StorageControllers>
|
|
55
|
+
<CPU count="2">
|
|
56
|
+
<HardwareVirtExLargePages enabled="false"/>
|
|
57
|
+
<PAE enabled="false"/>
|
|
58
|
+
<LongMode enabled="true"/>
|
|
59
|
+
</CPU>
|
|
60
|
+
</Hardware>
|
|
61
|
+
</Snapshot>
|
|
62
|
+
<Hardware>
|
|
63
|
+
<Memory RAMSize="4096"/>
|
|
64
|
+
<HID Pointing="USBTablet"/>
|
|
65
|
+
<Display controller="VBoxSVGA" VRAMSize="128"/>
|
|
66
|
+
<Firmware type="EFI"/>
|
|
67
|
+
<BIOS>
|
|
68
|
+
<IOAPIC enabled="true"/>
|
|
69
|
+
<SmbiosUuidLittleEndian enabled="true"/>
|
|
70
|
+
<AutoSerialNumGen enabled="true"/>
|
|
71
|
+
</BIOS>
|
|
72
|
+
<TrustedPlatformModule type="v2_0" location=""/>
|
|
73
|
+
<USB>
|
|
74
|
+
<Controllers>
|
|
75
|
+
<Controller name="XHCI" type="XHCI"/>
|
|
76
|
+
</Controllers>
|
|
77
|
+
</USB>
|
|
78
|
+
<Network>
|
|
79
|
+
<Adapter slot="0" enabled="true" MACAddress="0800274C9CFB" type="82540EM">
|
|
80
|
+
<NAT localhost-reachable="true"/>
|
|
81
|
+
</Adapter>
|
|
82
|
+
</Network>
|
|
83
|
+
<AudioAdapter controller="HDA" useDefault="true" driver="ALSA" enabled="true" enabledOut="true"/>
|
|
84
|
+
<Clipboard/>
|
|
85
|
+
<StorageControllers>
|
|
86
|
+
<StorageController name="SATA" type="AHCI" PortCount="3" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3">
|
|
87
|
+
<AttachedDevice type="HardDisk" hotpluggable="false" port="0" device="0">
|
|
88
|
+
<Image uuid="{742e6d0f-8896-4aa6-97f4-e05d70e73029}"/>
|
|
89
|
+
</AttachedDevice>
|
|
90
|
+
<AttachedDevice passthrough="false" type="DVD" hotpluggable="false" port="1" device="0"/>
|
|
91
|
+
<AttachedDevice type="HardDisk" hotpluggable="false" port="2" device="0">
|
|
92
|
+
<Image uuid="{1db0b9fe-36c2-44e8-9b7c-61fa5b6d1462}"/>
|
|
93
|
+
</AttachedDevice>
|
|
94
|
+
</StorageController>
|
|
95
|
+
</StorageControllers>
|
|
96
|
+
<CPU count="2">
|
|
97
|
+
<HardwareVirtExLargePages enabled="false"/>
|
|
98
|
+
<PAE enabled="false"/>
|
|
99
|
+
<LongMode enabled="true"/>
|
|
100
|
+
</CPU>
|
|
101
|
+
</Hardware>
|
|
102
|
+
</Machine>
|
|
103
|
+
</VirtualBox>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dissect.hypervisor.descriptor.hyperv import HyperVFile
|
|
4
|
+
from tests._util import absolute_path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_hyperv_vmcx() -> None:
|
|
8
|
+
with absolute_path("_data/descriptor/hyperv/test.vmcx").open("rb") as fh:
|
|
9
|
+
hf = HyperVFile(fh)
|
|
10
|
+
|
|
11
|
+
assert hf.header is hf.headers[0]
|
|
12
|
+
assert hf.version == 0x400
|
|
13
|
+
assert len(hf.replay_logs) == 1
|
|
14
|
+
assert len(hf.object_tables) == 1
|
|
15
|
+
assert len(hf.key_tables) == 8
|
|
16
|
+
|
|
17
|
+
obj = hf.as_dict()
|
|
18
|
+
assert set(obj.keys()) == {"configuration"}
|
|
19
|
+
assert len(obj["configuration"].keys()) == 27
|
|
20
|
+
assert len(obj["configuration"]["manifest"].keys()) == 39
|
|
21
|
+
assert len(obj["configuration"]["properties"].keys()) == 11
|
|
22
|
+
assert len(obj["configuration"]["settings"].keys()) == 6
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_hyperv_vmrs() -> None:
|
|
26
|
+
with absolute_path("_data/descriptor/hyperv/test.VMRS").open("rb") as fh:
|
|
27
|
+
hf = HyperVFile(fh)
|
|
28
|
+
|
|
29
|
+
assert hf.header is hf.headers[0]
|
|
30
|
+
assert hf.version == 0x400
|
|
31
|
+
assert len(hf.replay_logs) == 1
|
|
32
|
+
assert len(hf.object_tables) == 1
|
|
33
|
+
assert len(hf.key_tables) == 2
|
|
34
|
+
|
|
35
|
+
obj = hf.as_dict()
|
|
36
|
+
target = {
|
|
37
|
+
"configuration": {
|
|
38
|
+
"properties": {"version": 2304},
|
|
39
|
+
"global_settings": {
|
|
40
|
+
"metrics": {
|
|
41
|
+
"devicetype": {
|
|
42
|
+
"guid": "83F8638B-8DCA-4152-9EDA-2CA8B33039B4",
|
|
43
|
+
"deviceinstance": {
|
|
44
|
+
"guid": "83F8638B-8DCA-4152-9EDA-2CA8B33039B4",
|
|
45
|
+
"metric": {
|
|
46
|
+
"typecode": "4E1D459F-7861-46A4-887C-B64397C97E1B;0\\0\\L",
|
|
47
|
+
"value": 0,
|
|
48
|
+
"enabled": False,
|
|
49
|
+
"starttime": 0,
|
|
50
|
+
"lastcomputedtime": 0,
|
|
51
|
+
"peaktime": 0,
|
|
52
|
+
"poolid": "",
|
|
53
|
+
"resourcetypeid": "70BB60D2-A9D3-46AA-B654-3DE53004B4F8",
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"_ac6b8dc1-3257-4a70-b1b2-a9c9215659ad_": {"VDEVVersion": 2048},
|
|
60
|
+
"_e51b7ef6-4a7f-4780-aaae-d4b291aacd2e_": {"VDEVVersion": 512},
|
|
61
|
+
"_83f8638b-8dca-4152-9eda-2ca8b33039b4_": {"VDEVVersion": 1792},
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
assert obj == target
|