dissect.target 3.20.dev16__py3-none-any.whl → 3.20.dev18__py3-none-any.whl

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.
@@ -0,0 +1,68 @@
1
+ from pathlib import Path
2
+ from typing import Iterator
3
+
4
+ from dissect.target.exceptions import UnsupportedPluginError
5
+ from dissect.target.helpers.fsutil import TargetPath
6
+ from dissect.target.helpers.record import ChildTargetRecord
7
+ from dissect.target.plugin import ChildTargetPlugin
8
+ from dissect.target.target import Target
9
+
10
+ PARALLELS_USER_PATHS = [
11
+ "Parallels",
12
+ "Documents/Parallels",
13
+ "Library/Group Containers/*.com.parallels.desktop.appstore/Shared/Parallels",
14
+ ]
15
+
16
+ PARALLELS_SYSTEM_PATHS = [
17
+ "/Users/Shared/Parallels",
18
+ ]
19
+
20
+
21
+ def find_pvms(target: Target) -> Iterator[TargetPath]:
22
+ """Finds virtual machines located in default folders on a macOS target.
23
+
24
+ Resources:
25
+ - https://kb.parallels.com/117333
26
+ """
27
+ for user_details in target.user_details.all_with_home():
28
+ for parallels_path in PARALLELS_SYSTEM_PATHS:
29
+ if (path := target.fs.path(parallels_path)).exists():
30
+ yield from iter_vms(path)
31
+
32
+ for parallels_path in PARALLELS_USER_PATHS:
33
+ if "*" in parallels_path:
34
+ start_path, pattern = parallels_path.split("*", 1)
35
+ for path in user_details.home_path.joinpath(start_path).rglob("*" + pattern):
36
+ yield from iter_vms(path)
37
+ else:
38
+ if (path := user_details.home_path.joinpath(parallels_path)).exists():
39
+ yield from iter_vms(path)
40
+
41
+
42
+ def iter_vms(path: Path) -> Iterator[TargetPath]:
43
+ """Glob for .pvm folders in the provided folder."""
44
+ for file in path.rglob("*.pvm"):
45
+ if file.is_dir():
46
+ yield file
47
+
48
+
49
+ class ParallelsChildTargetPlugin(ChildTargetPlugin):
50
+ """Child target plugin that yields Parallels Desktop VM files."""
51
+
52
+ __type__ = "parallels"
53
+
54
+ def __init__(self, target: Target):
55
+ super().__init__(target)
56
+ self.pvms = list(find_pvms(target))
57
+
58
+ def check_compatible(self) -> None:
59
+ if not self.pvms:
60
+ raise UnsupportedPluginError("No Parallels pvm file(s) found")
61
+
62
+ def list_children(self) -> Iterator[ChildTargetRecord]:
63
+ for pvm in self.pvms:
64
+ yield ChildTargetRecord(
65
+ type=self.__type__,
66
+ path=pvm,
67
+ _target=self.target,
68
+ )
@@ -96,6 +96,7 @@ class ExtendedCmd(cmd.Cmd):
96
96
 
97
97
  CMD_PREFIX = "cmd_"
98
98
  _runtime_aliases = {}
99
+ DEFAULT_RUNCOMMANDS_FILE = None
99
100
 
100
101
  def __init__(self, cyber: bool = False):
101
102
  cmd.Cmd.__init__(self)
@@ -121,6 +122,28 @@ class ExtendedCmd(cmd.Cmd):
121
122
 
122
123
  return object.__getattribute__(self, attr)
123
124
 
125
+ def _load_targetrc(self, path: pathlib.Path) -> None:
126
+ """Load and execute commands from the run commands file."""
127
+ try:
128
+ with path.open() as fh:
129
+ for line in fh:
130
+ if (line := line.strip()) and not line.startswith("#"): # Ignore empty lines and comments
131
+ self.onecmd(line)
132
+ except FileNotFoundError:
133
+ # The .targetrc file is optional
134
+ pass
135
+ except Exception as e:
136
+ log.debug("Error processing .targetrc file: %s", e)
137
+
138
+ def _get_targetrc_path(self) -> pathlib.Path | None:
139
+ """Get the path to the run commands file. Can return ``None`` if ``DEFAULT_RUNCOMMANDS_FILE`` is not set."""
140
+ return pathlib.Path(self.DEFAULT_RUNCOMMANDS_FILE).expanduser() if self.DEFAULT_RUNCOMMANDS_FILE else None
141
+
142
+ def preloop(self) -> None:
143
+ super().preloop()
144
+ if targetrc_path := self._get_targetrc_path():
145
+ self._load_targetrc(targetrc_path)
146
+
124
147
  @staticmethod
125
148
  def check_compatible(target: Target) -> bool:
126
149
  return True
@@ -309,6 +332,8 @@ class TargetCmd(ExtendedCmd):
309
332
  DEFAULT_HISTFILESIZE = 10_000
310
333
  DEFAULT_HISTDIR = None
311
334
  DEFAULT_HISTDIRFMT = ".dissect_history_{uid}_{target}"
335
+ DEFAULT_RUNCOMMANDS_FILE = "~/.targetrc"
336
+ CONFIG_KEY_RUNCOMMANDS_FILE = "TARGETRCFILE"
312
337
 
313
338
  def __init__(self, target: Target):
314
339
  self.target = target
@@ -338,7 +363,15 @@ class TargetCmd(ExtendedCmd):
338
363
 
339
364
  super().__init__(self.target.props.get("cyber"))
340
365
 
