dissect.target 3.19.dev33__py3-none-any.whl → 3.19.dev35__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,27 +1,35 @@
1
+ from __future__ import annotations
2
+
1
3
  import ast
2
4
  import importlib.machinery
3
5
  import importlib.util
4
6
  import logging
5
7
  from pathlib import Path
6
8
  from types import ModuleType
7
- from typing import Optional, Union
8
9
 
9
10
  log = logging.getLogger(__name__)
10
11
 
11
12
  CONFIG_NAME = ".targetcfg.py"
12
13
 
13
14
 
14
- def load(path: Optional[Union[Path, str]]) -> ModuleType:
15
+ def load(paths: list[Path | str] | Path | str | None) -> ModuleType:
16
+ """Attempt to load one configuration from the provided path(s)."""
17
+
18
+ if isinstance(paths, Path) or isinstance(paths, str):
19
+ paths = [paths]
20
+
15
21
  config_spec = importlib.machinery.ModuleSpec("config", None)
16
22
  config = importlib.util.module_from_spec(config_spec)
17
- config_file = _find_config_file(path)
23
+ config_file = _find_config_file(paths)
24
+
18
25
  if config_file:
19
26
  config_values = _parse_ast(config_file.read_bytes())
20
27
  config.__dict__.update(config_values)
28
+
21
29
  return config
22
30
 
23
31
 
24
- def _parse_ast(code: str) -> dict[str, Union[str, int]]:
32
+ def _parse_ast(code: str) -> dict[str, str | int]:
25
33
  # Only allow basic value assignments for backwards compatibility
26
34
  obj = {}
27
35
 
@@ -49,15 +57,19 @@ def _parse_ast(code: str) -> dict[str, Union[str, int]]:
49
57
  return obj
50
58
 
51
59
 
52
- def _find_config_file(path: Optional[Union[Path, str]]) -> Optional[Path]:
53
- """Find a config file anywhere in the given path and return it.
60
+ def _find_config_file(paths: list[Path | str] | None) -> Path | None:
61
+ """Find a config file anywhere in the given path(s) and return it.
54
62
 
55
63
  This algorithm allows parts of the path to not exist or the last part to be a filename.
56
64
  It also does not look in the root directory ('/') for config files.
57
65
  """
58
66
 
67
+ if not paths:
68
+ return
69
+
59
70
  config_file = None
60
- if path:
71
+
72
+ for path in paths:
61
73
  path = Path(path)
62
74
  cur_path = path.absolute()
63
75
 
@@ -69,4 +81,7 @@ def _find_config_file(path: Optional[Union[Path, str]]) -> Optional[Path]:
69
81
  config_file = cur_config
70
82
  cur_path = cur_path.parent
71
83
 
84
+ if config_file:
85
+ break
86
+
72
87
  return config_file
@@ -45,7 +45,7 @@ class YaraPlugin(Plugin):
45
45
 
46
46
  @arg("-r", "--rules", required=True, nargs="*", help="path(s) to YARA rule file(s) or folder(s)")
47
47
  @arg("-p", "--path", default="/", help="path on target(s) to recursively scan")
48
- @arg("-m", "--max-size", default=DEFAULT_MAX_SCAN_SIZE, help="maximum file size in bytes to scan")
48
+ @arg("-m", "--max-size", type=int, default=DEFAULT_MAX_SCAN_SIZE, help="maximum file size in bytes to scan")
49
49
  @arg("-c", "--check", default=False, action="store_true", help="check if every YARA rule is valid")
50
50
  @export(record=YaraMatchRecord)
51
51
  def yara(
dissect/target/target.py CHANGED
@@ -87,9 +87,10 @@ class Target:
87
87
  self._applied = False
88
88
 
89
89
  try:
90
- self._config = config.load(self.path)
90
+ self._config = config.load([self.path, os.getcwd()])
91
91
  except Exception as e:
92
- self.log.debug("Error loading config file", exc_info=e)
92
+ self.log.warning("Error loading config file: %s", self.path)
93
+ self.log.debug("", exc_info=e)
93
94
  self._config = config.load(None) # This loads an empty config.
94
95
 
95
96
  # Fill the disks and/or volumes and/or filesystems and apply() will
@@ -58,6 +58,7 @@ try:
58
58
  except ImportError:
59
59
  # Readline is not available on Windows
60
60
  log.warning("Readline module is not available")
61
+ readline = None
61
62
 
62
63
  # ['mode', 'addr', 'dev', 'nlink', 'uid', 'gid', 'size', 'atime', 'mtime', 'ctime']
63
64
  STAT_TEMPLATE = """ File: {path} {symlink}
@@ -111,12 +112,43 @@ class TargetCmd(cmd.Cmd):
111
112
 
112
113
  CMD_PREFIX = "cmd_"
113
114
 
