dissect.target 3.20.2.dev11__py3-none-any.whl → 3.20.2.dev13__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.
@@ -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))
@@ -8,6 +8,7 @@ from dissect.target.plugins.os.unix._os import UnixPlugin
8
8
  from dissect.target.plugins.os.unix.bsd.osx._os import MacPlugin
9
9
  from dissect.target.plugins.os.unix.linux.network_managers import (
10
10
  LinuxNetworkManager,
11
+ parse_unix_dhcp_leases,
11
12
  parse_unix_dhcp_log_messages,
12
13
  )
13
14
  from dissect.target.plugins.os.windows._os import WindowsPlugin
@@ -39,8 +40,11 @@ class LinuxPlugin(UnixPlugin, LinuxNetworkManager):
39
40
  for ip_set in self.network_manager.get_config_value("ips"):
40
41
  ips.update(ip_set)
41
42
 
42
- for ip in parse_unix_dhcp_log_messages(self.target, iter_all=False):
43
- ips.add(ip)
43
+ if dhcp_lease_ips := parse_unix_dhcp_leases(self.target):
44
+ ips.update(dhcp_lease_ips)
45
+
46
+ elif dhcp_log_ips := parse_unix_dhcp_log_messages(self.target, iter_all=False):
47
+ ips.update(dhcp_log_ips)
44
48
 
45
49
  return list(ips)
46
50
 
@@ -12,6 +12,7 @@ from typing import TYPE_CHECKING, Any, Callable, Iterable, Iterator, Match
12
12
  from defusedxml import ElementTree
13
13
 
14
14
  from dissect.target.exceptions import PluginError
15
+ from dissect.target.helpers import configutil
15
16
 
16
17
  if TYPE_CHECKING:
17
18
  from dissect.target.helpers.fsutil import TargetPath
@@ -601,6 +602,40 @@ def parse_unix_dhcp_log_messages(target: Target, iter_all: bool = False) -> set[
601
602
  return ips
602
603
 
603
604
 
605
+ def parse_unix_dhcp_leases(target: Target) -> set[str]:
606
+ """Parse NetworkManager and dhclient DHCP ``.lease`` files.
607
+
608
+ Resources:
609
+ - https://linux.die.net/man/5/dhclient.conf
610
+
611
+ Args:
612
+ target: Target to discover and obtain network information from.
613
+
614
+ Returns:
615
+ A set of found DHCP IP addresses.
616
+ """
617
+ ips = set()
618
+
619
+ for lease_file in chain(
620
+ target.fs.path("/var/lib/NetworkManager").glob("*.lease*"),
621
+ target.fs.path("/var/lib/dhcp").glob("*.lease*"),
622
+ target.fs.path("/var/lib/dhclient").glob("*.lease*"),
623
+ ):
624
+ lease_text = lease_file.read_text()
625
+
626
+ if "lease {" in lease_text:
627
+ for line in lease_text.split("\n"):
628
+ if "fixed-address" in line:
629
+ ips.add(line.split(" ")[-1].strip(";"))
630
+
631
+ elif "ADDRESS=" in lease_text:
632
+ lease = configutil.parse(lease_file, hint="env")
633
+ if ip := lease.get("ADDRESS"):
634
+ ips.add(ip)
635
+
636
+ return ips
637
+
638
+
604
639
  def should_ignore_ip(ip: str) -> bool:
605
640
  for i in IGNORED_IPS:
606
641
  if ip.startswith(i):
@@ -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.dev13
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
@@ -227,14 +227,14 @@ dissect/target/plugins/os/unix/esxi/_os.py,sha256=eTI6zVubEmdx02mMDyTpmf2J53IzhW
227
227
  dissect/target/plugins/os/unix/etc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
228
228
  dissect/target/plugins/os/unix/etc/etc.py,sha256=YSCRZZfQvmzaR5VWhTJhB8pIGliL6Nw5ruhdfvYKYaM,2783
229
229
  dissect/target/plugins/os/unix/linux/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
230
- dissect/target/plugins/os/unix/linux/_os.py,sha256=k1aHhWqocSHMVbF54VDw9wqwa0QSToOa69TMKAyQcxw,2979
230
+ dissect/target/plugins/os/unix/linux/_os.py,sha256=C3IM_6dSixt_9Tsjjy6-LaT4IIkl3hiBuoo8LXTW4Dg,3137
231
231
  dissect/target/plugins/os/unix/linux/cmdline.py,sha256=n_Uetoplx33XpIY27oPtMaw1E2AbAEeGLCSkxHshWgY,1673
232
232
  dissect/target/plugins/os/unix/linux/environ.py,sha256=n7KttVzUtBHTIXQuS1DI5Azv6tM__d9gGqhPR_3ArIE,1932
233
233
  dissect/target/plugins/os/unix/linux/iptables.py,sha256=qTzY5PHHXA33WnPYb5NESgoSwI7ECZ8YPoEe_Fmln-8,6045
234
234
  dissect/target/plugins/os/unix/linux/modules.py,sha256=-LThb5mcKtngVfIICpdOGLtgJPc99WQ8Qufwddt8YgQ,2500
235
235
  dissect/target/plugins/os/unix/linux/netstat.py,sha256=EBpbK4BD3pZ0fKCR3ZMmVip4eQ0f6x_9yumA8vsUKPw,1691
236
236
  dissect/target/plugins/os/unix/linux/network.py,sha256=KfGfYhtrzpHHefaHjTpdbGSLu6IN4anweYt3V02D9zU,14392
237
- dissect/target/plugins/os/unix/linux/network_managers.py,sha256=atvcHPXFHVeCD5ipygqpR8pOgSexCGKIvVZz3Z8ITLA,25770
237
+ dissect/target/plugins/os/unix/linux/network_managers.py,sha256=h5kOQe8yAYx18kGD_0zc6Mda5PK-MuQQI34MlNkUXKw,26815
238
238
  dissect/target/plugins/os/unix/linux/proc.py,sha256=jm35fAasnNbObN2tpflwQuCfVYLDkTP2EDrzYG42ZSk,23354
239
239
  dissect/target/plugins/os/unix/linux/processes.py,sha256=xAJswf06HZsY8JhQ11xfJw1OLTZ1q9XZbu7_a7k2UpY,2019
240
240
  dissect/target/plugins/os/unix/linux/services.py,sha256=cZWmoVImbl7foKQfBpiKjeC2kjvfRUpM-ympFQorwHI,4128
@@ -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.dev13.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
387
+ dissect.target-3.20.2.dev13.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
388
+ dissect.target-3.20.2.dev13.dist-info/METADATA,sha256=9Lzw8f76ZYkGqAxYcbnxFjZx1JDFuQk_GTqfbStg8q0,13184
389
+ dissect.target-3.20.2.dev13.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
390
+ dissect.target-3.20.2.dev13.dist-info/entry_points.txt,sha256=yQwLCWUuzHgS6-sfCcRk66gAfoCfqXdCjqKjvhnQW8o,537
391
+ dissect.target-3.20.2.dev13.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
392
+ dissect.target-3.20.2.dev13.dist-info/RECORD,,