dissect.hypervisor 3.16.dev3__tar.gz → 3.17.dev1__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.16.dev3/dissect.hypervisor.egg-info → dissect_hypervisor-3.17.dev1}/PKG-INFO +1 -1
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/vmdk.py +90 -33
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1/dissect.hypervisor.egg-info}/PKG-INFO +1 -1
- dissect_hypervisor-3.17.dev1/tests/test_vmdk.py +199 -0
- dissect_hypervisor-3.16.dev3/tests/test_vmdk.py +0 -20
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/COPYRIGHT +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/LICENSE +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/MANIFEST.in +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/README.md +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/__init__.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/descriptor/__init__.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/descriptor/c_hyperv.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/descriptor/hyperv.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/descriptor/ovf.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/descriptor/pvs.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/descriptor/vbox.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/descriptor/vmx.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/__init__.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/c_hdd.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/c_qcow2.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/c_vdi.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/c_vhd.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/c_vhdx.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/c_vmdk.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/hdd.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/qcow2.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/vdi.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/vhd.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/vhdx.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/exceptions.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/tools/__init__.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/tools/envelope.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/util/__init__.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/util/envelope.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/util/vmtar.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect.hypervisor.egg-info/SOURCES.txt +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect.hypervisor.egg-info/dependency_links.txt +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect.hypervisor.egg-info/entry_points.txt +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect.hypervisor.egg-info/requires.txt +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect.hypervisor.egg-info/top_level.txt +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/pyproject.toml +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/setup.cfg +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/__init__.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/conftest.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/differencing.avhdx.gz +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/dynamic.vhd.gz +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/dynamic.vhdx.gz +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/encrypted.vmx +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/encryption.info +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/expanding.hdd/DiskDescriptor.xml +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/expanding.hdd/expanding.hdd +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/expanding.hdd/expanding.hdd.0.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/fixed.vhd.gz +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/fixed.vhdx.gz +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/local.tgz.ve +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/plain.hdd/DiskDescriptor.xml +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/plain.hdd/plain.hdd +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/plain.hdd/plain.hdd.0.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/sesparse.vmdk.gz +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/split.hdd/DiskDescriptor.xml +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/split.hdd/split.hdd +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/split.hdd/split.hdd.0.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/split.hdd/split.hdd.1.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/split.hdd/split.hdd.2.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/split.hdd/split.hdd.3.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/split.hdd/split.hdd.4.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/split.hdd/split.hdd.5.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/test.VMRS +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/test.vgz +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/test.vmcx +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/docs/Makefile +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/docs/conf.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/docs/index.rst +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/test_envelope.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/test_hdd.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/test_hyperv.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/test_ovf.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/test_pvs.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/test_vbox.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/test_vhd.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/test_vhdx.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/test_vmtar.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/test_vmx.py +0 -0
- {dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tox.ini +0 -0
{dissect_hypervisor-3.16.dev3/dissect.hypervisor.egg-info → dissect_hypervisor-3.17.dev1}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dissect.hypervisor
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.17.dev1
|
|
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
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/vmdk.py
RENAMED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import ctypes
|
|
2
4
|
import io
|
|
3
5
|
import logging
|
|
4
6
|
import os
|
|
7
|
+
import re
|
|
5
8
|
import textwrap
|
|
6
9
|
import zlib
|
|
7
10
|
from bisect import bisect_right
|
|
11
|
+
from dataclasses import dataclass
|
|
8
12
|
from functools import lru_cache
|
|
9
13
|
from pathlib import Path
|
|
10
14
|
|
|
@@ -59,13 +63,13 @@ class VMDK(AlignedStream):
|
|
|
59
63
|
if self.descriptor.attr["parentCID"] != "ffffffff":
|
|
60
64
|
self.parent = open_parent(path.parent, self.descriptor.attr["parentFileNameHint"])
|
|
61
65
|
|
|
62
|
-
for
|
|
63
|
-
if
|
|
64
|
-
sdisk_fh = path.with_name(filename).open("rb")
|
|
66
|
+
for extent in self.descriptor.extents:
|
|
67
|
+
if extent.type in ["SPARSE", "VMFSSPARSE", "SESPARSE"]:
|
|
68
|
+
sdisk_fh = path.with_name(extent.filename).open("rb")
|
|
65
69
|
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,
|
|
70
|
+
elif extent.type in ["VMFS", "FLAT"]:
|
|
71
|
+
rdisk_fh = path.with_name(extent.filename).open("rb")
|
|
72
|
+
self.disks.append(RawDisk(rdisk_fh, extent.sectors * SECTOR_SIZE))
|
|
69
73
|
|
|
70
74
|
elif magic in (COWD_MAGIC, VMDK_MAGIC, SESPARSE_MAGIC):
|
|
71
75
|
sparse_disk = SparseDisk(fh)
|
|
@@ -398,8 +402,53 @@ class SparseExtentHeader:
|
|
|
398
402
|
return getattr(self.hdr, attr)
|
|
399
403
|
|
|
400
404
|
|
|
405
|
+
RE_EXTENT_DESCRIPTOR = re.compile(
|
|
406
|
+
r"""
|
|
407
|
+
^
|
|
408
|
+
(?P<access_mode>RW|RDONLY|NOACCESS)\s
|
|
409
|
+
(?P<sectors>\d+)\s
|
|
410
|
+
(?P<type>SPARSE|ZERO|FLAT|VMFS|VMFSSPARSE|VMFSRDM|VMFSRAW)
|
|
411
|
+
(\s(?P<filename>\".+\"))?
|
|
412
|
+
(\s(?P<start_sector>\d+))?
|
|
413
|
+
(\s(?P<partition_uuid>\S+))?
|
|
414
|
+
(\s(?P<device_identifier>\S+))?
|
|
415
|
+
$
|
|
416
|
+
""",
|
|
417
|
+
re.VERBOSE,
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
@dataclass
|
|
422
|
+
class ExtentDescriptor:
|
|
423
|
+
raw: str
|
|
424
|
+
access_mode: str
|
|
425
|
+
sectors: int
|
|
426
|
+
type: str
|
|
427
|
+
filename: str | None = None
|
|
428
|
+
start_sector: int | None = None
|
|
429
|
+
partition_uuid: str | None = None
|
|
430
|
+
device_identifier: str | None = None
|
|
431
|
+
|
|
432
|
+
def __post_init__(self) -> None:
|
|
433
|
+
self.sectors = int(self.sectors)
|
|
434
|
+
|
|
435
|
+
if self.filename:
|
|
436
|
+
self.filename = self.filename.strip('"')
|
|
437
|
+
|
|
438
|
+
if self.start_sector:
|
|
439
|
+
self.start_sector = int(self.start_sector)
|
|
440
|
+
|
|
441
|
+
def __repr__(self) -> str:
|
|
442
|
+
return f"<ExtentDescriptor {self.raw}>"
|
|
443
|
+
|
|
444
|
+
def __str__(self) -> str:
|
|
445
|
+
return self.raw
|
|
446
|
+
|
|
447
|
+
|
|
401
448
|
class DiskDescriptor:
|
|
402
|
-
def __init__(
|
|
449
|
+
def __init__(
|
|
450
|
+
self, attr: dict, extents: list[ExtentDescriptor], disk_db: dict, sectors: int, raw_config: str | None = None
|
|
451
|
+
):
|
|
403
452
|
self.attr = attr
|
|
404
453
|
self.extents = extents
|
|
405
454
|
self.ddb = disk_db
|
|
@@ -407,9 +456,15 @@ class DiskDescriptor:
|
|
|
407
456
|
self.raw = raw_config
|
|
408
457
|
|
|
409
458
|
@classmethod
|
|
410
|
-
def parse(cls, vmdk_config):
|
|
459
|
+
def parse(cls, vmdk_config: str) -> DiskDescriptor:
|
|
460
|
+
"""Return :class:`DiskDescriptor` based on the provided ``vmdk_config``.
|
|
461
|
+
|
|
462
|
+
Resources:
|
|
463
|
+
- https://github.com/libyal/libvmdk/blob/main/documentation/VMWare%20Virtual%20Disk%20Format%20(VMDK).asciidoc
|
|
464
|
+
""" # noqa: E501
|
|
465
|
+
|
|
411
466
|
descriptor_settings = {}
|
|
412
|
-
extents = []
|
|
467
|
+
extents: list[ExtentDescriptor] = []
|
|
413
468
|
disk_db = {}
|
|
414
469
|
sectors = 0
|
|
415
470
|
|
|
@@ -420,11 +475,15 @@ class DiskDescriptor:
|
|
|
420
475
|
continue
|
|
421
476
|
|
|
422
477
|
if line.startswith("RW ") or line.startswith("RDONLY ") or line.startswith("NOACCESS "):
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
478
|
+
match = RE_EXTENT_DESCRIPTOR.search(line)
|
|
479
|
+
|
|
480
|
+
if not match:
|
|
481
|
+
log.warning("Unexpected ExtentDescriptor format in vmdk config: %s, ignoring", line)
|
|
482
|
+
continue
|
|
483
|
+
|
|
484
|
+
extent = ExtentDescriptor(raw=line, **match.groupdict())
|
|
485
|
+
sectors += extent.sectors
|
|
486
|
+
extents.append(extent)
|
|
428
487
|
continue
|
|
429
488
|
|
|
430
489
|
setting, _, value = line.partition("=")
|
|
@@ -438,35 +497,33 @@ class DiskDescriptor:
|
|
|
438
497
|
|
|
439
498
|
return cls(descriptor_settings, extents, disk_db, sectors, vmdk_config)
|
|
440
499
|
|
|
441
|
-
def __str__(self):
|
|
442
|
-
str_template =
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
500
|
+
def __str__(self) -> str:
|
|
501
|
+
str_template = textwrap.dedent(
|
|
502
|
+
"""\
|
|
503
|
+
# Disk DescriptorFile
|
|
504
|
+
version=1
|
|
505
|
+
{}
|
|
446
506
|
|
|
447
|
-
|
|
448
|
-
|
|
507
|
+
# Extent Description
|
|
508
|
+
{}
|
|
449
509
|
|
|
450
|
-
|
|
451
|
-
|
|
510
|
+
# The Disk Data Base
|
|
511
|
+
#DDB
|
|
512
|
+
|
|
513
|
+
{}"""
|
|
514
|
+
)
|
|
452
515
|
|
|
453
|
-
{}"""
|
|
454
|
-
str_template = textwrap.dedent(str_template)
|
|
455
516
|
descriptor_settings = []
|
|
456
517
|
for setting, value in self.attr.items():
|
|
457
|
-
if setting
|
|
458
|
-
|
|
459
|
-
descriptor_settings.append("{}={}".format(setting, value))
|
|
518
|
+
if setting != "version":
|
|
519
|
+
descriptor_settings.append(f"{setting}={value}")
|
|
460
520
|
descriptor_settings = "\n".join(descriptor_settings)
|
|
461
521
|
|
|
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)
|
|
522
|
+
extents = "\n".join(map(str, self.extents))
|
|
466
523
|
|
|
467
524
|
disk_db = []
|
|
468
525
|
for setting, value in self.ddb.items():
|
|
469
|
-
disk_db.append('{} = "{}"'
|
|
526
|
+
disk_db.append(f'{setting} = "{value}"')
|
|
470
527
|
disk_db = "\n".join(disk_db)
|
|
471
528
|
|
|
472
529
|
return str_template.format(descriptor_settings, extents, disk_db)
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1/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.17.dev1
|
|
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
|
|
@@ -0,0 +1,199 @@
|
|
|
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
|
+
raw='RW 123456789 SPARSE "disk.vmdk"',
|
|
33
|
+
access_mode="RW",
|
|
34
|
+
sectors=123456789,
|
|
35
|
+
type="SPARSE",
|
|
36
|
+
filename='"disk.vmdk"',
|
|
37
|
+
start_sector=None,
|
|
38
|
+
partition_uuid=None,
|
|
39
|
+
device_identifier=None,
|
|
40
|
+
),
|
|
41
|
+
],
|
|
42
|
+
),
|
|
43
|
+
(
|
|
44
|
+
'RW 123456789 FLAT "disk-flat.vmdk" 0',
|
|
45
|
+
[
|
|
46
|
+
ExtentDescriptor(
|
|
47
|
+
raw='RW 123456789 FLAT "disk-flat.vmdk" 0',
|
|
48
|
+
access_mode="RW",
|
|
49
|
+
sectors=123456789,
|
|
50
|
+
type="FLAT",
|
|
51
|
+
filename='"disk-flat.vmdk"',
|
|
52
|
+
start_sector=0,
|
|
53
|
+
partition_uuid=None,
|
|
54
|
+
device_identifier=None,
|
|
55
|
+
)
|
|
56
|
+
],
|
|
57
|
+
),
|
|
58
|
+
(
|
|
59
|
+
"RDONLY 0 ZERO",
|
|
60
|
+
[
|
|
61
|
+
ExtentDescriptor(
|
|
62
|
+
raw="RDONLY 0 ZERO",
|
|
63
|
+
access_mode="RDONLY",
|
|
64
|
+
sectors=0,
|
|
65
|
+
type="ZERO",
|
|
66
|
+
),
|
|
67
|
+
],
|
|
68
|
+
),
|
|
69
|
+
(
|
|
70
|
+
'NOACCESS 123456789 SPARSE "disk-sparse.vmdk" 123 partition-uuid device-id',
|
|
71
|
+
[
|
|
72
|
+
ExtentDescriptor(
|
|
73
|
+
raw='NOACCESS 123456789 SPARSE "disk-sparse.vmdk" 123 partition-uuid device-id',
|
|
74
|
+
access_mode="NOACCESS",
|
|
75
|
+
sectors=123456789,
|
|
76
|
+
type="SPARSE",
|
|
77
|
+
filename='"disk-sparse.vmdk"',
|
|
78
|
+
start_sector=123,
|
|
79
|
+
partition_uuid="partition-uuid",
|
|
80
|
+
device_identifier="device-id",
|
|
81
|
+
),
|
|
82
|
+
],
|
|
83
|
+
),
|
|
84
|
+
("RW 1234567890", []),
|
|
85
|
+
('RDONLY "file.vmdk"', []),
|
|
86
|
+
("NOACCESS", []),
|
|
87
|
+
(
|
|
88
|
+
'RW 1234567890 SPARSE "disk with spaces.vmdk"',
|
|
89
|
+
[
|
|
90
|
+
ExtentDescriptor(
|
|
91
|
+
raw='RW 1234567890 SPARSE "disk with spaces.vmdk"',
|
|
92
|
+
access_mode="RW",
|
|
93
|
+
sectors=1234567890,
|
|
94
|
+
type="SPARSE",
|
|
95
|
+
filename='"disk with spaces.vmdk"',
|
|
96
|
+
start_sector=None,
|
|
97
|
+
partition_uuid=None,
|
|
98
|
+
device_identifier=None,
|
|
99
|
+
)
|
|
100
|
+
],
|
|
101
|
+
),
|
|
102
|
+
(
|
|
103
|
+
'RW 1234567890 SPARSE "disk with spaces.vmdk" 123',
|
|
104
|
+
[
|
|
105
|
+
ExtentDescriptor(
|
|
106
|
+
raw='RW 1234567890 SPARSE "disk with spaces.vmdk" 123',
|
|
107
|
+
access_mode="RW",
|
|
108
|
+
sectors=1234567890,
|
|
109
|
+
type="SPARSE",
|
|
110
|
+
filename='"disk with spaces.vmdk"',
|
|
111
|
+
start_sector=123,
|
|
112
|
+
partition_uuid=None,
|
|
113
|
+
device_identifier=None,
|
|
114
|
+
)
|
|
115
|
+
],
|
|
116
|
+
),
|
|
117
|
+
(
|
|
118
|
+
'RW 1234567890 SPARSE "disk with spaces.vmdk" 123 part-uuid',
|
|
119
|
+
[
|
|
120
|
+
ExtentDescriptor(
|
|
121
|
+
raw='RW 1234567890 SPARSE "disk with spaces.vmdk" 123 part-uuid',
|
|
122
|
+
access_mode="RW",
|
|
123
|
+
sectors=1234567890,
|
|
124
|
+
type="SPARSE",
|
|
125
|
+
filename='"disk with spaces.vmdk"',
|
|
126
|
+
start_sector=123,
|
|
127
|
+
partition_uuid="part-uuid",
|
|
128
|
+
device_identifier=None,
|
|
129
|
+
)
|
|
130
|
+
],
|
|
131
|
+
),
|
|
132
|
+
(
|
|
133
|
+
'RW 1234567890 SPARSE "disk with spaces.vmdk" 123 part-uuid device-id',
|
|
134
|
+
[
|
|
135
|
+
ExtentDescriptor(
|
|
136
|
+
raw='RW 1234567890 SPARSE "disk with spaces.vmdk" 123 part-uuid device-id',
|
|
137
|
+
access_mode="RW",
|
|
138
|
+
sectors=1234567890,
|
|
139
|
+
type="SPARSE",
|
|
140
|
+
filename='"disk with spaces.vmdk"',
|
|
141
|
+
start_sector=123,
|
|
142
|
+
partition_uuid="part-uuid",
|
|
143
|
+
device_identifier="device-id",
|
|
144
|
+
)
|
|
145
|
+
],
|
|
146
|
+
),
|
|
147
|
+
(
|
|
148
|
+
r'RW 16777216 SPARSE "this is an example "\' diskëäô:)\\\'`\foo.vmdk" 123',
|
|
149
|
+
[
|
|
150
|
+
ExtentDescriptor(
|
|
151
|
+
raw=r'RW 16777216 SPARSE "this is an example "\' diskëäô:)\\\'`\foo.vmdk" 123',
|
|
152
|
+
access_mode="RW",
|
|
153
|
+
sectors=16777216,
|
|
154
|
+
type="SPARSE",
|
|
155
|
+
filename=r'"this is an example "\' diskëäô:)\\\'`\foo.vmdk"',
|
|
156
|
+
start_sector=123,
|
|
157
|
+
partition_uuid=None,
|
|
158
|
+
device_identifier=None,
|
|
159
|
+
)
|
|
160
|
+
],
|
|
161
|
+
),
|
|
162
|
+
(
|
|
163
|
+
r'RW 13371337 SPARSE "🦊 🦊 🦊.vmdk"',
|
|
164
|
+
[
|
|
165
|
+
ExtentDescriptor(
|
|
166
|
+
raw=r'RW 13371337 SPARSE "🦊 🦊 🦊.vmdk"',
|
|
167
|
+
access_mode="RW",
|
|
168
|
+
sectors=13371337,
|
|
169
|
+
type="SPARSE",
|
|
170
|
+
filename='"🦊 🦊 🦊.vmdk"',
|
|
171
|
+
)
|
|
172
|
+
],
|
|
173
|
+
),
|
|
174
|
+
],
|
|
175
|
+
ids=(
|
|
176
|
+
"sparse",
|
|
177
|
+
"flat",
|
|
178
|
+
"zero",
|
|
179
|
+
"sparse-ids",
|
|
180
|
+
"bad-1",
|
|
181
|
+
"bad-2",
|
|
182
|
+
"bad-3",
|
|
183
|
+
"spaces-four-parts",
|
|
184
|
+
"spaces-five-parts",
|
|
185
|
+
"spaces-six-parts",
|
|
186
|
+
"spaces-seven-parts",
|
|
187
|
+
"specials-five-parts",
|
|
188
|
+
"emoji-four-parts",
|
|
189
|
+
),
|
|
190
|
+
)
|
|
191
|
+
def test_vmdk_extent_description(extent_description: str, expected_extents: list) -> None:
|
|
192
|
+
"""test if we correctly parse VMDK sparse and flat extent descriptions.
|
|
193
|
+
|
|
194
|
+
Resources:
|
|
195
|
+
- https://github.com/libyal/libvmdk/blob/main/documentation/VMWare%20Virtual%20Disk%20Format%20(VMDK).asciidoc#22-extent-descriptions
|
|
196
|
+
""" # noqa: E501
|
|
197
|
+
|
|
198
|
+
descriptor = DiskDescriptor.parse(extent_description)
|
|
199
|
+
assert descriptor.extents == expected_extents
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
from dissect.hypervisor.disk.c_vmdk import c_vmdk
|
|
2
|
-
from dissect.hypervisor.disk.vmdk import VMDK
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def test_vmdk_sesparse(sesparse_vmdk):
|
|
6
|
-
vmdk = VMDK(sesparse_vmdk)
|
|
7
|
-
|
|
8
|
-
disk = vmdk.disks[0]
|
|
9
|
-
|
|
10
|
-
assert disk.is_sesparse
|
|
11
|
-
assert disk._grain_directory_size == 0x20000
|
|
12
|
-
assert disk._grain_table_size == 0x1000
|
|
13
|
-
assert disk._grain_entry_type == c_vmdk.uint64
|
|
14
|
-
assert disk._grain_directory[0] == 0x1000000000000000
|
|
15
|
-
|
|
16
|
-
header = disk.header
|
|
17
|
-
assert header.magic == c_vmdk.SESPARSE_CONST_HEADER_MAGIC
|
|
18
|
-
assert header.version == 0x200000001
|
|
19
|
-
|
|
20
|
-
assert vmdk.read(0x1000000) == b"a" * 0x1000000
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/descriptor/ovf.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/descriptor/pvs.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/descriptor/vbox.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/descriptor/vmx.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/__init__.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/c_hdd.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/c_qcow2.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/c_vdi.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/c_vhd.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/c_vhdx.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/c_vmdk.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/hdd.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/qcow2.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/vdi.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/vhd.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/disk/vhdx.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/exceptions.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/tools/__init__.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/tools/envelope.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/util/__init__.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/util/envelope.py
RENAMED
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/dissect/hypervisor/util/vmtar.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/differencing.avhdx.gz
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/expanding.hdd/expanding.hdd
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/plain.hdd/plain.hdd
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_hypervisor-3.16.dev3 → dissect_hypervisor-3.17.dev1}/tests/data/split.hdd/split.hdd
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|