dissect.target 3.16.dev29__py3-none-any.whl → 3.16.dev31__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.
@@ -60,6 +60,8 @@ class IISLogsPlugin(WebserverPlugin):
60
60
  super().__init__(target)
61
61
  self.config = self.target.fs.path(self.APPLICATION_HOST_CONFIG)
62
62
 
63
+ self._create_extended_descriptor = lru_cache(4096)(self._create_extended_descriptor)
64
+
63
65
  def check_compatible(self) -> None:
64
66
  if not self.config.exists() and not self.target.fs.path("sysvol/files").exists():
65
67
  raise UnsupportedPluginError("No ApplicationHost config file found")
@@ -157,7 +159,6 @@ class IISLogsPlugin(WebserverPlugin):
157
159
  row = replace_dash_with_none(row)
158
160
  yield BasicRecordDescriptor(**row)
159
161
 
160
- @lru_cache(maxsize=4096)
161
162
  def _create_extended_descriptor(self, extra_fields: tuple[tuple[str, str]]) -> TargetRecordDescriptor:
162
163
  return TargetRecordDescriptor(LOG_RECORD_NAME, BASIC_RECORD_FIELDS + list(extra_fields))
163
164
 
@@ -4,6 +4,7 @@ import gzip
4
4
  import json
5
5
  import lzma
6
6
  import struct
7
+ import subprocess
7
8
  from configparser import ConfigParser
8
9
  from configparser import Error as ConfigParserError
9
10
  from io import BytesIO
@@ -13,6 +14,8 @@ from defusedxml import ElementTree
13
14
  from dissect.hypervisor.util import vmtar
14
15
  from dissect.sql import sqlite3
15
16
 
17
+ from dissect.target.helpers.fsutil import TargetPath
18
+
16
19
  try:
17
20
  from dissect.hypervisor.util.envelope import Envelope, KeyStore
18
21
 
@@ -217,23 +220,72 @@ def _mount_local(target: Target, local_layer: VirtualFilesystem):
217
220
  local_fs = tar.TarFilesystem(local_tgz.open())
218
221
  else:
219
222
  local_tgz_ve = target.fs.path("local.tgz.ve")
220
- encryption_info = target.fs.path("encryption.info")
223
+ # In the case "encryption.info" does not exist, but ".#encryption.info" does
224
+ encryption_info = next(target.fs.path("/").glob("*encryption.info"), None)
221
225
  if not local_tgz_ve.exists() or not encryption_info.exists():
222
226
  raise ValueError("Unable to find valid configuration archive")
223
227
 
224
- if HAS_ENVELOPE:
225
- target.log.info("local.tgz is encrypted, attempting to decrypt")
226
- envelope = Envelope(local_tgz_ve.open())
227
- keystore = KeyStore.from_text(encryption_info.read_text("utf-8"))
228
- local_tgz = BytesIO(envelope.decrypt(keystore.key, aad=b"ESXConfiguration"))
229
- local_fs = tar.TarFilesystem(local_tgz)
230
- else:
231
- target.log.warning("local.tgz is encrypted but no crypto module available!")
228
+ local_fs = _create_local_fs(target, local_tgz_ve, encryption_info)
232
229
 
233
230
  if local_fs:
234
231
  local_layer.mount("/", local_fs)
235
232
 
236
233
 
