dissect.target 3.16.dev36__py3-none-any.whl → 3.16.dev38__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- dissect/target/helpers/fsutil.py +1 -0
- dissect/target/loaders/velociraptor.py +14 -6
- dissect/target/plugins/apps/webserver/iis.py +35 -8
- {dissect.target-3.16.dev36.dist-info → dissect.target-3.16.dev38.dist-info}/METADATA +1 -1
- {dissect.target-3.16.dev36.dist-info → dissect.target-3.16.dev38.dist-info}/RECORD +10 -10
- {dissect.target-3.16.dev36.dist-info → dissect.target-3.16.dev38.dist-info}/COPYRIGHT +0 -0
- {dissect.target-3.16.dev36.dist-info → dissect.target-3.16.dev38.dist-info}/LICENSE +0 -0
- {dissect.target-3.16.dev36.dist-info → dissect.target-3.16.dev38.dist-info}/WHEEL +0 -0
- {dissect.target-3.16.dev36.dist-info → dissect.target-3.16.dev38.dist-info}/entry_points.txt +0 -0
- {dissect.target-3.16.dev36.dist-info → dissect.target-3.16.dev38.dist-info}/top_level.txt +0 -0
dissect/target/helpers/fsutil.py
CHANGED
@@ -19,12 +19,6 @@ WINDOWS_ACCESSORS = ["mft", "ntfs", "lazy_ntfs", "ntfs_vss", "auto"]
|
|
19
19
|
|
20
20
|
|
21
21
|
def find_fs_directories(path: Path) -> tuple[Optional[OperatingSystem], Optional[list[Path]]]:
|
22
|
-
# As of Velociraptor version 0.7.0 the structure of the Velociraptor Offline Collector varies by operating system.
|
23
|
-
# Generic.Collectors.File (Unix) uses the accessors file and auto.
|
24
|
-
# Generic.Collectors.File (Windows) and Windows.KapeFiles.Targets (Windows) uses the accessors
|
25
|
-
# mft, ntfs, lazy_ntfs, ntfs_vss and auto. The loader only supports a collection where a single accessor is used.
|
26
|
-
# For Windows usage of the ntfs_vss accessor can be forced by configuring VSSAnalysisAge to be greater than 0.
|
27
|
-
|
28
22
|
fs_root = path.joinpath(FILESYSTEMS_ROOT)
|
29
23
|
|
30
24
|
# Unix
|
@@ -43,6 +37,9 @@ def find_fs_directories(path: Path) -> tuple[Optional[OperatingSystem], Optional
|
|
43
37
|
if accessor_root.exists():
|
44
38
|
# If the accessor directory exists, assume all the subdirectories are volumes
|
45
39
|
for volume in accessor_root.iterdir():
|
40
|
+
if not volume.is_dir():
|
41
|
+
continue
|
42
|
+
|
46
43
|
# https://github.com/Velocidex/velociraptor/blob/87368e7cc678144592a1614bb3bbd0a0f900ded9/accessors/ntfs/vss.go#L82
|
47
44
|
if "HarddiskVolumeShadowCopy" in volume.name:
|
48
45
|
vss_volumes.add(volume)
|
@@ -60,6 +57,17 @@ def find_fs_directories(path: Path) -> tuple[Optional[OperatingSystem], Optional
|
|
60
57
|
class VelociraptorLoader(DirLoader):
|
61
58
|
"""Load Rapid7 Velociraptor forensic image files.
|
62
59
|
|
60
|
+
As of Velociraptor version 0.7.0 the structure of the Velociraptor Offline Collector varies by operating system.
|
61
|
+
Generic.Collectors.File (Unix) uses the accessors file and auto. The loader supports the following configuration::
|
62
|
+
|
63
|
+
{"Generic.Collectors.File":{"Root":"/","collectionSpec":"Glob\\netc/**\\nvar/log/**"}}
|
64
|
+
|
65
|
+
Generic.Collectors.File (Windows) and Windows.KapeFiles.Targets (Windows) uses the accessors mft, ntfs, lazy_ntfs,
|
66
|
+
ntfs_vss and auto. The loader only supports a collection where a single accessor is used, which can be forced by
|
67
|
+
using the following configuration::
|
68
|
+
|
69
|
+
{"Windows.KapeFiles.Targets":{"VSSAnalysisAge":"1000","_SANS_Triage":"Y"}}
|
70
|
+
|
63
71
|
References:
|
64
72
|
- https://www.rapid7.com/products/velociraptor/
|
65
73
|
- https://docs.velociraptor.app/
|
@@ -10,6 +10,7 @@ from flow.record.base import RE_VALID_FIELD_NAME
|
|
10
10
|
from dissect.target import plugin
|
11
11
|
from dissect.target.exceptions import FileNotFoundError as DissectFileNotFoundError
|
12
12
|
from dissect.target.exceptions import PluginError, UnsupportedPluginError
|
13
|
+
from dissect.target.helpers.fsutil import has_glob_magic
|
13
14
|
from dissect.target.helpers.record import TargetRecordDescriptor
|
14
15
|
from dissect.target.plugins.apps.webserver.webserver import (
|
15
16
|
WebserverAccessLogRecord,
|
@@ -54,24 +55,33 @@ class IISLogsPlugin(WebserverPlugin):
|
|
54
55
|
|
55
56
|
APPLICATION_HOST_CONFIG = "sysvol/windows/system32/inetsrv/config/applicationHost.config"
|
56
57
|
|
58
|
+
DEFAULT_LOG_PATHS = [
|
59
|
+
"sysvol\\Windows\\System32\\LogFiles\\W3SVC*\\*.log",
|
60
|
+
"sysvol\\Windows.old\\Windows\\System32\\LogFiles\\W3SVC*\\*.log",
|
61
|
+
"sysvol\\inetpub\\logs\\LogFiles\\*.log",
|
62
|
+
"sysvol\\inetpub\\logs\\LogFiles\\W3SVC*\\*.log",
|
63
|
+
"sysvol\\Resources\\Directory\\*\\LogFiles\\Web\\W3SVC*\\*.log",
|
64
|
+
]
|
65
|
+
|
57
66
|
__namespace__ = "iis"
|
58
67
|
|
59
68
|
def __init__(self, target):
|
60
69
|
super().__init__(target)
|
61
70
|
self.config = self.target.fs.path(self.APPLICATION_HOST_CONFIG)
|
71
|
+
self.log_dirs = self.get_log_dirs()
|
62
72
|
|
63
73
|
self._create_extended_descriptor = lru_cache(4096)(self._create_extended_descriptor)
|
64
74
|
|
65
75
|
def check_compatible(self) -> None:
|
66
|
-
if not self.
|
67
|
-
raise UnsupportedPluginError("No
|
76
|
+
if not self.log_dirs:
|
77
|
+
raise UnsupportedPluginError("No IIS log files found")
|
68
78
|
|
69
79
|
@plugin.internal
|
70
80
|
def get_log_dirs(self) -> list[tuple[str, Path]]:
|
71
|
-
log_paths =
|
81
|
+
log_paths = set()
|
72
82
|
|
73
83
|
if (sysvol_files := self.target.fs.path("sysvol/files")).exists():
|
74
|
-
log_paths.
|
84
|
+
log_paths.add(("auto", sysvol_files))
|
75
85
|
|
76
86
|
try:
|
77
87
|
xml_data = ElementTree.fromstring(self.config.open().read(), forbid_dtd=True)
|
@@ -79,16 +89,33 @@ class IISLogsPlugin(WebserverPlugin):
|
|
79
89
|
log_format = log_file_element.get("logFormat") or "W3C"
|
80
90
|
if log_dir := log_file_element.get("directory"):
|
81
91
|
log_dir = self.target.resolve(log_dir)
|
82
|
-
log_paths.
|
92
|
+
log_paths.add((log_format, log_dir))
|
83
93
|
|
84
94
|
except (ElementTree.ParseError, DissectFileNotFoundError) as e:
|
85
|
-
self.target.log.warning(
|
95
|
+
self.target.log.warning("Error while parsing %s:%s", self.config, e)
|
96
|
+
|
97
|
+
for log_path in self.DEFAULT_LOG_PATHS:
|
98
|
+
try:
|
99
|
+
# later on we use */*.log to collect the files, so we need to move up 2 levels
|
100
|
+
log_dir = self.target.fs.path(log_path).parents[1]
|
101
|
+
except IndexError:
|
102
|
+
self.target.log.error("Incompatible path found: %s", log_path)
|
103
|
+
continue
|
104
|
+
|
105
|
+
if not has_glob_magic(str(log_dir)) and log_dir.exists():
|
106
|
+
log_paths.add(("auto", log_dir))
|
107
|
+
continue
|
108
|
+
|
109
|
+
for _log_dir_str in self.target.fs.glob(str(log_dir)):
|
110
|
+
if not (_log_dir := self.target.fs.path(_log_dir_str)).is_dir():
|
111
|
+
continue
|
112
|
+
log_paths.add(("auto", _log_dir))
|
86
113
|
|
87
|
-
return log_paths
|
114
|
+
return list(log_paths)
|
88
115
|
|
89
116
|
@plugin.internal
|
90
117
|
def iter_log_format_path_pairs(self) -> list[tuple[str, str]]:
|
91
|
-
for log_format, log_dir_path in self.
|
118
|
+
for log_format, log_dir_path in self.log_dirs:
|
92
119
|
for log_file in log_dir_path.glob("*/*.log"):
|
93
120
|
yield (log_format, log_file)
|
94
121
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: dissect.target
|
3
|
-
Version: 3.16.
|
3
|
+
Version: 3.16.dev38
|
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
|
@@ -48,7 +48,7 @@ dissect/target/helpers/configutil.py,sha256=t_UNvcWuMMT5C1tut_PgTwCnVUodf6RjhfXP
|
|
48
48
|
dissect/target/helpers/cyber.py,sha256=Ki5oSU0GgQxjgC_yWoeieGP7GOY5blQCzNX7vy7Pgas,16782
|
49
49
|
dissect/target/helpers/descriptor_extensions.py,sha256=uT8GwznfDAiIgMM7JKKOY0PXKMv2c0GCqJTCkWFgops,2605
|
50
50
|
dissect/target/helpers/docs.py,sha256=J5U65Y3yOTqxDEZRCdrEmO63XQCeDzOJea1PwPM6Cyc,5146
|
51
|
-
dissect/target/helpers/fsutil.py,sha256=
|
51
|
+
dissect/target/helpers/fsutil.py,sha256=Djm7r7gbxMlm7QQagWNeoHd-KoCn3u3JMMRc4TH950Q,19781
|
52
52
|
dissect/target/helpers/hashutil.py,sha256=SD24rcV_y0sBEl7M9T-isjm-VzJvCiTN2BoWMqAOAVI,2160
|
53
53
|
dissect/target/helpers/keychain.py,sha256=wYH0sf7eaxP0bZTo80RF_BQMWulCWmIQ8Tzt9K5TSNQ,3611
|
54
54
|
dissect/target/helpers/lazy.py,sha256=823VtmdWsbJyVZvNWopDhQdqq2i1xtj6b8IKfveboKw,1771
|
@@ -102,7 +102,7 @@ dissect/target/loaders/targetd.py,sha256=sfbn2_j3il2G-rPywAoNT5YPtD5KmKkmBv1zrPD
|
|
102
102
|
dissect/target/loaders/utm.py,sha256=e5x5ZI3HeL0STh4S-CaQb68Rnug4SVZR9zlmHaGFj0M,978
|
103
103
|
dissect/target/loaders/vb.py,sha256=CnQcn7bAkMzIB1y-lWLtPPXdIVsyeDaT6hTZEurjkV4,2072
|
104
104
|
dissect/target/loaders/vbox.py,sha256=8JD7D8iAY9JRvTHsrosp5ZMsZezuLhZ10Zt8sEL7KBI,732
|
105
|
-
dissect/target/loaders/velociraptor.py,sha256=
|
105
|
+
dissect/target/loaders/velociraptor.py,sha256=WPnDIWANIIUPgc-kfXSjXptCQ2pkcy1jdkEydiOvs58,4613
|
106
106
|
dissect/target/loaders/vma.py,sha256=AAY5-s-nz6wgvmcFkptJD7nNXhpkdf6SqEKVOrJaIKs,644
|
107
107
|
dissect/target/loaders/vmwarevm.py,sha256=1MlKoIuWSwpYmpuLxDuVacvaYHUhAGO1KgZxzrc4fyg,428
|
108
108
|
dissect/target/loaders/vmx.py,sha256=o1rYYKu6ReleqqHf2aeRcNrmoRcngWZNhz1h7GlmggQ,962
|
@@ -144,7 +144,7 @@ dissect/target/plugins/apps/webserver/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCe
|
|
144
144
|
dissect/target/plugins/apps/webserver/apache.py,sha256=bD6_XObfO7W-cFlLRWyhdwEfw-Y57JBi47rWnXCx-vg,15026
|
145
145
|
dissect/target/plugins/apps/webserver/caddy.py,sha256=qZsAK_tILGvroV4SWkDKc-Otwd41bUEtv9H9TuHmt-0,6422
|
146
146
|
dissect/target/plugins/apps/webserver/citrix.py,sha256=FEPdBteEJeeGg3B95W_27O9wLJVhenEc5A5fSLDmK18,3044
|
147
|
-
dissect/target/plugins/apps/webserver/iis.py,sha256=
|
147
|
+
dissect/target/plugins/apps/webserver/iis.py,sha256=fnVF6npYXbVfg9SYvFOFMM1c7dT81mKS6cMerRDhuy4,15847
|
148
148
|
dissect/target/plugins/apps/webserver/nginx.py,sha256=WA5soi1FU1c44oHRcyOoHK3gH8Jzc_Qi5uXcimDYukw,4129
|
149
149
|
dissect/target/plugins/apps/webserver/webserver.py,sha256=a7a2lLrhsa9c1AXnwiLP-tqVv-IUbmaVaSZI5S0fKa8,1500
|
150
150
|
dissect/target/plugins/child/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -332,10 +332,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
|
|
332
332
|
dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
|
333
333
|
dissect/target/volumes/md.py,sha256=j1K1iKmspl0C_OJFc7-Q1BMWN2OCC5EVANIgVlJ_fIE,1673
|
334
334
|
dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
|
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.
|
341
|
-
dissect.target-3.16.
|
335
|
+
dissect.target-3.16.dev38.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
|
336
|
+
dissect.target-3.16.dev38.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
337
|
+
dissect.target-3.16.dev38.dist-info/METADATA,sha256=LCsm2qVyfCBMvuEx5O0DbD_J-OhYuilVWMT_N2YRS7s,11107
|
338
|
+
dissect.target-3.16.dev38.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
339
|
+
dissect.target-3.16.dev38.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
|
340
|
+
dissect.target-3.16.dev38.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
|
341
|
+
dissect.target-3.16.dev38.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
{dissect.target-3.16.dev36.dist-info → dissect.target-3.16.dev38.dist-info}/entry_points.txt
RENAMED
File without changes
|
File without changes
|