dissect.target 3.16.dev30__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.
@@ -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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.16.dev30
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
@@ -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
@@ -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.dev30.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
335
- dissect.target-3.16.dev30.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
336
- dissect.target-3.16.dev30.dist-info/METADATA,sha256=oFKQeKw2Ch3n9X2N0AtdhaXzpVbvqrAp3jvpOf4ppaU,11107
337
- dissect.target-3.16.dev30.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
338
- dissect.target-3.16.dev30.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
339
- dissect.target-3.16.dev30.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
340
- dissect.target-3.16.dev30.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,,