dissect.target 3.20.2.dev11__py3-none-any.whl → 3.20.2.dev12__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- dissect/target/filesystems/dir.py +9 -6
- dissect/target/filesystems/zip.py +4 -1
- dissect/target/loaders/dir.py +13 -3
- dissect/target/loaders/velociraptor.py +35 -15
- {dissect.target-3.20.2.dev11.dist-info → dissect.target-3.20.2.dev12.dist-info}/METADATA +1 -1
- {dissect.target-3.20.2.dev11.dist-info → dissect.target-3.20.2.dev12.dist-info}/RECORD +11 -11
- {dissect.target-3.20.2.dev11.dist-info → dissect.target-3.20.2.dev12.dist-info}/COPYRIGHT +0 -0
- {dissect.target-3.20.2.dev11.dist-info → dissect.target-3.20.2.dev12.dist-info}/LICENSE +0 -0
- {dissect.target-3.20.2.dev11.dist-info → dissect.target-3.20.2.dev12.dist-info}/WHEEL +0 -0
- {dissect.target-3.20.2.dev11.dist-info → dissect.target-3.20.2.dev12.dist-info}/entry_points.txt +0 -0
- {dissect.target-3.20.2.dev11.dist-info → dissect.target-3.20.2.dev12.dist-info}/top_level.txt +0 -0
@@ -27,12 +27,7 @@ class DirectoryFilesystem(Filesystem):
|
|
27
27
|
def _detect(fh: BinaryIO) -> bool:
|
28
28
|
raise TypeError("Detect is not allowed on DirectoryFilesystem class")
|
29
29
|
|
30
|
-
def
|
31
|
-
path = path.strip("/")
|
32
|
-
|
33
|
-
if not path:
|
34
|
-
return DirectoryFilesystemEntry(self, "/", self.base_path)
|
35
|
-
|
30
|
+
def _resolve_path(self, path: str) -> Path:
|
36
31
|
if not self.case_sensitive:
|
37
32
|
searchpath = self.base_path
|
38
33
|
|
@@ -48,6 +43,14 @@ class DirectoryFilesystem(Filesystem):
|
|
48
43
|
else:
|
49
44
|
entry = self.base_path.joinpath(path.strip("/"))
|
50
45
|
|
46
|
+
return entry
|
47
|
+
|
48
|
+
def get(self, path: str) -> FilesystemEntry:
|
49
|
+
if not (path := path.strip("/")):
|
50
|
+
return DirectoryFilesystemEntry(self, "/", self.base_path)
|
51
|
+
|
52
|
+
entry = self._resolve_path(path)
|
53
|
+
|
51
54
|
try:
|
52
55
|
entry.lstat()
|
53
56
|
return DirectoryFilesystemEntry(self, path, entry)
|
@@ -56,7 +56,7 @@ class ZipFilesystem(Filesystem):
|
|
56
56
|
if not mname.startswith(self.base) or mname == ".":
|
57
57
|
continue
|
58
58
|
|
59
|
-
rel_name =
|
59
|
+
rel_name = self._resolve_path(mname)
|
60
60
|
self._fs.map_file_entry(rel_name, ZipFilesystemEntry(self, rel_name, member))
|
61
61
|
|
62
62
|
@staticmethod
|
@@ -64,6 +64,9 @@ class ZipFilesystem(Filesystem):
|
|
64
64
|
"""Detect a zip file on a given file-like object."""
|
65
65
|
return zipfile.is_zipfile(fh)
|
66
66
|
|
67
|
+
def _resolve_path(self, path: str) -> str:
|
68
|
+
return fsutil.normpath(path[len(self.base) :], alt_separator=self.alt_separator)
|
69
|
+
|
67
70
|
def get(self, path: str, relentry: FilesystemEntry = None) -> FilesystemEntry:
|
68
71
|
"""Returns a ZipFilesystemEntry object corresponding to the given path."""
|
69
72
|
return self._fs.get(path, relentry=relentry)
|
dissect/target/loaders/dir.py
CHANGED
@@ -36,13 +36,23 @@ def find_entry_path(path: Path) -> str | None:
|
|
36
36
|
return prefix
|
37
37
|
|
38
38
|
|
39
|
-
def map_dirs(
|
39
|
+
def map_dirs(
|
40
|
+
target: Target,
|
41
|
+
dirs: list[Path | tuple[str, Path]],
|
42
|
+
os_type: str,
|
43
|
+
*,
|
44
|
+
dirfs: type[DirectoryFilesystem] = DirectoryFilesystem,
|
45
|
+
zipfs: type[ZipFilesystem] = ZipFilesystem,
|
46
|
+
**kwargs,
|
47
|
+
) -> None:
|
40
48
|
"""Map directories as filesystems into the given target.
|
41
49
|
|
42
50
|
Args:
|
43
51
|
target: The target to map into.
|
44
52
|
dirs: The directories to map as filesystems. If a list member is a tuple, the first element is the drive letter.
|
45
53
|
os_type: The operating system type, used to determine how the filesystem should be mounted.
|
54
|
+
dirfs: The filesystem class to use for directory filesystems.
|
55
|
+
zipfs: The filesystem class to use for ZIP filesystems.
|
46
56
|
"""
|
47
57
|
alt_separator = ""
|
48
58
|
case_sensitive = True
|
@@ -59,9 +69,9 @@ def map_dirs(target: Target, dirs: list[Path | tuple[str, Path]], os_type: str,
|
|
59
69
|
drive_letter = path.name[0]
|
60
70
|
|
61
71
|
if isinstance(path, zipfile.Path):
|
62
|
-
dfs =
|
72
|
+
dfs = zipfs(path.root.fp, path.at, alt_separator=alt_separator, case_sensitive=case_sensitive)
|
63
73
|
else:
|
64
|
-
dfs =
|
74
|
+
dfs = dirfs(path, alt_separator=alt_separator, case_sensitive=case_sensitive)
|
65
75
|
|
66
76
|
drive_letter_map[drive_letter].append(dfs)
|
67
77
|
|
@@ -4,7 +4,11 @@ import logging
|
|
4
4
|
import zipfile
|
5
5
|
from pathlib import Path
|
6
6
|
from typing import TYPE_CHECKING
|
7
|
+
from urllib.parse import quote, unquote
|
7
8
|
|
9
|
+
from dissect.target.filesystems.dir import DirectoryFilesystem
|
10
|
+
from dissect.target.filesystems.zip import ZipFilesystem
|
11
|
+
from dissect.target.helpers.fsutil import basename, dirname, join
|
8
12
|
from dissect.target.loaders.dir import DirLoader, find_dirs, map_dirs
|
9
13
|
from dissect.target.plugin import OperatingSystem
|
10
14
|
|
@@ -87,11 +91,13 @@ class VelociraptorLoader(DirLoader):
|
|
87
91
|
super().__init__(path)
|
88
92
|
|
89
93
|
if path.suffix == ".zip":
|
90
|
-
log.warning(
|
91
|
-
f"Velociraptor target {path!r} is compressed, which will slightly affect performance. "
|
92
|
-
"Consider uncompressing the archive and passing the uncompressed folder to Dissect."
|
93
|
-
)
|
94
94
|
self.root = zipfile.Path(path.open("rb"))
|
95
|
+
if self.root.root.getinfo("uploads.json").compress_type > 0:
|
96
|
+
log.warning(
|
97
|
+
"Velociraptor target '%s' is compressed, which will slightly affect performance. "
|
98
|
+
"Consider uncompressing the archive and passing the uncompressed folder to Dissect.",
|
99
|
+
path,
|
100
|
+
)
|
95
101
|
else:
|
96
102
|
self.root = path
|
97
103
|
|
@@ -116,14 +122,28 @@ class VelociraptorLoader(DirLoader):
|
|
116
122
|
|
117
123
|
def map(self, target: Target) -> None:
|
118
124
|
os_type, dirs = find_fs_directories(self.root)
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
125
|
+
|
126
|
+
# Velociraptor URL encodes paths before storing these in a collection, this leads plugins not being able to find
|
127
|
+
# these paths. To circumvent this issue, for a zip file the path names are URL decoded before mapping into the
|
128
|
+
# VFS and for a directory the paths are URL encoded at lookup time.
|
129
|
+
map_dirs(
|
130
|
+
target,
|
131
|
+
dirs,
|
132
|
+
os_type,
|
133
|
+
dirfs=VelociraptorDirectoryFilesystem,
|
134
|
+
zipfs=VelociraptorZipFilesystem,
|
135
|
+
)
|
136
|
+
|
137
|
+
|
138
|
+
class VelociraptorDirectoryFilesystem(DirectoryFilesystem):
|
139
|
+
def _resolve_path(self, path: str) -> Path:
|
140
|
+
path = quote(path, safe="$/% ")
|
141
|
+
if (fname := basename(path)).startswith("."):
|
142
|
+
path = join(dirname(path), fname.replace(".", "%2E", 1))
|
143
|
+
|
144
|
+
return super()._resolve_path(path)
|
145
|
+
|
146
|
+
|
147
|
+
class VelociraptorZipFilesystem(ZipFilesystem):
|
148
|
+
def _resolve_path(self, path: str) -> str:
|
149
|
+
return unquote(super()._resolve_path(path))
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: dissect.target
|
3
|
-
Version: 3.20.2.
|
3
|
+
Version: 3.20.2.dev12
|
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
|
@@ -27,7 +27,7 @@ dissect/target/filesystems/btrfs.py,sha256=GE9wWJ1e04UMxVs4Ycw6Q2YWZJoD3sqEKF7Xt
|
|
27
27
|
dissect/target/filesystems/cb.py,sha256=6LcoJiwsYu1Han31IUzVpZVDTifhTLTx_gLfNpB_p6k,5329
|
28
28
|
dissect/target/filesystems/config.py,sha256=VGrzv456rj4tqRzxp1gSGzkHZ447viiLLLcs5NYPYvg,12057
|
29
29
|
dissect/target/filesystems/cpio.py,sha256=ssVCjkAtLn2FqmNxeo6U5boyUdSYFxLWfXpytHYGPqs,641
|
30
|
-
dissect/target/filesystems/dir.py,sha256=
|
30
|
+
dissect/target/filesystems/dir.py,sha256=3GehQbLr8qbH8oSys7BvkeRpBNpogRaa5y04ktZsKqw,4675
|
31
31
|
dissect/target/filesystems/exfat.py,sha256=PRkZPUVN5NlgB1VetFtywdNgF6Yj5OBtF5a25t-fFvw,5917
|
32
32
|
dissect/target/filesystems/extfs.py,sha256=LVdB94lUI2DRHW0xUPx8lwuY-NKVeSwFGZiLOpZ8-Lk,4827
|
33
33
|
dissect/target/filesystems/fat.py,sha256=bqpN4kVSz-0cz3P4QLk1ouJFw1xH1atCynW_ehXJAJE,4824
|
@@ -42,7 +42,7 @@ dissect/target/filesystems/tar.py,sha256=EJyvRCU6H7eu0exC0tQggyAZKZ3JFFaihYyx9SI
|
|
42
42
|
dissect/target/filesystems/vmfs.py,sha256=39FPJiznzSivV5UI2PWo8uD7IKZV7qw-8qIVK5_UcAg,4947
|
43
43
|
dissect/target/filesystems/vmtar.py,sha256=LlKWkTIuLemQmG9yGqL7980uC_AOL77_GWhbJc_grSk,804
|
44
44
|
dissect/target/filesystems/xfs.py,sha256=HsVWbOmq1tn95Q4Jo0QzP2D1A2Cce_bn6WSDkN-GPfc,5051
|
45
|
-
dissect/target/filesystems/zip.py,sha256=
|
45
|
+
dissect/target/filesystems/zip.py,sha256=mBG43kCt6Vo8CmSO9jePBTg83G7RuQKyIqZsq55Udp0,5555
|
46
46
|
dissect/target/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
47
47
|
dissect/target/helpers/cache.py,sha256=TXlJBdFRz6V9zKs903am4Yawr0maYw5kZY0RqklDQJM,8568
|
48
48
|
dissect/target/helpers/config.py,sha256=RMHnIuKJHINHiLrvKN3EyA0jFA1o6-pbeaycG8Pgrp8,2596
|
@@ -79,7 +79,7 @@ dissect/target/loaders/ad1.py,sha256=1_VmPZckDzXVvNF-HNtoUZqabnhCKBLUD3vVaitHQ00
|
|
79
79
|
dissect/target/loaders/asdf.py,sha256=dvPPDBrnz2JPXpCbqsu-NgQWIdVGMOit2KAdhIO1iiQ,972
|
80
80
|
dissect/target/loaders/cb.py,sha256=EGhdytBKBdofTd89juavDZZbmupEZmMBadeUXvVIK20,6612
|
81
81
|
dissect/target/loaders/cyber.py,sha256=Ip2hI7L98ZP7gUZuHQr0GxBdmbTzD-PntXmLJ5KpBuQ,1533
|
82
|
-
dissect/target/loaders/dir.py,sha256=
|
82
|
+
dissect/target/loaders/dir.py,sha256=0qzlSnblcacNtugN07NJ4DS-8miW0SkDCTDj4W2sMHs,6037
|
83
83
|
dissect/target/loaders/hyperv.py,sha256=_IOUJEO0BXaCBZ6sjIX0DZTkG9UNW5Vs9VcNHYv073w,5928
|
84
84
|
dissect/target/loaders/itunes.py,sha256=k0LaSWr0AVLX7tBCapWQA9uKxTKk_LQskQEAbhH3jeU,13176
|
85
85
|
dissect/target/loaders/kape.py,sha256=t5TfrGLqPeIpUUpXzIl6aHsqXMEGDqJ5YwDCs07DiBA,1237
|
@@ -106,7 +106,7 @@ dissect/target/loaders/target.py,sha256=MU_HUtg58YdhdZu6ga1sYG7fK61Dn7N0TBkWXDCW
|
|
106
106
|
dissect/target/loaders/utm.py,sha256=7oHYP_jmr5gcjoyOP1pnh9Rz-IqQirBI6bjSvGwiKao,1053
|
107
107
|
dissect/target/loaders/vb.py,sha256=CdimOMeoJEDq8xYDgtldGSiwhR-dY5uxac1L0sYwAEU,2078
|
108
108
|
dissect/target/loaders/vbox.py,sha256=8JD7D8iAY9JRvTHsrosp5ZMsZezuLhZ10Zt8sEL7KBI,732
|
109
|
-
dissect/target/loaders/velociraptor.py,sha256=
|
109
|
+
dissect/target/loaders/velociraptor.py,sha256=5CLfq63PkhDL-WB6sZQEJAIL-f5vIi2xCp0CnFJA8Jw,5826
|
110
110
|
dissect/target/loaders/vma.py,sha256=tF3B4TdRWHJ8gklQliSRn1bMYx0uozTFkmn_QHS-Dqc,641
|
111
111
|
dissect/target/loaders/vmwarevm.py,sha256=1MlKoIuWSwpYmpuLxDuVacvaYHUhAGO1KgZxzrc4fyg,428
|
112
112
|
dissect/target/loaders/vmx.py,sha256=o1rYYKu6ReleqqHf2aeRcNrmoRcngWZNhz1h7GlmggQ,962
|
@@ -383,10 +383,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
|
|
383
383
|
dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
|
384
384
|
dissect/target/volumes/md.py,sha256=7ShPtusuLGaIv27SvEETtgsuoQyAa4iAAeOR1NEaajI,1689
|
385
385
|
dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
|
386
|
-
dissect.target-3.20.2.
|
387
|
-
dissect.target-3.20.2.
|
388
|
-
dissect.target-3.20.2.
|
389
|
-
dissect.target-3.20.2.
|
390
|
-
dissect.target-3.20.2.
|
391
|
-
dissect.target-3.20.2.
|
392
|
-
dissect.target-3.20.2.
|
386
|
+
dissect.target-3.20.2.dev12.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
|
387
|
+
dissect.target-3.20.2.dev12.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
388
|
+
dissect.target-3.20.2.dev12.dist-info/METADATA,sha256=au0kJQvTe9SWFe37c1WTFl7D7EqigPuUR1X7vtXQLK4,13184
|
389
|
+
dissect.target-3.20.2.dev12.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
390
|
+
dissect.target-3.20.2.dev12.dist-info/entry_points.txt,sha256=yQwLCWUuzHgS6-sfCcRk66gAfoCfqXdCjqKjvhnQW8o,537
|
391
|
+
dissect.target-3.20.2.dev12.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
|
392
|
+
dissect.target-3.20.2.dev12.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
{dissect.target-3.20.2.dev11.dist-info → dissect.target-3.20.2.dev12.dist-info}/entry_points.txt
RENAMED
File without changes
|
{dissect.target-3.20.2.dev11.dist-info → dissect.target-3.20.2.dev12.dist-info}/top_level.txt
RENAMED
File without changes
|