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.
@@ -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 get(self, path: str) -> FilesystemEntry:
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 = fsutil.normpath(mname[len(self.base) :], alt_separator=self.alt_separator)
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)
@@ -36,13 +36,23 @@ def find_entry_path(path: Path) -> str | None:
36
36
  return prefix
37
37
 
38
38
 
39
- def map_dirs(target: Target, dirs: list[Path | tuple[str, Path]], os_type: str, **kwargs) -> None:
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 = ZipFilesystem(path.root.fp, path.at, alt_separator=alt_separator, case_sensitive=case_sensitive)
72
+ dfs = zipfs(path.root.fp, path.at, alt_separator=alt_separator, case_sensitive=case_sensitive)
63
73
  else:
64
- dfs = DirectoryFilesystem(path, alt_separator=alt_separator, case_sensitive=case_sensitive)
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
- if os_type == OperatingSystem.WINDOWS:
120
- # Velociraptor doesn't have the correct filenames for the paths "$J" and "$Secure:$SDS"
121
- map_dirs(
122
- target,
123
- dirs,
124
- os_type,
125
- usnjrnl_path="$Extend/$UsnJrnl%3A$J",
126
- sds_path="$Secure%3A$SDS",
127
- )
128
- else:
129
- map_dirs(target, dirs, os_type)
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.dev11
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=rKEreX3A7CI6a3pMssrO9F-9i5pkxCn_Ucs_dMtHxxA,4574
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=BeNj23DOYfWuTm5V1V419ViJiMfBrO1VA5gP6rljwXs,5467
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=F-PgvBw82XmL0rdKyBxznUkDc5Oct6-_Y9xM4fhvA6I,5791
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=auMdtLguOxr2Bsx4R0vVr0pHpn2xCwgBy3Rx35k51C8,4932
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.dev11.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
387
- dissect.target-3.20.2.dev11.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
388
- dissect.target-3.20.2.dev11.dist-info/METADATA,sha256=w_k50dxPfplJclpnnGInsJcOX38D4aENqBQpa41Nbe8,13184
389
- dissect.target-3.20.2.dev11.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
390
- dissect.target-3.20.2.dev11.dist-info/entry_points.txt,sha256=yQwLCWUuzHgS6-sfCcRk66gAfoCfqXdCjqKjvhnQW8o,537
391
- dissect.target-3.20.2.dev11.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
392
- dissect.target-3.20.2.dev11.dist-info/RECORD,,
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,,