dissect.target 3.20.2.dev11__py3-none-any.whl → 3.20.2.dev13__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))
@@ -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,,