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.
- dissect/target/plugins/apps/webserver/iis.py +2 -1
- dissect/target/plugins/os/unix/esxi/_os.py +61 -9
- dissect/target/plugins/os/windows/log/etl.py +3 -1
- dissect/target/plugins/os/windows/log/evtx.py +1 -1
- dissect/target/plugins/os/windows/registry.py +3 -1
- {dissect.target-3.16.dev29.dist-info → dissect.target-3.16.dev31.dist-info}/METADATA +1 -1
- {dissect.target-3.16.dev29.dist-info → dissect.target-3.16.dev31.dist-info}/RECORD +12 -12
- {dissect.target-3.16.dev29.dist-info → dissect.target-3.16.dev31.dist-info}/COPYRIGHT +0 -0
- {dissect.target-3.16.dev29.dist-info → dissect.target-3.16.dev31.dist-info}/LICENSE +0 -0
- {dissect.target-3.16.dev29.dist-info → dissect.target-3.16.dev31.dist-info}/WHEEL +0 -0
- {dissect.target-3.16.dev29.dist-info → dissect.target-3.16.dev31.dist-info}/entry_points.txt +0 -0
- {dissect.target-3.16.dev29.dist-info → dissect.target-3.16.dev31.dist-info}/top_level.txt +0 -0
@@ -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
|
-
|
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
|
-
|
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.
|
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=
|
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=
|
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=
|
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=
|
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=
|
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.
|
335
|
-
dissect.target-3.16.
|
336
|
-
dissect.target-3.16.
|
337
|
-
dissect.target-3.16.
|
338
|
-
dissect.target-3.16.
|
339
|
-
dissect.target-3.16.
|
340
|
-
dissect.target-3.16.
|
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,,
|
File without changes
|
File without changes
|
File without changes
|
{dissect.target-3.16.dev29.dist-info → dissect.target-3.16.dev31.dist-info}/entry_points.txt
RENAMED
File without changes
|
File without changes
|