234
+ def _decrypt_envelope(local_tgz_ve: TargetPath, encryption_info: TargetPath) -> BinaryIO:
235
+ """Decrypt ``local.tgz.ve`` ourselves with hard-coded keys."""
236
+ envelope = Envelope(local_tgz_ve.open())
237
+ keystore = KeyStore.from_text(encryption_info.read_text("utf-8"))
238
+ local_tgz = BytesIO(envelope.decrypt(keystore.key, aad=b"ESXConfiguration"))
239
+ return local_tgz
240
+
241
+
242
+ def _decrypt_crypto_util(local_tgz_ve: TargetPath) -> Optional[BytesIO]:
243
+ """Decrypt ``local.tgz.ve`` using ESXi ``crypto-util``.
244
+
245
+ We write to stdout, but this results in ``crypto-util`` exiting with a non-zero return code
246
+ and stderr containing an I/O error message. The file does get properly decrypted, so we return
247
+ ``None`` if there are no bytes in stdout which would indicate it actually failed.
248
+ """
249
+
250
+ result = subprocess.run(
251
+ ["crypto-util", "envelope", "extract", "--aad", "ESXConfiguration", f"/{local_tgz_ve.as_posix()}", "-"],
252
+ capture_output=True,
253
+ )
254
+
255
+ if len(result.stdout) == 0:
256
+ return None
257
+
258
+ return BytesIO(result.stdout)
259
+
260
+
261
+ def _create_local_fs(
262
+ target: Target, local_tgz_ve: TargetPath, encryption_info: TargetPath
263
+ ) -> Optional[tar.TarFilesystem]:
264
+ local_tgz = None
265
+
266
+ if HAS_ENVELOPE:
267
+ try:
268
+ local_tgz = _decrypt_envelope(local_tgz_ve, encryption_info)
269
+ except NotImplementedError:
270
+ target.log.debug("Failed to decrypt %s, likely TPM encrypted", local_tgz_ve)
271
+ else:
272
+ target.log.debug("Skipping static decryption because of missing crypto module")
273
+
274
+ if not local_tgz and target.name == "local":
275
+ target.log.info(
276
+ "local.tgz is encrypted but static decryption failed, attempting dynamic decryption using crypto-util"
277
+ )
278
+ local_tgz = _decrypt_crypto_util(local_tgz_ve)
279
+
280
+ if local_tgz is None:
281
+ target.log.warning("Dynamic decryption of %s failed.", local_tgz_ve)
282
+ else:
283
+ target.log.warning("local.tgz is encrypted but static decryption failed and no dynamic decryption available!")
284
+
285
+ if local_tgz:
286
+ return tar.TarFilesystem(local_tgz)
287
+
288
+
237
289
  def _mount_filesystems(target: Target, sysvol: Filesystem, cfg: dict[str, str]):
238
290
  version = cfg["build"]
239
291
 
@@ -13,6 +13,9 @@ from dissect.target.plugins.os.windows.datetime import parse_tzi
13
13
  class EtlRecordBuilder:
14
14
  RECORD_NAME = "filesystem/windows/etl"
15
15
 
16
+ def __init__(self):
17
+ self._create_event_descriptor = lru_cache(4096)(self._create_event_descriptor)
18
+
16
19
  def _build_record(self, etl_event: Event, etl_path: Path, target: Target):
17
20
  """Builds an ETL event record"""
18
21
 
@@ -51,7 +54,6 @@ class EtlRecordBuilder:
51
54
  desc = self._create_event_descriptor(tuple(record_fields))
52
55
  return desc(**record_values)
53
56
 
54
- @lru_cache(maxsize=4096)
55
57
  def _create_event_descriptor(self, record_fields):
56
58
  return TargetRecordDescriptor(self.RECORD_NAME, record_fields)
57
59
 
@@ -29,6 +29,7 @@ class EvtxPlugin(WindowsEventlogsMixin, plugin.Plugin):
29
29
 
30
30
  def __init__(self, target):
31
31
  super().__init__(target)
32
+ self._create_event_descriptor = lru_cache(4096)(self._create_event_descriptor)
32
33
 
33
34
  @plugin.arg("--logs-dir", help="logs directory to scan")
34
35
  @plugin.arg("--log-file-glob", default=EVTX_GLOB, help="glob pattern to match a log file name")
@@ -145,7 +146,6 @@ class EvtxPlugin(WindowsEventlogsMixin, plugin.Plugin):
145
146
  desc = self._create_event_descriptor(tuple(record_fields))
146
147
  return desc(**record_values)
147
148
 
148
- @lru_cache(maxsize=4096)
149
149
  def _create_event_descriptor(self, record_fields) -> TargetRecordDescriptor:
150
150
  return TargetRecordDescriptor(self.RECORD_NAME, record_fields)
151
151
 
@@ -72,6 +72,7 @@ class RegistryPlugin(Plugin):
72
72
 
73
73
  def __init__(self, target: Target) -> None:
74
74
  super().__init__(target)
75
+
75
76
  self._root = VirtualHive()
76
77
  self._hive_collections = defaultdict(HiveCollection)
77
78
  self._hive_paths = []
@@ -83,6 +84,8 @@ class RegistryPlugin(Plugin):
83
84
  self._users_loaded = False