115
+ DEFAULT_HISTFILE = "~/.dissect_history"
116
+ DEFAULT_HISTFILESIZE = 10_000
117
+ DEFAULT_HISTDIR = None
118
+ DEFAULT_HISTDIRFMT = ".dissect_history_{uid}_{target}"
119
+
114
120
  def __init__(self, target: Target):
115
121
  cmd.Cmd.__init__(self)
116
122
  self.target = target
117
123
  self.debug = False
118
124
  self.identchars += "."
119
125
 
126
+ self.histfilesize = getattr(target._config, "HISTFILESIZE", self.DEFAULT_HISTFILESIZE)
127
+ self.histdir = getattr(target._config, "HISTDIR", self.DEFAULT_HISTDIR)
128
+
129
+ if self.histdir:
130
+ self.histdirfmt = getattr(target._config, "HISTDIRFMT", self.DEFAULT_HISTDIRFMT)
131
+ self.histfile = pathlib.Path(self.histdir).resolve() / pathlib.Path(
132
+ self.histdirfmt.format(uid=os.getuid(), target=target.name)
133
+ )
134
+ else:
135
+ self.histfile = pathlib.Path(getattr(target._config, "HISTFILE", self.DEFAULT_HISTFILE)).expanduser()
136
+
137
+ def preloop(self) -> None:
138
+ if readline and self.histfile.exists():
139
+ try:
140
+ readline.read_history_file(self.histfile)
141
+ except Exception as e:
142
+ log.debug("Error reading history file: %s", e)
143
+
144
+ def postloop(self) -> None:
145
+ if readline:
146
+ readline.set_history_length(self.histfilesize)
147
+ try:
148
+ readline.write_history_file(self.histfile)
149
+ except Exception as e:
150
+ log.debug("Error writing history file: %s", e)
151
+
120
152
  def __getattr__(self, attr: str) -> Any:
121
153
  if attr.startswith("help_"):
122
154
  _, _, command = attr.partition("_")
@@ -1241,10 +1273,11 @@ def run_cli(cli: cmd.Cmd) -> None:
1241
1273
  # Print an empty newline on exit
1242
1274
  print()
1243
1275
  return
1276
+
1244
1277
  except KeyboardInterrupt:
1245
1278
  # Add a line when pressing ctrl+c, so the next one starts at a new line
1246
1279
  print()
1247
- pass
1280
+
1248
1281
  except Exception as e:
1249
1282
  if cli.debug:
1250
1283
  log.exception(e)
@@ -1252,7 +1285,6 @@ def run_cli(cli: cmd.Cmd) -> None:
1252
1285
  log.info(e)
1253
1286
  print(f"*** Unhandled error: {e}")
1254
1287
  print("If you wish to see the full debug trace, enable debug mode.")
1255
- pass
1256
1288
 
1257
1289
 
1258
1290
  @catch_sigpipe
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.19.dev33
3
+ Version: 3.19.dev35
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
@@ -5,7 +5,7 @@ dissect/target/filesystem.py,sha256=G1gbOUpnQZyovubYGEUKgaDV0eHH5vE83-0gTc5PZAM,
5
5
  dissect/target/loader.py,sha256=I8WNzDA0SMy42F7zfyBcSKj_VKNv64213WUvtGZ77qE,7374
6
6
  dissect/target/plugin.py,sha256=HAN8maaDt-Rlqt8Rr1IW7gXQpzNQZjCVz-i4aSPphSw,48677
7
7
  dissect/target/report.py,sha256=06uiP4MbNI8cWMVrC1SasNS-Yg6ptjVjckwj8Yhe0Js,7958
8
- dissect/target/target.py,sha256=KZ3vDsMjrXxEP6sQE1kOlxMNjqFFsxnivYhoX26GBEY,32363
8
+ dissect/target/target.py,sha256=nqd5OuVTwYR7XSzlMp7SHQoRCgZD_Z7QshnEEKcX-tw,32426
9
9
  dissect/target/volume.py,sha256=aQZAJiny8jjwkc9UtwIRwy7nINXjCxwpO-_UDfh6-BA,15801
10
10
  dissect/target/containers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  dissect/target/containers/asdf.py,sha256=DJp0QEFwUjy2MFwKYcYqIR_BS1fQT1Yi9Kcmqt0aChM,1366
@@ -45,7 +45,7 @@ dissect/target/filesystems/xfs.py,sha256=kIyFGKYlyFYC7H3jaEv-lNKtBW4ZkD92H0WpfGc
45
45
  dissect/target/filesystems/zip.py,sha256=WT1bQhzX_1MXXVZTKrJniae4xqRqMZ8FsfbvhgGQRTQ,4462
46
46
  dissect/target/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
47
  dissect/target/helpers/cache.py,sha256=TXlJBdFRz6V9zKs903am4Yawr0maYw5kZY0RqklDQJM,8568
