dissect.target 3.9.dev24__py3-none-any.whl → 3.9.dev26__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- dissect/target/container.py +3 -1
- dissect/target/containers/hdd.py +37 -0
- dissect/target/containers/hds.py +41 -0
- dissect/target/loader.py +2 -0
- dissect/target/loaders/pvm.py +14 -0
- dissect/target/loaders/pvs.py +35 -0
- dissect/target/plugins/os/unix/_os.py +5 -3
- dissect/target/volumes/lvm.py +3 -1
- {dissect.target-3.9.dev24.dist-info → dissect.target-3.9.dev26.dist-info}/METADATA +1 -1
- {dissect.target-3.9.dev24.dist-info → dissect.target-3.9.dev26.dist-info}/RECORD +15 -11
- {dissect.target-3.9.dev24.dist-info → dissect.target-3.9.dev26.dist-info}/COPYRIGHT +0 -0
- {dissect.target-3.9.dev24.dist-info → dissect.target-3.9.dev26.dist-info}/LICENSE +0 -0
- {dissect.target-3.9.dev24.dist-info → dissect.target-3.9.dev26.dist-info}/WHEEL +0 -0
- {dissect.target-3.9.dev24.dist-info → dissect.target-3.9.dev26.dist-info}/entry_points.txt +0 -0
- {dissect.target-3.9.dev24.dist-info → dissect.target-3.9.dev26.dist-info}/top_level.txt +0 -0
dissect/target/container.py
CHANGED
@@ -183,7 +183,7 @@ def open(item: Union[list, str, BinaryIO, Path], *args, **kwargs):
|
|
183
183
|
first_fh = first
|
184
184
|
else:
|
185
185
|
first_path = first
|
186
|
-
if first_path.
|
186
|
+
if first_path.is_file():
|
187
187
|
first_fh = first.open("rb")
|
188
188
|
first_fh_opened = True
|
189
189
|
|
@@ -213,4 +213,6 @@ register("vhdx", "VhdxContainer")
|
|
213
213
|
register("vhd", "VhdContainer")
|
214
214
|
register("qcow2", "QCow2Container")
|
215
215
|
register("vdi", "VdiContainer")
|
216
|
+
register("hdd", "HddContainer")
|
217
|
+
register("hds", "HdsContainer")
|
216
218
|
register("split", "SplitContainer")
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import io
|
2
|
+
from pathlib import Path
|
3
|
+
from typing import BinaryIO, Union
|
4
|
+
|
5
|
+
from dissect.hypervisor import hdd
|
6
|
+
|
7
|
+
from dissect.target.container import Container
|
8
|
+
|
9
|
+
|
10
|
+
class HddContainer(Container):
|
11
|
+
def __init__(self, fh: Path, *args, **kwargs):
|
12
|
+
if hasattr(fh, "read"):
|
13
|
+
raise TypeError("HddContainer can only be opened by path")
|
14
|
+
|
15
|
+
self.hdd = hdd.HDD(fh)
|
16
|
+
self.stream = self.hdd.open()
|
17
|
+
super().__init__(fh, self.stream.size, *args, **kwargs)
|
18
|
+
|
19
|
+
@staticmethod
|
20
|
+
def detect_fh(fh: BinaryIO, original: Union[list, BinaryIO]) -> bool:
|
21
|
+
return False
|
22
|
+
|
23
|
+
@staticmethod
|
24
|
+
def detect_path(path: Path, original: Union[list, BinaryIO]) -> bool:
|
25
|
+
return path.suffix.lower() == ".hdd"
|
26
|
+
|
27
|
+
def read(self, length: int) -> bytes:
|
28
|
+
return self.stream.read(length)
|
29
|
+
|
30
|
+
def seek(self, offset: int, whence: int = io.SEEK_SET) -> int:
|
31
|
+
return self.stream.seek(offset, whence)
|
32
|
+
|
33
|
+
def tell(self) -> int:
|
34
|
+
return self.stream.tell()
|
35
|
+
|
36
|
+
def close(self) -> None:
|
37
|
+
self.stream.close()
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import io
|
2
|
+
from pathlib import Path
|
3
|
+
from typing import BinaryIO, Union
|
4
|
+
|
5
|
+
from dissect.hypervisor.disk import hdd
|
6
|
+
from dissect.hypervisor.disk.c_hdd import c_hdd
|
7
|
+
|
8
|
+
from dissect.target.container import Container
|
9
|
+
|
10
|
+
|
11
|
+
class HdsContainer(Container):
|
12
|
+
def __init__(self, fh: Union[BinaryIO, Path], *args, **kwargs):
|
13
|
+
f = fh
|
14
|
+
if not hasattr(fh, "read"):
|
15
|
+
f = fh.open("rb")
|
16
|
+
|
17
|
+
self.hds = hdd.HDS(f)
|
18
|
+
super().__init__(fh, self.hds.size, *args, **kwargs)
|
19
|
+
|
20
|
+
@staticmethod
|
21
|
+
def detect_fh(fh: BinaryIO, original: Union[list, BinaryIO]) -> bool:
|
22
|
+
sig = fh.read(16)
|
23
|
+
fh.seek(-16, io.SEEK_CUR)
|
24
|
+
|
25
|
+
return sig in (c_hdd.SIGNATURE_STRUCTURED_DISK_V1, c_hdd.SIGNATURE_STRUCTURED_DISK_V2)
|
26
|
+
|
27
|
+
@staticmethod
|
28
|
+
def detect_path(path: Path, original: Union[list, BinaryIO]) -> bool:
|
29
|
+
return path.suffix.lower() == ".hds"
|
30
|
+
|
31
|
+
def read(self, length: int) -> bytes:
|
32
|
+
return self.hds.read(length)
|
33
|
+
|
34
|
+
def seek(self, offset: int, whence: int = io.SEEK_SET) -> int:
|
35
|
+
return self.hds.seek(offset, whence)
|
36
|
+
|
37
|
+
def tell(self) -> int:
|
38
|
+
return self.hds.tell()
|
39
|
+
|
40
|
+
def close(self) -> None:
|
41
|
+
self.hds.close()
|
dissect/target/loader.py
CHANGED
@@ -182,6 +182,8 @@ register("tar", "TarLoader")
|
|
182
182
|
register("vmx", "VmxLoader")
|
183
183
|
register("vmwarevm", "VmwarevmLoader")
|
184
184
|
register("hyperv", "HyperVLoader")
|
185
|
+
register("pvs", "PvsLoader")
|
186
|
+
register("pvm", "PvmLoader")
|
185
187
|
register("ovf", "OvfLoader")
|
186
188
|
register("vbox", "VBoxLoader")
|
187
189
|
register("ewf", "EwfLoader")
|
@@ -0,0 +1,14 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
|
3
|
+
from dissect.target.loaders.pvs import PvsLoader
|
4
|
+
|
5
|
+
|
6
|
+
class PvmLoader(PvsLoader):
|
7
|
+
"""Parallels VM directory (.pvm)."""
|
8
|
+
|
9
|
+
def __init__(self, path: Path, **kwargs):
|
10
|
+
super().__init__(path.joinpath("config.pvs"))
|
11
|
+
|
12
|
+
@staticmethod
|
13
|
+
def detect(path: Path) -> bool:
|
14
|
+
return path.is_dir() and path.suffix.lower() == ".pvm" and path.joinpath("config.pvs").exists()
|
@@ -0,0 +1,35 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import TYPE_CHECKING
|
5
|
+
|
6
|
+
from dissect.hypervisor import pvs
|
7
|
+
|
8
|
+
from dissect.target.containers.hdd import HddContainer
|
9
|
+
from dissect.target.loader import Loader
|
10
|
+
|
11
|
+
if TYPE_CHECKING:
|
12
|
+
from dissect.target import Target
|
13
|
+
|
14
|
+
|
15
|
+
class PvsLoader(Loader):
|
16
|
+
"""Parallels VM configuration file (config.pvs)."""
|
17
|
+
|
18
|
+
def __init__(self, path: Path, **kwargs):
|
19
|
+
path = path.resolve()
|
20
|
+
|
21
|
+
super().__init__(path)
|
22
|
+
self.pvs = pvs.PVS(path.open("rt"))
|
23
|
+
self.base_dir = path.parent
|
24
|
+
|
25
|
+
@staticmethod
|
26
|
+
def detect(path: Path) -> bool:
|
27
|
+
return path.suffix.lower() == ".pvs"
|
28
|
+
|
29
|
+
def map(self, target: Target) -> None:
|
30
|
+
for disk in self.pvs.disks():
|
31
|
+
path = self.base_dir.joinpath(disk)
|
32
|
+
try:
|
33
|
+
target.disks.add(HddContainer(path))
|
34
|
+
except Exception:
|
35
|
+
target.log.exception("Failed to load HDD: %s", disk)
|
@@ -4,7 +4,7 @@ import logging
|
|
4
4
|
import re
|
5
5
|
import uuid
|
6
6
|
from struct import unpack
|
7
|
-
from typing import Iterator, Optional,
|
7
|
+
from typing import Iterator, Optional, Union
|
8
8
|
|
9
9
|
from dissect.target.filesystem import Filesystem
|
10
10
|
from dissect.target.helpers.fsutil import TargetPath
|
@@ -277,7 +277,7 @@ class UnixPlugin(OSPlugin):
|
|
277
277
|
def parse_fstab(
|
278
278
|
fstab: TargetPath,
|
279
279
|
log: logging.Logger = log,
|
280
|
-
) -> Iterator[
|
280
|
+
) -> Iterator[tuple[Union[uuid.UUID, str], str, str, str]]:
|
281
281
|
"""Parse fstab file and return a generator that streams the details of entries,
|
282
282
|
with unsupported FS types and block devices filtered away.
|
283
283
|
"""
|
@@ -315,7 +315,9 @@ def parse_fstab(
|
|
315
315
|
if dev.startswith(("/dev/mapper", "/dev/gpt")):
|
316
316
|
volume_name = dev.rsplit("/")[-1]
|
317
317
|
elif dev.startswith("/dev/") and dev.count("/") == 3:
|
318
|
-
|
318
|
+
# When composing a vg-lv name, LVM2 replaces hyphens with double hyphens in the vg and lv names
|
319
|
+
# Emulate that here when combining the vg and lv names
|
320
|
+
volume_name = "-".join(part.replace("-", "--") for part in dev.rsplit("/")[-2:])
|
319
321
|
elif dev.startswith("UUID="):
|
320
322
|
dev_id = dev.split("=")[1]
|
321
323
|
try:
|
dissect/target/volumes/lvm.py
CHANGED
@@ -48,5 +48,7 @@ class LvmVolumeSystem(LogicalVolumeSystem):
|
|
48
48
|
|
49
49
|
def _volumes(self) -> Iterator[Volume]:
|
50
50
|
for num, lv in enumerate(self.lvm.volume_group.logical_volumes):
|
51
|
-
|
51
|
+
# When composing a vg-lv name, LVM2 replaces hyphens with double hyphens in the vg and lv names
|
52
|
+
# Emulate that here for the volume name
|
53
|
+
name = f"{lv.vg.name.replace('-', '--')}-{lv.metadata.name.replace('-', '--')}"
|
52
54
|
yield Volume(lv, num, None, lv.size, None, name, raw=lv, vs=self)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: dissect.target
|
3
|
-
Version: 3.9.
|
3
|
+
Version: 3.9.dev26
|
4
4
|
Summary: This module ties all other Dissect modules together, it provides a programming API and command line tools which allow easy access to various data sources inside disk images or file collections (a.k.a. targets)
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
6
6
|
License: Affero General Public License v3
|
@@ -1,8 +1,8 @@
|
|
1
1
|
dissect/target/__init__.py,sha256=Oc7ounTgq2hE4nR6YcNabetc7SQA40ldSa35VEdZcQU,63
|
2
|
-
dissect/target/container.py,sha256=
|
2
|
+
dissect/target/container.py,sha256=R8M9EE7DqKq8DeMuekcpR1nxtZ827zuqmTmO4s7PYkg,7730
|
3
3
|
dissect/target/exceptions.py,sha256=w3qNa4dtGpxUkOCfmAQtvseQrpQq9qmO9wIbztRlIDQ,2273
|
4
4
|
dissect/target/filesystem.py,sha256=YJfuRzd37DIm91cVPlMZK-XjiJ1UCZG93htaYcSUrIk,46276
|
5
|
-
dissect/target/loader.py,sha256=
|
5
|
+
dissect/target/loader.py,sha256=Rg4X-4Lr2EtTzBA04WFWtPESF2iR1JNahKccMBImLZ0,7043
|
6
6
|
dissect/target/plugin.py,sha256=qF0okKg7TxYfiLVxpCWhb18gvDsNtr9nCYD7kSeaYIU,31955
|
7
7
|
dissect/target/report.py,sha256=06uiP4MbNI8cWMVrC1SasNS-Yg6ptjVjckwj8Yhe0Js,7958
|
8
8
|
dissect/target/target.py,sha256=TgDY-yAsReOQOG-Phz_m1vdNucdbk9fUI_RMZpMeYG8,28334
|
@@ -10,6 +10,8 @@ dissect/target/volume.py,sha256=vHBXdDttpiu-Q_oWycNM7fdJ5N8Ob7-i_UBJK9DEs24,1502
|
|
10
10
|
dissect/target/containers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
11
|
dissect/target/containers/asdf.py,sha256=g8omgyCvXBPd6ZZ1TKmaHNfzfs7W1HqmAsEAdDaXYLk,1398
|
12
12
|
dissect/target/containers/ewf.py,sha256=VEzjFH7R5GQB7ywKKyarYn9b9QdrBPxQ667Xh5WNmdQ,1370
|
13
|
+
dissect/target/containers/hdd.py,sha256=CenRlMNDmevCqccGPbSzOIPbdKIl0rHCtQ5kThOZQAU,1046
|
14
|
+
dissect/target/containers/hds.py,sha256=0nh9qoJ0SH0ADCEykpUrIU2tGt9xsksNAxs7ocILtdA,1175
|
13
15
|
dissect/target/containers/qcow2.py,sha256=RWmFeXfxAkU3OMGo7vfnOQTRlcWBH5-96LP37JB2o3o,1159
|
14
16
|
dissect/target/containers/raw.py,sha256=7fRHA5zIxBcBuGlACIJWvaSivjH98meNkyVLaR1Mi7k,1064
|
15
17
|
dissect/target/containers/split.py,sha256=dYibfeVddm-ux_ORjIAQxhqbWc9LKws3b8gYIXnINj4,2377
|
@@ -64,6 +66,8 @@ dissect/target/loaders/local.py,sha256=JEZN17wg4Tmw7nxQp2_6z97UuDx8ORxNLsgFs4rQh
|
|
64
66
|
dissect/target/loaders/ovf.py,sha256=3nd9ZinRRH71Qp0_r-lZURafNdXiKjyMw1zsgZRwjgo,924
|
65
67
|
dissect/target/loaders/phobos.py,sha256=r9mkITM8iuO60BHzDt-GkPMOFn4YWH0ahPRLSyEXAmA,1864
|
66
68
|
dissect/target/loaders/profile.py,sha256=73BlV0zAAPWBYY0tZAaX154kf7TZmwAwZhwCY4E43_A,1633
|
69
|
+
dissect/target/loaders/pvm.py,sha256=b-PvHNTbRVdOnf7-OR5dbikbDTCFlW85b-9Z8PEL2Cs,406
|
70
|
+
dissect/target/loaders/pvs.py,sha256=dMqdYSBQtH9QLM3tdu0mokLBcn73edg_HUtYtqrdi6E,955
|
67
71
|
dissect/target/loaders/raw.py,sha256=03OXVlvkqwR29XYu7WPg3pmGtYd_4QJEGnkAuvIrdPs,355
|
68
72
|
dissect/target/loaders/remote.py,sha256=AoI7-RxH2UMjNWnuHbNaieZycApTY3YZmk4wkQAwFt0,8820
|
69
73
|
dissect/target/loaders/res.py,sha256=2IAm-f83fvMUeK5J0g5jNVy2-24k8qKYijimcFvZ47I,8832
|
@@ -135,7 +139,7 @@ dissect/target/plugins/general/scrape.py,sha256=eBcFv6Po4FJ9HV829U3Bc5eWPtsuqFpd
|
|
135
139
|
dissect/target/plugins/general/users.py,sha256=qCXXsNOf3-IBgMUJjeH56RVhFeAsTSkXXaxWX-irYvU,2140
|
136
140
|
dissect/target/plugins/os/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
137
141
|
dissect/target/plugins/os/unix/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
138
|
-
dissect/target/plugins/os/unix/_os.py,sha256=
|
142
|
+
dissect/target/plugins/os/unix/_os.py,sha256=VUxsf3DzZlMhBsPrKKn3U5Wd4I4WyrwlEnyTeFoMi5s,12336
|
139
143
|
dissect/target/plugins/os/unix/cronjobs.py,sha256=3g2_EoXmRIvqwhASnn6p-iN3c8g70bLMWfzyN38znbA,3508
|
140
144
|
dissect/target/plugins/os/unix/datetime.py,sha256=21OyCR1g6wa6q5sGZTK3Kv4Jduoxj3o4A8GsdqK9JDQ,1510
|
141
145
|
dissect/target/plugins/os/unix/generic.py,sha256=R9fi1qNDaY5_l5g0XVLuXv1jOSz9wpb6zPVmWY3rczk,1835
|
@@ -254,12 +258,12 @@ dissect/target/tools/dump/utils.py,sha256=nYcLQvPpDgzckM62hokGBh4z32DNH6d6oA8Kel
|
|
254
258
|
dissect/target/volumes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
255
259
|
dissect/target/volumes/bde.py,sha256=gYGg5yF9MNARwNzEkrEfZmKkxyZW4rhLkpdnPJCbhGk,3662
|
256
260
|
dissect/target/volumes/disk.py,sha256=95grSsPt1BLVpKwTclwQYzPFGKTkFFqapIk0RoGWf38,968
|
257
|
-
dissect/target/volumes/lvm.py,sha256=
|
261
|
+
dissect/target/volumes/lvm.py,sha256=_kIB1mdRs1OFhRgoT4VEP5Fv8imQnI7oQ_ie4x710tQ,1814
|
258
262
|
dissect/target/volumes/vmfs.py,sha256=mlAJ8278tYaoRjk1u6tFFlCaDQUrVu5ZZE4ikiFvxi8,1707
|
259
|
-
dissect.target-3.9.
|
260
|
-
dissect.target-3.9.
|
261
|
-
dissect.target-3.9.
|
262
|
-
dissect.target-3.9.
|
263
|
-
dissect.target-3.9.
|
264
|
-
dissect.target-3.9.
|
265
|
-
dissect.target-3.9.
|
263
|
+
dissect.target-3.9.dev26.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
|
264
|
+
dissect.target-3.9.dev26.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
265
|
+
dissect.target-3.9.dev26.dist-info/METADATA,sha256=KCYCb5u-wp6D3lF6nmSnDg9Qudwq5ktMBIs_I4OgxtI,9984
|
266
|
+
dissect.target-3.9.dev26.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
267
|
+
dissect.target-3.9.dev26.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
|
268
|
+
dissect.target-3.9.dev26.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
|
269
|
+
dissect.target-3.9.dev26.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|