84
85
  self._init_registry()
85
86
 
87
+ self.key = lru_cache(4096)(self.key)
88
+
86
89
  def _init_registry(self) -> None:
87
90
  dirs = [
88
91
  ("sysvol/windows/system32/config", False),
@@ -217,7 +220,6 @@ class RegistryPlugin(Plugin):
217
220
  return self.key()
218
221
 
219
222
  @internal
220
- @lru_cache(4096)
221
223
  def key(self, key: Optional[str] = None) -> KeyCollection:
222
224
  """Query the virtual registry on the given key.
223
225
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.16.dev29
3
+ Version: 3.16.dev31
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
@@ -143,7 +143,7 @@ dissect/target/plugins/apps/webserver/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCe
143
143
  dissect/target/plugins/apps/webserver/apache.py,sha256=bD6_XObfO7W-cFlLRWyhdwEfw-Y57JBi47rWnXCx-vg,15026
144
144
  dissect/target/plugins/apps/webserver/caddy.py,sha256=qZsAK_tILGvroV4SWkDKc-Otwd41bUEtv9H9TuHmt-0,6422
145
145
  dissect/target/plugins/apps/webserver/citrix.py,sha256=FEPdBteEJeeGg3B95W_27O9wLJVhenEc5A5fSLDmK18,3044
146
- dissect/target/plugins/apps/webserver/iis.py,sha256=UwRVzLqnKScijdLoZFfpkSUzKTQosicZpn16q__4QBU,14669
146
+ dissect/target/plugins/apps/webserver/iis.py,sha256=t92JGTuMbBlUma5BVurdOuzUYvrjpgT8NEHpu9Xz5F0,14734
147
147
  dissect/target/plugins/apps/webserver/nginx.py,sha256=WA5soi1FU1c44oHRcyOoHK3gH8Jzc_Qi5uXcimDYukw,4129
148
148
  dissect/target/plugins/apps/webserver/webserver.py,sha256=a7a2lLrhsa9c1AXnwiLP-tqVv-IUbmaVaSZI5S0fKa8,1500
149
149
  dissect/target/plugins/child/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -201,7 +201,7 @@ dissect/target/plugins/os/unix/bsd/osx/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JC
201
201
  dissect/target/plugins/os/unix/bsd/osx/_os.py,sha256=KvP7YJ7apVwoIop7MR-8q5QbVGoB6MdR42l6ssEe6es,4081
202
202
  dissect/target/plugins/os/unix/bsd/osx/user.py,sha256=qopB0s3n7e6Q7NjWzn8Z-dKtDtU7e6In4Vm7hIvvedo,2322
203
203
  dissect/target/plugins/os/unix/esxi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
204
- dissect/target/plugins/os/unix/esxi/_os.py,sha256=V3HtCdlZ5gl-aUhrHhzmUwH29iMrIxZCg3l48MjdCYI,15610
204
+ dissect/target/plugins/os/unix/esxi/_os.py,sha256=jqw71St-L_BiREai8bw27oFOrLK4_GuEDLUTK5FMGLU,17498
205
205
  dissect/target/plugins/os/unix/linux/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
206
206
  dissect/target/plugins/os/unix/linux/_os.py,sha256=YJYwuq_iAinOrPqTE49Q4DLYMWBeRCly1uTbDvPhp6Q,2796
207
207
  dissect/target/plugins/os/unix/linux/cmdline.py,sha256=XIvaTL42DzeQGhqHN_RTMI5g8hbI2_wjzb7KZ0kPOM0,1591
@@ -261,7 +261,7 @@ dissect/target/plugins/os/windows/locale.py,sha256=yXVdclpUqss9h8Nq7N4kg3OHwWGDf
261
261
  dissect/target/plugins/os/windows/notifications.py,sha256=64xHHueHwtJCc8RTAF70oa0RxvqfCu_DBPWRSZBnYZc,17386
262
262
  dissect/target/plugins/os/windows/prefetch.py,sha256=5hRxdIP9sIV5Q9TAScMjLbl_mImZ37abvdE_pAd6rh4,10398
263
263
  dissect/target/plugins/os/windows/recyclebin.py,sha256=4GSj0Q3YvONufnqANbnG0ffiMQyToCiL5s35Wmu4JOQ,4898
264
- dissect/target/plugins/os/windows/registry.py,sha256=IBRqltJ_4fZpVuwMVCAH_nS8JUaNVjsC1jh9AZSNHL4,12788
264
+ dissect/target/plugins/os/windows/registry.py,sha256=EfqUkgbzaqTuq1kIPYNG1TfvJxhJE5X-TEjV3K_xsPU,12814
265
265
  dissect/target/plugins/os/windows/sam.py,sha256=Es_8ROQ6R6-akuTtegCdsJHXzZJNhzgoFuS8y9xNN8E,15267
266
266
  dissect/target/plugins/os/windows/services.py,sha256=_6YkuoZD8LUxk72R3n1p1bOBab3A1wszdB1NuPavIGM,6037
267
267
  dissect/target/plugins/os/windows/sru.py,sha256=sOM7CyMkW8XIXzI75GL69WoqUrSK2X99TFIfdQR2D64,17767
@@ -280,9 +280,9 @@ dissect/target/plugins/os/windows/exchange/__init__.py,sha256=47DEQpj8HBSa-_TImW
280
280
  dissect/target/plugins/os/windows/exchange/exchange.py,sha256=ofoapuDQXefIX4sTzwNboyk5RztN2JEyw1OWl5cx-wo,1564
281
281
  dissect/target/plugins/os/windows/log/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
282
282
  dissect/target/plugins/os/windows/log/amcache.py,sha256=TabtjNx9Ve-u-Fn0K95A0v_SLGzn2YeNPHrcQvjVKJc,5877
283
- dissect/target/plugins/os/windows/log/etl.py,sha256=9skhXdKvgmdKE1f3P9MhxvLprKvIGBv5RhOHq-XK91U,6966
283
+ dissect/target/plugins/os/windows/log/etl.py,sha256=Rau1zqPJ5LL91j59nC4Jg81KF2t1uuMx-oQp9JK0a00,7049
284
284
  dissect/target/plugins/os/windows/log/evt.py,sha256=vK9XHc-hOxf6BbLKMNzGNlbCRWN2nlksQoCLdHqPgnw,7049
285
- dissect/target/plugins/os/windows/log/evtx.py,sha256=Ue-6uX-vMfzmmSN5bQgEXks0E42Yx-zPl3Gy1TCa6Cg,6038
285
+ dissect/target/plugins/os/windows/log/evtx.py,sha256=C1JM64GW7z82qT9K9hIiyCv0EFxszFD9GVvtUZUHdL4,6096
286
286
  dissect/target/plugins/os/windows/log/pfro.py,sha256=BCjg3OZzkIP4-HzRa1b1dPkDv_B4sbd78fl40obUVkM,2706
287
287
  dissect/target/plugins/os/windows/log/schedlgu.py,sha256=vzMOcCSrGRTMNQUZzvyQorZzbTNgs1UJiPe0zeOOupQ,5515
288
288
  dissect/target/plugins/os/windows/regf/7zip.py,sha256=Vc336zhS6R8W98GGlLtPJ_OR0vEP014QnBtYwbx_HUo,3217
@@ -331,10 +331,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
331
331
  dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
332
332
  dissect/target/volumes/md.py,sha256=j1K1iKmspl0C_OJFc7-Q1BMWN2OCC5EVANIgVlJ_fIE,1673
333
333
  dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
334
- dissect.target-3.16.dev29.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
335
- dissect.target-3.16.dev29.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
336
- dissect.target-3.16.dev29.dist-info/METADATA,sha256=qyLj7ZGXe4UjRPqGCfnwa08qYNrNfO8oM64J6KwfC8Y,11107
337
- dissect.target-3.16.dev29.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
338
- dissect.target-3.16.dev29.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
339
- dissect.target-3.16.dev29.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
340
- dissect.target-3.16.dev29.dist-info/RECORD,,
334
+ dissect.target-3.16.dev31.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
335
+ dissect.target-3.16.dev31.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
336
+ dissect.target-3.16.dev31.dist-info/METADATA,sha256=bQJydAA40PRNfKgAuW4LJCissMW3rELgyfBIyapzadU,11107
337
+ dissect.target-3.16.dev31.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
338
+ dissect.target-3.16.dev31.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
339
+ dissect.target-3.16.dev31.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
340
+ dissect.target-3.16.dev31.dist-info/RECORD,,