dissect.target 3.16.dev29__py3-none-any.whl → 3.16.dev31__py3-none-any.whl

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