366
+ def _get_targetrc_path(self) -> pathlib.Path:
367
+ """Get the path to the run commands file."""
368
+
369
+ return pathlib.Path(
370
+ getattr(self.target._config, self.CONFIG_KEY_RUNCOMMANDS_FILE, self.DEFAULT_RUNCOMMANDS_FILE)
371
+ ).expanduser()
372
+
341
373
  def preloop(self) -> None:
374
+ super().preloop()
342
375
  if readline and self.histfile.exists():
343
376
  try:
344
377
  readline.read_history_file(self.histfile)
@@ -507,7 +540,6 @@ class TargetCli(TargetCmd):
507
540
  self.prompt_base = _target_name(target)
508
541
 
509
542
  TargetCmd.__init__(self, target)
510
-
511
543
  self._clicache = {}
512
544
  self.cwd = None
513
545
  self.chdir("/")
@@ -1144,6 +1176,10 @@ class UnixConfigTreeCli(TargetCli):
1144
1176
  class RegistryCli(TargetCmd):
1145
1177
  """CLI for browsing the registry."""
1146
1178
 
1179
+ # Registry shell is incompatible with default shell, so override the default rc file and config key
1180
+ DEFAULT_RUNCOMMANDS_FILE = "~/.targetrc.registry"
1181
+ CONFIG_KEY_RUNCOMMANDS_FILE = "TARGETRCFILE_REGISTRY"
1182
+
1147
1183
  def __init__(self, target: Target, registry: regutil.RegfHive | None = None):
1148
1184
  self.prompt_base = _target_name(target)
1149
1185
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.20.dev16
3
+ Version: 3.20.dev18
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
@@ -157,6 +157,7 @@ dissect/target/plugins/child/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
157
157
  dissect/target/plugins/child/docker.py,sha256=frBZ8UUzbtkT9VrK1fwUzXDAdkHESdPCb-QI_OP9Jj4,872
158
158
  dissect/target/plugins/child/esxi.py,sha256=GfgQzxntcHcyxAE2QjMJ-TrFhklweSXLbYh0uuv-klg,693
159
159
  dissect/target/plugins/child/hyperv.py,sha256=R2qVeu4p_9V53jO-65znN0LwX9v3FVA-9jbbtOQcEz8,2236
160
+ dissect/target/plugins/child/parallels.py,sha256=jeBT_NvTQbQBaUjqGWTy2I5Q5OWlrogoyWHRXjOhLis,2255
160
161
  dissect/target/plugins/child/qemu.py,sha256=vNzQwzFO964jYaI67MlX8vpWyHxpegjIU5F29zHKOGI,791
161
162
  dissect/target/plugins/child/virtuozzo.py,sha256=Mx4ZxEl21g7IYkzraw4FBZup5EfrkFDv4WuTE3hxguw,1206
162
163
  dissect/target/plugins/child/vmware_workstation.py,sha256=8wkA_tSufvBUyp4XQHzRzFETf5ROlyyO_MVS3TExyfw,1570
@@ -350,7 +351,7 @@ dissect/target/tools/logging.py,sha256=5ZnumtMWLyslxfrUGZ4ntRyf3obOOhmn8SBjKfdLc
350
351
  dissect/target/tools/mount.py,sha256=8GRYnu4xEmFBHxuIZAYhOMyyTGX8fat1Ou07DNiUnW4,3945
351
352
  dissect/target/tools/query.py,sha256=e-yAN9zdQjuOiTuoOQoo17mVEQGGcOgaA9YkF4GYpkM,15394
352
353
  dissect/target/tools/reg.py,sha256=FDsiBBDxjWVUBTRj8xn82vZe-J_d9piM-TKS3PHZCcM,3193
353
- dissect/target/tools/shell.py,sha256=7jur65pFugpZHyfA0MkaMPCYWZPUSFjhkFQZO8IBYXQ,52077
354
+ dissect/target/tools/shell.py,sha256=0RqcPmOmFEQ0-5Efqm8ZdGbTeZw2OXFFaCGNyCCzUVs,53714
354
355
  dissect/target/tools/utils.py,sha256=JJZDSso1CEK2sv4Z3HJNgqxH6G9S5lbmV-C3h-XmcMo,12035
355
356
  dissect/target/tools/yara.py,sha256=70k-2VMulf1EdkX03nCACzejaOEcsFHOyX-4E40MdQU,2044
356
357
  dissect/target/tools/dump/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -365,10 +366,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
365
366
  dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
366
367
  dissect/target/volumes/md.py,sha256=7ShPtusuLGaIv27SvEETtgsuoQyAa4iAAeOR1NEaajI,1689
367
368
  dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
368
- dissect.target-3.20.dev16.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
369
- dissect.target-3.20.dev16.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
370
- dissect.target-3.20.dev16.dist-info/METADATA,sha256=RLzyPf8gnwZFIOTzoWItUBwzSzdMYkdoBdJnENDslDk,12897
371
- dissect.target-3.20.dev16.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
372
- dissect.target-3.20.dev16.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
373
- dissect.target-3.20.dev16.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
374
- dissect.target-3.20.dev16.dist-info/RECORD,,
369
+ dissect.target-3.20.dev18.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
370
+ dissect.target-3.20.dev18.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
371
+ dissect.target-3.20.dev18.dist-info/METADATA,sha256=mgzYr9ayweYe6lsopWNXI3cfGRMDemWb8ydUGkZayvU,12897
372
+ dissect.target-3.20.dev18.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
373
+ dissect.target-3.20.dev18.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
374
+ dissect.target-3.20.dev18.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
375
+ dissect.target-3.20.dev18.dist-info/RECORD,,