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

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,,