dissect.target 3.15.dev2__py3-none-any.whl → 3.15.dev4__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/plugin.py +66 -39
- {dissect.target-3.15.dev2.dist-info → dissect.target-3.15.dev4.dist-info}/METADATA +1 -1
- {dissect.target-3.15.dev2.dist-info → dissect.target-3.15.dev4.dist-info}/RECORD +8 -8
- {dissect.target-3.15.dev2.dist-info → dissect.target-3.15.dev4.dist-info}/COPYRIGHT +0 -0
- {dissect.target-3.15.dev2.dist-info → dissect.target-3.15.dev4.dist-info}/LICENSE +0 -0
- {dissect.target-3.15.dev2.dist-info → dissect.target-3.15.dev4.dist-info}/WHEEL +0 -0
- {dissect.target-3.15.dev2.dist-info → dissect.target-3.15.dev4.dist-info}/entry_points.txt +0 -0
- {dissect.target-3.15.dev2.dist-info → dissect.target-3.15.dev4.dist-info}/top_level.txt +0 -0
dissect/target/plugin.py
CHANGED
@@ -292,18 +292,43 @@ class OSPlugin(Plugin):
|
|
292
292
|
This provides a base class for certain common functions of OS's, which each OS plugin has to implement separately.
|
293
293
|
|
294
294
|
For example, it provides an interface for retrieving the hostname and users of a target.
|
295
|
+
|
296
|
+
All derived classes MUST implement ALL the classmethods and exported
|
297
|
+
methods with the same ``@classmethod`` or ``@export(...)`` annotation.
|
295
298
|
"""
|
296
299
|
|
300
|
+
def __init_subclass__(cls, **kwargs):
|
301
|
+
# Note that cls is the subclass
|
302
|
+
super().__init_subclass__(**kwargs)
|
303
|
+
|
304
|
+
for os_method in get_nonprivate_attributes(OSPlugin):
|
305
|
+
if isinstance(os_method, property):
|
306
|
+
os_method = os_method.fget
|
307
|
+
os_docstring = os_method.__doc__
|
308
|
+
|
309
|
+
method = getattr(cls, os_method.__name__, None)
|
310
|
+
if isinstance(method, property):
|
311
|
+
method = method.fget
|
312
|
+
# This works as None has a __doc__ property (which is None).
|
313
|
+
docstring = method.__doc__
|
314
|
+
|
315
|
+
if method and not docstring:
|
316
|
+
if hasattr(method, "__func__"):
|
317
|
+
method = method.__func__
|
318
|
+
method.__doc__ = os_docstring
|
319
|
+
|
297
320
|
def check_compatible(self) -> bool:
|
298
|
-
"""OSPlugin's use a different compatibility check, override the
|
321
|
+
"""OSPlugin's use a different compatibility check, override the one from the :class:`Plugin` class.
|
322
|
+
|
323
|
+
Returns:
|
324
|
+
This function always returns ``True``.
|
325
|
+
"""
|
299
326
|
return True
|
300
327
|
|
301
328
|
@classmethod
|
302
329
|
def detect(cls, fs: Filesystem) -> Optional[Filesystem]:
|
303
330
|
"""Provide detection of this OSPlugin on a given filesystem.
|
304
331
|
|
305
|
-
Note: must be implemented as a classmethod.
|
306
|
-
|
307
332
|
Args:
|
308
333
|
fs: :class:`~dissect.target.filesystem.Filesystem` to detect the OS on.
|
309
334
|
|
@@ -316,11 +341,9 @@ class OSPlugin(Plugin):
|
|
316
341
|
def create(cls, target: Target, sysvol: Filesystem) -> OSPlugin:
|
317
342
|
"""Initiate this OSPlugin with the given target and detected filesystem.
|
318
343
|
|
319
|
-
Note: must be implemented as a classmethod.
|
320
|
-
|
321
344
|
Args:
|
322
|
-
target: The Target object.
|
323
|
-
sysvol: The filesystem that was detected in the detect() function.
|
345
|
+
target: The :class:`~dissect.target.target.Target` object.
|
346
|
+
sysvol: The filesystem that was detected in the ``detect()`` function.
|
324
347
|
|
325
348
|
Returns:
|
326
349
|
An instantiated version of the OSPlugin.
|
@@ -329,9 +352,7 @@ class OSPlugin(Plugin):
|
|
329
352
|
|
330
353
|
@export(property=True)
|
331
354
|
def hostname(self) -> Optional[str]:
|
332
|
-
"""
|
333
|
-
|
334
|
-
Implementations must be decorated with ``@export(property=True)``.
|
355
|
+
"""Return the target's hostname.
|
335
356
|
|
336
357
|
Returns:
|
337
358
|
The hostname as string.
|
@@ -340,9 +361,7 @@ class OSPlugin(Plugin):
|
|
340
361
|
|
341
362
|
@export(property=True)
|
342
363
|
def ips(self) -> list[str]:
|
343
|
-
"""
|
344
|
-
|
345
|
-
Implementations must be decorated with ``@export(property=True)``.
|
364
|
+
"""Return the IP addresses configured in the target.
|
346
365
|
|
347
366
|
Returns:
|
348
367
|
The IPs as list.
|
@@ -351,9 +370,7 @@ class OSPlugin(Plugin):
|
|
351
370
|
|
352
371
|
@export(property=True)
|
353
372
|
def version(self) -> Optional[str]:
|
354
|
-
"""
|
355
|
-
|
356
|
-
Implementations must be decorated with ``@export(property=True)``.
|
373
|
+
"""Return the target's OS version.
|
357
374
|
|
358
375
|
Returns:
|
359
376
|
The OS version as string.
|
@@ -362,9 +379,7 @@ class OSPlugin(Plugin):
|
|
362
379
|
|
363
380
|
@export(record=EmptyRecord)
|
364
381
|
def users(self) -> list[Record]:
|
365
|
-
"""
|
366
|
-
|
367
|
-
Implementations must be decorated with @export.
|
382
|
+
"""Return the users available in the target.
|
368
383
|
|
369
384
|
Returns:
|
370
385
|
A list of user records.
|
@@ -373,9 +388,7 @@ class OSPlugin(Plugin):
|
|
373
388
|
|
374
389
|
@export(property=True)
|
375
390
|
def os(self) -> str:
|
376
|
-
"""
|
377
|
-
|
378
|
-
Implementations must be decorated with ``@export(property=True)``.
|
391
|
+
"""Return a slug of the target's OS name.
|
379
392
|
|
380
393
|
Returns:
|
381
394
|
A slug of the OS name, e.g. 'windows' or 'linux'.
|
@@ -384,9 +397,7 @@ class OSPlugin(Plugin):
|
|
384
397
|
|
385
398
|
@export(property=True)
|
386
399
|
def architecture(self) -> Optional[str]:
|
387
|
-
"""
|
388
|
-
|
389
|
-
Implementations must be decorated with ``@export(property=True)``.
|
400
|
+
"""Return a slug of the target's OS architecture.
|
390
401
|
|
391
402
|
Returns:
|
392
403
|
A slug of the OS architecture, e.g. 'x86_32-unix', 'MIPS-linux' or
|
@@ -1128,29 +1139,45 @@ def find_plugin_functions(
|
|
1128
1139
|
ignore_load_errors = kwargs.get("ignore_load_errors", False)
|
1129
1140
|
|
1130
1141
|
for pattern in patterns.split(","):
|
1131
|
-
#
|
1142
|
+
# Backward compatibility fix for namespace-level plugins (i.e. chrome)
|
1143
|
+
# If an exact namespace match is found, the pattern is changed to the tree to that namespace.
|
1144
|
+
# Examples:
|
1145
|
+
# -f browser -> apps.browser.browser
|
1146
|
+
# -f iexplore -> apps.browser.iexplore
|
1147
|
+
namespace_match = False
|
1132
1148
|
for index_name, func in functions.items():
|
1133
1149
|
if func["namespace"] == pattern:
|
1134
|
-
pattern = func["module"]
|
1150
|
+
pattern = func["module"]
|
1151
|
+
namespace_match = True
|
1152
|
+
break
|
1135
1153
|
|
1136
1154
|
wildcard = any(char in pattern for char in ["*", "!", "?", "[", "]"])
|
1137
1155
|
treematch = pattern.split(".")[0] in rootset and pattern != "os"
|
1138
1156
|
exact_match = pattern in functions
|
1139
1157
|
|
1140
|
-
# Allow for exact matches
|
1141
|
-
#
|
1142
|
-
#
|
1143
|
-
#
|
1144
|
-
#
|
1145
|
-
|
1158
|
+
# Allow for exact and namespace matches even if the plugin does not want to be found, otherwise you cannot
|
1159
|
+
# reach documented namespace plugins like apps.browser.browser.downloads.
|
1160
|
+
# You can *always* run these using the namespace/classic-style like: browser.downloads (but -l lists them
|
1161
|
+
# in the tree for documentation purposes so it would be misleading not to allow tree access as well).
|
1162
|
+
#
|
1163
|
+
# Note that these tree items will never respond to wildcards though to avoid duplicate results, e.g. when
|
1164
|
+
# querying apps.browser.*, this also means apps.browser.browser.* won't work.
|
1165
|
+
if exact_match or namespace_match:
|
1146
1166
|
show_hidden = True
|
1147
1167
|
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1168
|
+
# Change the treematch pattern into an fnmatch-able pattern to give back all functions from the sub-tree
|
1169
|
+
# (if there is a subtree).
|
1170
|
+
#
|
1171
|
+
# Examples:
|
1172
|
+
# -f browser -> apps.browser.browser* (the whole package, due to a namespace match)
|
1173
|
+
# -f apps.webservers.iis -> apps.webservers.iis* (logs etc)
|
1174
|
+
# -f apps.webservers.iis.logs -> apps.webservers.iis.logs* (only the logs, there is no subtree)
|
1175
|
+
# We do not include a dot because that does not work if the full path is given:
|
1176
|
+
# -f apps.webservers.iis.logs != apps.webservers.iis.logs.* (does not work)
|
1177
|
+
#
|
1178
|
+
# In practice a namespace_match would almost always also be a treematch, except when the namespace plugin
|
1179
|
+
# is in the root of the plugin tree.
|
1180
|
+
if (treematch or namespace_match) and not wildcard and not exact_match:
|
1154
1181
|
pattern += "*"
|
1155
1182
|
|
1156
1183
|
if wildcard or treematch:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: dissect.target
|
3
|
-
Version: 3.15.
|
3
|
+
Version: 3.15.dev4
|
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
|
@@ -3,7 +3,7 @@ dissect/target/container.py,sha256=9ixufT1_0WhraqttBWwQjG80caToJqvCX8VjFk8d5F0,9
|
|
3
3
|
dissect/target/exceptions.py,sha256=VVW_Rq_vQinapz-2mbJ3UkxBEZpb2pE_7JlhMukdtrY,2877
|
4
4
|
dissect/target/filesystem.py,sha256=oCPNw09I3odf69HKkqph6EM5-AywAQIn9UPO-BxtbpY,53445
|
5
5
|
dissect/target/loader.py,sha256=4ZdX-QJY83NPswTyNG31LUwYXdV1tuByrR2vKKg7d5k,7214
|
6
|
-
dissect/target/plugin.py,sha256=
|
6
|
+
dissect/target/plugin.py,sha256=MyBjC7uJ-qml9SQMQ6xsNMdudsOFNJiHNMRn-AFi_pM,47405
|
7
7
|
dissect/target/report.py,sha256=06uiP4MbNI8cWMVrC1SasNS-Yg6ptjVjckwj8Yhe0Js,7958
|
8
8
|
dissect/target/target.py,sha256=CuqLTD3fwr4HIxtDgN_fwJ3UHSqe5PhNJlLTVGsluB8,31908
|
9
9
|
dissect/target/volume.py,sha256=aQZAJiny8jjwkc9UtwIRwy7nINXjCxwpO-_UDfh6-BA,15801
|
@@ -305,10 +305,10 @@ dissect/target/volumes/luks.py,sha256=v_mHW05KM5iG8JDe47i2V4Q9O0r4rnAMA9m_qc9cYw
|
|
305
305
|
dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
|
306
306
|
dissect/target/volumes/md.py,sha256=j1K1iKmspl0C_OJFc7-Q1BMWN2OCC5EVANIgVlJ_fIE,1673
|
307
307
|
dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
|
308
|
-
dissect.target-3.15.
|
309
|
-
dissect.target-3.15.
|
310
|
-
dissect.target-3.15.
|
311
|
-
dissect.target-3.15.
|
312
|
-
dissect.target-3.15.
|
313
|
-
dissect.target-3.15.
|
314
|
-
dissect.target-3.15.
|
308
|
+
dissect.target-3.15.dev4.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
|
309
|
+
dissect.target-3.15.dev4.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
310
|
+
dissect.target-3.15.dev4.dist-info/METADATA,sha256=ZHcCCAily7wTHdfI01lHfl1RXkpa00HXb_oUyZUtO3M,11106
|
311
|
+
dissect.target-3.15.dev4.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
312
|
+
dissect.target-3.15.dev4.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
|
313
|
+
dissect.target-3.15.dev4.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
|
314
|
+
dissect.target-3.15.dev4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|