dissect.hypervisor 3.15.dev2__tar.gz → 3.16.dev2__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.15.dev2/dissect.hypervisor.egg-info → dissect_hypervisor-3.16.dev2}/PKG-INFO +1 -2
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/__init__.py +0 -3
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/disk/vmdk.py +74 -33
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2/dissect.hypervisor.egg-info}/PKG-INFO +1 -2
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect.hypervisor.egg-info/SOURCES.txt +0 -7
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect.hypervisor.egg-info/entry_points.txt +0 -1
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect.hypervisor.egg-info/requires.txt +0 -1
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/pyproject.toml +0 -2
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/conftest.py +0 -5
- dissect_hypervisor-3.16.dev2/tests/test_vmdk.py +93 -0
- dissect_hypervisor-3.15.dev2/dissect/hypervisor/backup/c_vma.py +0 -60
- dissect_hypervisor-3.15.dev2/dissect/hypervisor/backup/vma.py +0 -269
- dissect_hypervisor-3.15.dev2/dissect/hypervisor/backup/xva.py +0 -136
- dissect_hypervisor-3.15.dev2/dissect/hypervisor/tools/vma.py +0 -173
- dissect_hypervisor-3.15.dev2/tests/__init__.py +0 -0
- dissect_hypervisor-3.15.dev2/tests/data/test.vma.gz +0 -0
- dissect_hypervisor-3.15.dev2/tests/test_vma.py +0 -64
- dissect_hypervisor-3.15.dev2/tests/test_vmdk.py +0 -20
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/COPYRIGHT +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/LICENSE +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/MANIFEST.in +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/README.md +0 -0
- {dissect_hypervisor-3.15.dev2/dissect/hypervisor/backup → dissect_hypervisor-3.16.dev2/dissect/hypervisor/descriptor}/__init__.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/descriptor/c_hyperv.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/descriptor/hyperv.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/descriptor/ovf.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/descriptor/pvs.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/descriptor/vbox.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/descriptor/vmx.py +0 -0
- {dissect_hypervisor-3.15.dev2/dissect/hypervisor/descriptor → dissect_hypervisor-3.16.dev2/dissect/hypervisor/disk}/__init__.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/disk/c_hdd.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/disk/c_qcow2.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/disk/c_vdi.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/disk/c_vhd.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/disk/c_vhdx.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/disk/c_vmdk.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/disk/hdd.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/disk/qcow2.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/disk/vdi.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/disk/vhd.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/disk/vhdx.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/exceptions.py +0 -0
- {dissect_hypervisor-3.15.dev2/dissect/hypervisor/disk → dissect_hypervisor-3.16.dev2/dissect/hypervisor/tools}/__init__.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/tools/envelope.py +0 -0
- {dissect_hypervisor-3.15.dev2/dissect/hypervisor/tools → dissect_hypervisor-3.16.dev2/dissect/hypervisor/util}/__init__.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/util/envelope.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/util/vmtar.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect.hypervisor.egg-info/dependency_links.txt +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect.hypervisor.egg-info/top_level.txt +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/setup.cfg +0 -0
- {dissect_hypervisor-3.15.dev2/dissect/hypervisor/util → dissect_hypervisor-3.16.dev2/tests}/__init__.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/differencing.avhdx.gz +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/dynamic.vhd.gz +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/dynamic.vhdx.gz +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/encrypted.vmx +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/encryption.info +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/expanding.hdd/DiskDescriptor.xml +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/expanding.hdd/expanding.hdd +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/expanding.hdd/expanding.hdd.0.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/fixed.vhd.gz +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/fixed.vhdx.gz +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/local.tgz.ve +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/plain.hdd/DiskDescriptor.xml +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/plain.hdd/plain.hdd +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/plain.hdd/plain.hdd.0.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/sesparse.vmdk.gz +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/split.hdd/DiskDescriptor.xml +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/split.hdd/split.hdd +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/split.hdd/split.hdd.0.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/split.hdd/split.hdd.1.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/split.hdd/split.hdd.2.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/split.hdd/split.hdd.3.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/split.hdd/split.hdd.4.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/split.hdd/split.hdd.5.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/test.VMRS +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/test.vgz +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/data/test.vmcx +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/docs/Makefile +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/docs/conf.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/docs/index.rst +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/test_envelope.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/test_hdd.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/test_hyperv.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/test_ovf.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/test_pvs.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/test_vbox.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/test_vhd.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/test_vhdx.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/test_vmtar.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tests/test_vmx.py +0 -0
- {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/tox.ini +0 -0
{dissect_hypervisor-3.15.dev2/dissect.hypervisor.egg-info → dissect_hypervisor-3.16.dev2}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dissect.hypervisor
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.16.dev2
|
|
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: Affero General Public License v3
|
|
@@ -27,7 +27,6 @@ Requires-Dist: dissect.cstruct<5,>=4
|
|
|
27
27
|
Requires-Dist: dissect.util<4,>=3
|
|
28
28
|
Provides-Extra: full
|
|
29
29
|
Requires-Dist: pycryptodome; extra == "full"
|
|
30
|
-
Requires-Dist: rich; extra == "full"
|
|
31
30
|
Provides-Extra: dev
|
|
32
31
|
Requires-Dist: dissect.hypervisor[full]; extra == "dev"
|
|
33
32
|
Requires-Dist: dissect.cstruct<5.0.dev,>=4.0.dev; extra == "dev"
|
{dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/__init__.py
RENAMED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from dissect.hypervisor.backup import vma, xva
|
|
2
1
|
from dissect.hypervisor.descriptor import hyperv, ovf, pvs, vbox, vmx
|
|
3
2
|
from dissect.hypervisor.disk import hdd, qcow2, vdi, vhd, vhdx, vmdk
|
|
4
3
|
from dissect.hypervisor.util import envelope, vmtar
|
|
@@ -14,9 +13,7 @@ __all__ = [
|
|
|
14
13
|
"vdi",
|
|
15
14
|
"vhd",
|
|
16
15
|
"vhdx",
|
|
17
|
-
"vma",
|
|
18
16
|
"vmdk",
|
|
19
17
|
"vmtar",
|
|
20
18
|
"vmx",
|
|
21
|
-
"xva",
|
|
22
19
|
]
|
{dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2}/dissect/hypervisor/disk/vmdk.py
RENAMED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import ctypes
|
|
2
4
|
import io
|
|
3
5
|
import logging
|
|
@@ -5,6 +7,7 @@ import os
|
|
|
5
7
|
import textwrap
|
|
6
8
|
import zlib
|
|
7
9
|
from bisect import bisect_right
|
|
10
|
+
from dataclasses import dataclass
|
|
8
11
|
from functools import lru_cache
|
|
9
12
|
from pathlib import Path
|
|
10
13
|
|
|
@@ -59,13 +62,13 @@ class VMDK(AlignedStream):
|
|
|
59
62
|
if self.descriptor.attr["parentCID"] != "ffffffff":
|
|
60
63
|
self.parent = open_parent(path.parent, self.descriptor.attr["parentFileNameHint"])
|
|
61
64
|
|
|
62
|
-
for
|
|
63
|
-
if
|
|
64
|
-
sdisk_fh = path.with_name(filename).open("rb")
|
|
65
|
+
for extent in self.descriptor.extents:
|
|
66
|
+
if extent.type in ["SPARSE", "VMFSSPARSE", "SESPARSE"]:
|
|
67
|
+
sdisk_fh = path.with_name(extent.filename).open("rb")
|
|
65
68
|
self.disks.append(SparseDisk(sdisk_fh, parent=self.parent))
|
|
66
|
-
elif
|
|
67
|
-
rdisk_fh = path.with_name(filename).open("rb")
|
|
68
|
-
self.disks.append(RawDisk(rdisk_fh,
|
|
69
|
+
elif extent.type in ["VMFS", "FLAT"]:
|
|
70
|
+
rdisk_fh = path.with_name(extent.filename).open("rb")
|
|
71
|
+
self.disks.append(RawDisk(rdisk_fh, extent.sectors * SECTOR_SIZE))
|
|
69
72
|
|
|
70
73
|
elif magic in (COWD_MAGIC, VMDK_MAGIC, SESPARSE_MAGIC):
|
|
71
74
|
sparse_disk = SparseDisk(fh)
|
|
@@ -398,8 +401,37 @@ class SparseExtentHeader:
|
|
|
398
401
|
return getattr(self.hdr, attr)
|
|
399
402
|
|
|
400
403
|
|
|
404
|
+
@dataclass
|
|
405
|
+
class ExtentDescriptor:
|
|
406
|
+
access_mode: str
|
|
407
|
+
sectors: int
|
|
408
|
+
type: str
|
|
409
|
+
filename: str | None = None
|
|
410
|
+
start_sector: int | None = None
|
|
411
|
+
partition_uuid: str | None = None
|
|
412
|
+
device_identifier: str | None = None
|
|
413
|
+
|
|
414
|
+
def __post_init__(self) -> None:
|
|
415
|
+
self._raw = " ".join(map(str, [v for v in self.__dict__.values() if v is not None]))
|
|
416
|
+
self.sectors = int(self.sectors)
|
|
417
|
+
|
|
418
|
+
if self.filename:
|
|
419
|
+
self.filename = self.filename.strip('"')
|
|
420
|
+
|
|
421
|
+
if self.start_sector:
|
|
422
|
+
self.start_sector = int(self.start_sector)
|
|
423
|
+
|
|
424
|
+
def __repr__(self) -> str:
|
|
425
|
+
return f"<ExtentDescriptor {self._raw}>"
|
|
426
|
+
|
|
427
|
+
def __str__(self) -> str:
|
|
428
|
+
return self._raw
|
|
429
|
+
|
|
430
|
+
|
|
401
431
|
class DiskDescriptor:
|
|
402
|
-
def __init__(
|
|
432
|
+
def __init__(
|
|
433
|
+
self, attr: dict, extents: list[ExtentDescriptor], disk_db: dict, sectors: int, raw_config: str | None = None
|
|
434
|
+
):
|
|
403
435
|
self.attr = attr
|
|
404
436
|
self.extents = extents
|
|
405
437
|
self.ddb = disk_db
|
|
@@ -407,9 +439,15 @@ class DiskDescriptor:
|
|
|
407
439
|
self.raw = raw_config
|
|
408
440
|
|
|
409
441
|
@classmethod
|
|
410
|
-
def parse(cls, vmdk_config):
|
|
442
|
+
def parse(cls, vmdk_config: str) -> DiskDescriptor:
|
|
443
|
+
"""Return :class:`DiskDescriptor` based on the provided ``vmdk_config``.
|
|
444
|
+
|
|
445
|
+
Resources:
|
|
446
|
+
- https://github.com/libyal/libvmdk/blob/main/documentation/VMWare%20Virtual%20Disk%20Format%20(VMDK).asciidoc
|
|
447
|
+
""" # noqa: E501
|
|
448
|
+
|
|
411
449
|
descriptor_settings = {}
|
|
412
|
-
extents = []
|
|
450
|
+
extents: list[ExtentDescriptor] = []
|
|
413
451
|
disk_db = {}
|
|
414
452
|
sectors = 0
|
|
415
453
|
|
|
@@ -420,11 +458,16 @@ class DiskDescriptor:
|
|
|
420
458
|
continue
|
|
421
459
|
|
|
422
460
|
if line.startswith("RW ") or line.startswith("RDONLY ") or line.startswith("NOACCESS "):
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
461
|
+
# Extent descriptors can have up to seven values according to libvmdk documentation.
|
|
462
|
+
parts = line.split(" ", maxsplit=6)
|
|
463
|
+
|
|
464
|
+
if len(parts) < 3:
|
|
465
|
+
log.warning("Unexpected ExtentDescriptor format in vmdk config: %s, ignoring", line)
|
|
466
|
+
continue
|
|
467
|
+
|
|
468
|
+
extent = ExtentDescriptor(*parts)
|
|
469
|
+
sectors += extent.sectors
|
|
470
|
+
extents.append(extent)
|
|
428
471
|
continue
|
|
429
472
|
|
|
430
473
|
setting, _, value = line.partition("=")
|
|
@@ -438,35 +481,33 @@ class DiskDescriptor:
|
|
|
438
481
|
|
|
439
482
|
return cls(descriptor_settings, extents, disk_db, sectors, vmdk_config)
|
|
440
483
|
|
|
441
|
-
def __str__(self):
|
|
442
|
-
str_template =
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
484
|
+
def __str__(self) -> str:
|
|
485
|
+
str_template = textwrap.dedent(
|
|
486
|
+
"""\
|
|
487
|
+
# Disk DescriptorFile
|
|
488
|
+
version=1
|
|
489
|
+
{}
|
|
490
|
+
|
|
491
|
+
# Extent Description
|
|
492
|
+
{}
|
|
446
493
|
|
|
447
|
-
|
|
448
|
-
|
|
494
|
+
# The Disk Data Base
|
|
495
|
+
#DDB
|
|
449
496
|
|
|
450
|
-
|
|
451
|
-
|
|
497
|
+
{}"""
|
|
498
|
+
)
|
|
452
499
|
|
|
453
|
-
{}"""
|
|
454
|
-
str_template = textwrap.dedent(str_template)
|
|
455
500
|
descriptor_settings = []
|
|
456
501
|
for setting, value in self.attr.items():
|
|
457
|
-
if setting
|
|
458
|
-
|
|
459
|
-
descriptor_settings.append("{}={}".format(setting, value))
|
|
502
|
+
if setting != "version":
|
|
503
|
+
descriptor_settings.append(f"{setting}={value}")
|
|
460
504
|
descriptor_settings = "\n".join(descriptor_settings)
|
|
461
505
|
|
|
462
|
-
extents =
|
|
463
|
-
for access_type, size, extent_type, filename in self.extents:
|
|
464
|
-
extents.append('{} {} {} "{}"'.format(access_type, size, extent_type, filename))
|
|
465
|
-
extents = "\n".join(extents)
|
|
506
|
+
extents = "\n".join(map(str, self.extents))
|
|
466
507
|
|
|
467
508
|
disk_db = []
|
|
468
509
|
for setting, value in self.ddb.items():
|
|
469
|
-
disk_db.append('{} = "{}"'
|
|
510
|
+
disk_db.append(f'{setting} = "{value}"')
|
|
470
511
|
disk_db = "\n".join(disk_db)
|
|
471
512
|
|
|
472
513
|
return str_template.format(descriptor_settings, extents, disk_db)
|
{dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev2/dissect.hypervisor.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dissect.hypervisor
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.16.dev2
|
|
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: Affero General Public License v3
|
|
@@ -27,7 +27,6 @@ Requires-Dist: dissect.cstruct<5,>=4
|
|
|
27
27
|
Requires-Dist: dissect.util<4,>=3
|
|
28
28
|
Provides-Extra: full
|
|
29
29
|
Requires-Dist: pycryptodome; extra == "full"
|
|
30
|
-
Requires-Dist: rich; extra == "full"
|
|
31
30
|
Provides-Extra: dev
|
|
32
31
|
Requires-Dist: dissect.hypervisor[full]; extra == "dev"
|
|
33
32
|
Requires-Dist: dissect.cstruct<5.0.dev,>=4.0.dev; extra == "dev"
|
|
@@ -12,10 +12,6 @@ dissect.hypervisor.egg-info/requires.txt
|
|
|
12
12
|
dissect.hypervisor.egg-info/top_level.txt
|
|
13
13
|
dissect/hypervisor/__init__.py
|
|
14
14
|
dissect/hypervisor/exceptions.py
|
|
15
|
-
dissect/hypervisor/backup/__init__.py
|
|
16
|
-
dissect/hypervisor/backup/c_vma.py
|
|
17
|
-
dissect/hypervisor/backup/vma.py
|
|
18
|
-
dissect/hypervisor/backup/xva.py
|
|
19
15
|
dissect/hypervisor/descriptor/__init__.py
|
|
20
16
|
dissect/hypervisor/descriptor/c_hyperv.py
|
|
21
17
|
dissect/hypervisor/descriptor/hyperv.py
|
|
@@ -38,7 +34,6 @@ dissect/hypervisor/disk/vhdx.py
|
|
|
38
34
|
dissect/hypervisor/disk/vmdk.py
|
|
39
35
|
dissect/hypervisor/tools/__init__.py
|
|
40
36
|
dissect/hypervisor/tools/envelope.py
|
|
41
|
-
dissect/hypervisor/tools/vma.py
|
|
42
37
|
dissect/hypervisor/util/__init__.py
|
|
43
38
|
dissect/hypervisor/util/envelope.py
|
|
44
39
|
dissect/hypervisor/util/vmtar.py
|
|
@@ -52,7 +47,6 @@ tests/test_pvs.py
|
|
|
52
47
|
tests/test_vbox.py
|
|
53
48
|
tests/test_vhd.py
|
|
54
49
|
tests/test_vhdx.py
|
|
55
|
-
tests/test_vma.py
|
|
56
50
|
tests/test_vmdk.py
|
|
57
51
|
tests/test_vmtar.py
|
|
58
52
|
tests/test_vmx.py
|
|
@@ -67,7 +61,6 @@ tests/data/local.tgz.ve
|
|
|
67
61
|
tests/data/sesparse.vmdk.gz
|
|
68
62
|
tests/data/test.VMRS
|
|
69
63
|
tests/data/test.vgz
|
|
70
|
-
tests/data/test.vma.gz
|
|
71
64
|
tests/data/test.vmcx
|
|
72
65
|
tests/data/expanding.hdd/DiskDescriptor.xml
|
|
73
66
|
tests/data/expanding.hdd/expanding.hdd
|
|
@@ -39,7 +39,6 @@ repository = "https://github.com/fox-it/dissect.hypervisor"
|
|
|
39
39
|
[project.optional-dependencies]
|
|
40
40
|
full = [
|
|
41
41
|
"pycryptodome",
|
|
42
|
-
"rich",
|
|
43
42
|
]
|
|
44
43
|
dev = [
|
|
45
44
|
"dissect.hypervisor[full]",
|
|
@@ -48,7 +47,6 @@ dev = [
|
|
|
48
47
|
]
|
|
49
48
|
|
|
50
49
|
[project.scripts]
|
|
51
|
-
vma-extract = "dissect.hypervisor.tools.vma:main"
|
|
52
50
|
envelope-decrypt = "dissect.hypervisor.tools.envelope:main"
|
|
53
51
|
|
|
54
52
|
[tool.black]
|
|
@@ -79,11 +79,6 @@ def split_hdd() -> Iterator[str]:
|
|
|
79
79
|
yield absolute_path("data/split.hdd")
|
|
80
80
|
|
|
81
81
|
|
|
82
|
-
@pytest.fixture
|
|
83
|
-
def simple_vma() -> Iterator[BinaryIO]:
|
|
84
|
-
yield from open_file_gz("data/test.vma.gz")
|
|
85
|
-
|
|
86
|
-
|
|
87
82
|
@pytest.fixture
|
|
88
83
|
def envelope() -> Iterator[BinaryIO]:
|
|
89
84
|
yield from open_file("data/local.tgz.ve")
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from dissect.hypervisor.disk.c_vmdk import c_vmdk
|
|
4
|
+
from dissect.hypervisor.disk.vmdk import VMDK, DiskDescriptor, ExtentDescriptor
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_vmdk_sesparse(sesparse_vmdk):
|
|
8
|
+
vmdk = VMDK(sesparse_vmdk)
|
|
9
|
+
|
|
10
|
+
disk = vmdk.disks[0]
|
|
11
|
+
|
|
12
|
+
assert disk.is_sesparse
|
|
13
|
+
assert disk._grain_directory_size == 0x20000
|
|
14
|
+
assert disk._grain_table_size == 0x1000
|
|
15
|
+
assert disk._grain_entry_type == c_vmdk.uint64
|
|
16
|
+
assert disk._grain_directory[0] == 0x1000000000000000
|
|
17
|
+
|
|
18
|
+
header = disk.header
|
|
19
|
+
assert header.magic == c_vmdk.SESPARSE_CONST_HEADER_MAGIC
|
|
20
|
+
assert header.version == 0x200000001
|
|
21
|
+
|
|
22
|
+
assert vmdk.read(0x1000000) == b"a" * 0x1000000
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@pytest.mark.parametrize(
|
|
26
|
+
"extent_description, expected_extents",
|
|
27
|
+
[
|
|
28
|
+
(
|
|
29
|
+
'RW 123456789 SPARSE "disk.vmdk"',
|
|
30
|
+
[
|
|
31
|
+
ExtentDescriptor(
|
|
32
|
+
access_mode="RW",
|
|
33
|
+
sectors=123456789,
|
|
34
|
+
type="SPARSE",
|
|
35
|
+
filename="disk.vmdk",
|
|
36
|
+
partition_uuid=None,
|
|
37
|
+
device_identifier=None,
|
|
38
|
+
),
|
|
39
|
+
],
|
|
40
|
+
),
|
|
41
|
+
(
|
|
42
|
+
'RW 123456789 FLAT "disk-flat.vmdk" 0',
|
|
43
|
+
[
|
|
44
|
+
ExtentDescriptor(
|
|
45
|
+
access_mode="RW",
|
|
46
|
+
sectors=123456789,
|
|
47
|
+
type="FLAT",
|
|
48
|
+
filename="disk-flat.vmdk",
|
|
49
|
+
start_sector=0,
|
|
50
|
+
partition_uuid=None,
|
|
51
|
+
device_identifier=None,
|
|
52
|
+
)
|
|
53
|
+
],
|
|
54
|
+
),
|
|
55
|
+
(
|
|
56
|
+
"RDONLY 0 ZERO",
|
|
57
|
+
[
|
|
58
|
+
ExtentDescriptor(
|
|
59
|
+
access_mode="RDONLY",
|
|
60
|
+
sectors=0,
|
|
61
|
+
type="ZERO",
|
|
62
|
+
),
|
|
63
|
+
],
|
|
64
|
+
),
|
|
65
|
+
(
|
|
66
|
+
'NOACCESS 123456789 SPARSE "disk-sparse.vmdk" 123 partition-uuid device-id',
|
|
67
|
+
[
|
|
68
|
+
ExtentDescriptor(
|
|
69
|
+
access_mode="NOACCESS",
|
|
70
|
+
sectors=123456789,
|
|
71
|
+
type="SPARSE",
|
|
72
|
+
filename="disk-sparse.vmdk",
|
|
73
|
+
start_sector=123,
|
|
74
|
+
partition_uuid="partition-uuid",
|
|
75
|
+
device_identifier="device-id",
|
|
76
|
+
),
|
|
77
|
+
],
|
|
78
|
+
),
|
|
79
|
+
("RW 1234567890", []),
|
|
80
|
+
('RDONLY "file.vmdk"', []),
|
|
81
|
+
("NOACCESS", []),
|
|
82
|
+
],
|
|
83
|
+
ids=("sparse", "flat", "zero", "sparse-ids", "bad-1", "bad-2", "bad-3"),
|
|
84
|
+
)
|
|
85
|
+
def test_vmdk_extent_description(extent_description: str, expected_extents: list) -> None:
|
|
86
|
+
"""test if we correctly parse VMDK sparse and flat extent descriptions.
|
|
87
|
+
|
|
88
|
+
Resources:
|
|
89
|
+
- https://github.com/libyal/libvmdk/blob/main/documentation/VMWare%20Virtual%20Disk%20Format%20(VMDK).asciidoc#22-extent-descriptions
|
|
90
|
+
""" # noqa: E501
|
|
91
|
+
|
|
92
|
+
descriptor = DiskDescriptor.parse(extent_description)
|
|
93
|
+
assert descriptor.extents == expected_extents
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
from dissect.cstruct import cstruct
|
|
2
|
-
|
|
3
|
-
vma_def = """
|
|
4
|
-
#define VMA_BLOCK_BITS 12
|
|
5
|
-
#define VMA_BLOCK_SIZE (1 << VMA_BLOCK_BITS)
|
|
6
|
-
#define VMA_CLUSTER_BITS (VMA_BLOCK_BITS + 4)
|
|
7
|
-
#define VMA_CLUSTER_SIZE (1 << VMA_CLUSTER_BITS)
|
|
8
|
-
|
|
9
|
-
#define VMA_EXTENT_HEADER_SIZE 512
|
|
10
|
-
#define VMA_BLOCKS_PER_EXTENT 59
|
|
11
|
-
#define VMA_MAX_CONFIGS 256
|
|
12
|
-
|
|
13
|
-
#define VMA_MAX_EXTENT_SIZE (VMA_EXTENT_HEADER_SIZE + VMA_CLUSTER_SIZE * VMA_BLOCKS_PER_EXTENT)
|
|
14
|
-
|
|
15
|
-
/* File Format Definitions */
|
|
16
|
-
|
|
17
|
-
struct VmaDeviceInfoHeader {
|
|
18
|
-
uint32 devname_ptr; /* offset into blob_buffer table */
|
|
19
|
-
uint32 reserved0;
|
|
20
|
-
uint64 size; /* device size in bytes */
|
|
21
|
-
uint64 reserved1;
|
|
22
|
-
uint64 reserved2;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
struct VmaHeader {
|
|
26
|
-
char magic[4];
|
|
27
|
-
uint32 version;
|
|
28
|
-
char uuid[16];
|
|
29
|
-
int64 ctime;
|
|
30
|
-
char md5sum[16];
|
|
31
|
-
|
|
32
|
-
uint32 blob_buffer_offset;
|
|
33
|
-
uint32 blob_buffer_size;
|
|
34
|
-
uint32 header_size;
|
|
35
|
-
|
|
36
|
-
char _reserved1[1984];
|
|
37
|
-
|
|
38
|
-
uint32 config_names[VMA_MAX_CONFIGS]; /* offset into blob_buffer table */
|
|
39
|
-
uint32 config_data[VMA_MAX_CONFIGS]; /* offset into blob_buffer table */
|
|
40
|
-
|
|
41
|
-
char _reserved2[4];
|
|
42
|
-
|
|
43
|
-
VmaDeviceInfoHeader dev_info[256];
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
struct VmaExtentHeader {
|
|
47
|
-
char magic[4];
|
|
48
|
-
uint16 reserved1;
|
|
49
|
-
uint16 block_count;
|
|
50
|
-
char uuid[16];
|
|
51
|
-
char md5sum[16];
|
|
52
|
-
uint64 blockinfo[VMA_BLOCKS_PER_EXTENT];
|
|
53
|
-
};
|
|
54
|
-
"""
|
|
55
|
-
|
|
56
|
-
c_vma = cstruct(endian=">").load(vma_def)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
VMA_MAGIC = b"VMA\x00"
|
|
60
|
-
VMA_EXTENT_MAGIC = b"VMAE"
|