48
- dissect/target/helpers/config.py,sha256=6917CZ6eDHaK_tOoiVEIndyhRXO6r6eCBIleq6f47PQ,2346
48
+ dissect/target/helpers/config.py,sha256=RMHnIuKJHINHiLrvKN3EyA0jFA1o6-pbeaycG8Pgrp8,2596
49
49
  dissect/target/helpers/configutil.py,sha256=AEnkMQ0e6PncvCqGa-ACzBQWQBhMGBCzO5qzGJtRu60,27644
50
50
  dissect/target/helpers/cyber.py,sha256=WnJlk-HqAETmDAgLq92JPxyDLxvzSoFV_WrO-odVKBI,16805
51
51
  dissect/target/helpers/descriptor_extensions.py,sha256=uT8GwznfDAiIgMM7JKKOY0PXKMv2c0GCqJTCkWFgops,2605
@@ -164,7 +164,7 @@ dissect/target/plugins/filesystem/acquire_hash.py,sha256=OVxI19-Bl1tdqCiFMscFMLm
164
164
  dissect/target/plugins/filesystem/icat.py,sha256=bOMi04IlljnKwxTWTZJKtK7RxKnabFu3WcXyUwzkE-4,4090
165
165
  dissect/target/plugins/filesystem/resolver.py,sha256=HfyASUFV4F9uD-yFXilFpPTORAsRDvdmTvuYHgOaOWg,4776
166
166
  dissect/target/plugins/filesystem/walkfs.py,sha256=e8HEZcV5Wiua26FGWL3xgiQ_PIhcNvGI5KCdsAx2Nmo,2298
167
- dissect/target/plugins/filesystem/yara.py,sha256=w9kJ8trua0rhcpaN18erc0vGIFsJJeqaV6y5lMRl8JQ,6611
167
+ dissect/target/plugins/filesystem/yara.py,sha256=zh4hU3L_egddLqDeaHDVuCWYhTlNzPYPVak36Q6IMxI,6621
168
168
  dissect/target/plugins/filesystem/ntfs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
169
169
  dissect/target/plugins/filesystem/ntfs/mft.py,sha256=2ibCLJA7yUrZshFSPKdjoNt3TpfwTtk-DaErghe91CM,11445
170
170
  dissect/target/plugins/filesystem/ntfs/mft_timeline.py,sha256=vvNFAZbr7s3X2OTYf4ES_L6-XsouTXcTymfxnHfZ1Rw,6791
@@ -331,7 +331,7 @@ dissect/target/tools/logging.py,sha256=5ZnumtMWLyslxfrUGZ4ntRyf3obOOhmn8SBjKfdLc
331
331
  dissect/target/tools/mount.py,sha256=L_0tSmiBdW4aSaF0vXjB0bAkTC0kmT2N1hrbW6s5Jow,3254
332
332
  dissect/target/tools/query.py,sha256=ONHu2FVomLccikb84qBrlhNmEfRoHYFQMcahk_y2c9A,15580
333
333
  dissect/target/tools/reg.py,sha256=FDsiBBDxjWVUBTRj8xn82vZe-J_d9piM-TKS3PHZCcM,3193
334
- dissect/target/tools/shell.py,sha256=_widEuIRqZhYzcFR52NYI8O2aPFm6tG5Uiv-AIrC32U,45155
334
+ dissect/target/tools/shell.py,sha256=sjoc4nI9fsU5ZG7nDPNZvE-RtIPTwREbVdbg8WA3XTo,46442
335
335
  dissect/target/tools/utils.py,sha256=sQizexY3ui5vmWw4KOBLg5ecK3TPFjD-uxDqRn56ZTY,11304
336
336
  dissect/target/tools/yara.py,sha256=70k-2VMulf1EdkX03nCACzejaOEcsFHOyX-4E40MdQU,2044
337
337
  dissect/target/tools/dump/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -346,10 +346,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
346
346
  dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
347
347
  dissect/target/volumes/md.py,sha256=7ShPtusuLGaIv27SvEETtgsuoQyAa4iAAeOR1NEaajI,1689
348
348
  dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
349
- dissect.target-3.19.dev33.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
350
- dissect.target-3.19.dev33.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
351
- dissect.target-3.19.dev33.dist-info/METADATA,sha256=qql1vSsBtkxg9RPKiPg49ssQekDjKwQfE3GKlxWsjCk,12719
352
- dissect.target-3.19.dev33.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
353
- dissect.target-3.19.dev33.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
354
- dissect.target-3.19.dev33.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
355
- dissect.target-3.19.dev33.dist-info/RECORD,,
349
+ dissect.target-3.19.dev35.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
350
+ dissect.target-3.19.dev35.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
351
+ dissect.target-3.19.dev35.dist-info/METADATA,sha256=3ApP47TWFjPe5wV6_fuejtFbpr7YL-bwmvPePNKfN1M,12719
352
+ dissect.target-3.19.dev35.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
353
+ dissect.target-3.19.dev35.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
354
+ dissect.target-3.19.dev35.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
355
+ dissect.target-3.19.dev35.dist-info/RECORD,,