dissect.target 3.20.dev64__py3-none-any.whl → 3.20.1__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.
- dissect/target/helpers/configutil.py +2 -2
- dissect/target/helpers/record.py +12 -6
- dissect/target/helpers/regutil.py +28 -11
- dissect/target/helpers/utils.py +20 -1
- dissect/target/plugins/general/network.py +1 -1
- dissect/target/plugins/os/unix/bsd/osx/network.py +2 -1
- dissect/target/plugins/os/unix/etc/etc.py +12 -6
- dissect/target/plugins/os/unix/linux/fortios/_keys.py +832 -0
- dissect/target/plugins/os/unix/linux/network.py +338 -0
- dissect/target/plugins/os/unix/trash.py +13 -2
- dissect/target/plugins/os/windows/network.py +9 -5
- {dissect.target-3.20.dev64.dist-info → dissect.target-3.20.1.dist-info}/METADATA +73 -73
- {dissect.target-3.20.dev64.dist-info → dissect.target-3.20.1.dist-info}/RECORD +18 -17
- {dissect.target-3.20.dev64.dist-info → dissect.target-3.20.1.dist-info}/WHEEL +1 -1
- {dissect.target-3.20.dev64.dist-info → dissect.target-3.20.1.dist-info}/COPYRIGHT +0 -0
- {dissect.target-3.20.dev64.dist-info → dissect.target-3.20.1.dist-info}/LICENSE +0 -0
- {dissect.target-3.20.dev64.dist-info → dissect.target-3.20.1.dist-info}/entry_points.txt +0 -0
- {dissect.target-3.20.dev64.dist-info → dissect.target-3.20.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,338 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import re
|
4
|
+
from dataclasses import dataclass, field
|
5
|
+
from datetime import datetime, timezone
|
6
|
+
from ipaddress import ip_address, ip_interface
|
7
|
+
from typing import TYPE_CHECKING, Any, Iterator, Literal, NamedTuple
|
8
|
+
|
9
|
+
from dissect.target.helpers import configutil
|
10
|
+
from dissect.target.helpers.record import UnixInterfaceRecord
|
11
|
+
from dissect.target.helpers.utils import to_list
|
12
|
+
from dissect.target.plugins.general.network import NetworkPlugin
|
13
|
+
|
14
|
+
if TYPE_CHECKING:
|
15
|
+
from ipaddress import IPv4Address, IPv4Interface, IPv6Address, IPv6Interface
|
16
|
+
|
17
|
+
from dissect.target import Target
|
18
|
+
from dissect.target.target import TargetPath
|
19
|
+
|
20
|
+
NetAddress = IPv4Address | IPv6Address
|
21
|
+
NetInterface = IPv4Interface | IPv6Interface
|
22
|
+
|
23
|
+
|
24
|
+
class LinuxNetworkPlugin(NetworkPlugin):
|
25
|
+
"""Linux network interface plugin."""
|
26
|
+
|
27
|
+
def _interfaces(self) -> Iterator[UnixInterfaceRecord]:
|
28
|
+
"""Try all available network configuration managers and aggregate the results."""
|
29
|
+
for manager_cls in MANAGERS:
|
30
|
+
manager: LinuxNetworkConfigParser = manager_cls(self.target)
|
31
|
+
yield from manager.interfaces()
|
32
|
+
|
33
|
+
|
34
|
+
VlanIdByInterface = dict[str, set[int]]
|
35
|
+
|
36
|
+
|
37
|
+
class LinuxNetworkConfigParser:
|
38
|
+
def __init__(self, target: Target):
|
39
|
+
self._target = target
|
40
|
+
|
41
|
+
def _config_files(self, config_paths: list[str], glob: str) -> list[TargetPath]:
|
42
|
+
"""Returns all configuration files in config_paths matching the given extension."""
|
43
|
+
all_files = []
|
44
|
+
for config_path in config_paths:
|
45
|
+
paths = self._target.fs.path(config_path).glob(glob)
|
46
|
+
all_files.extend(config_file for config_file in paths if config_file.is_file())
|
47
|
+
|
48
|
+
return sorted(all_files, key=lambda p: p.stem)
|
49
|
+
|
50
|
+
def interfaces(self) -> Iterator[UnixInterfaceRecord]:
|
51
|
+
"""Parse network interfaces from configuration files."""
|
52
|
+
yield from ()
|
53
|
+
|
54
|
+
|
55
|
+
class NetworkManagerConfigParser(LinuxNetworkConfigParser):
|
56
|
+
"""NetworkManager configuration parser.
|
57
|
+
|
58
|
+
NetworkManager configuration files are generally in an INI-like format.
|
59
|
+
Note that Red Hat and Fedora deprecated ifcfg files.
|
60
|
+
Documentation: https://networkmanager.dev/docs/api/latest/nm-settings-keyfile.html
|
61
|
+
"""
|
62
|
+
|
63
|
+
config_paths: list[str] = [
|
64
|
+
"/etc/NetworkManager/system-connections/",
|
65
|
+
"/usr/lib/NetworkManager/system-connections/",
|
66
|
+
"/run/NetworkManager/system-connections/",
|
67
|
+
]
|
68
|
+
|
69
|
+
@dataclass
|
70
|
+
class ParserContext:
|
71
|
+
source: str
|
72
|
+
uuid: str | None = None
|
73
|
+
last_connected: datetime | None = None
|
74
|
+
name: str | None = None
|
75
|
+
mac_address: str | None = None
|
76
|
+
type: str = ""
|
77
|
+
dns: set[NetAddress] = field(default_factory=set)
|
78
|
+
ip_interfaces: set[NetInterface] = field(default_factory=set)
|
79
|
+
gateways: set[NetAddress] = field(default_factory=set)
|
80
|
+
dhcp_ipv4: bool = False
|
81
|
+
dhcp_ipv6: bool = False
|
82
|
+
vlan: set[int] = field(default_factory=set)
|
83
|
+
|
84
|
+
def to_record(self) -> UnixInterfaceRecord:
|
85
|
+
return UnixInterfaceRecord(
|
86
|
+
source=self.source,
|
87
|
+
last_connected=self.last_connected,
|
88
|
+
name=self.name,
|
89
|
+
mac=[self.mac_address] if self.mac_address else [],
|
90
|
+
type=self.type,
|
91
|
+
dhcp_ipv4=self.dhcp_ipv4,
|
92
|
+
dhcp_ipv6=self.dhcp_ipv6,
|
93
|
+
dns=list(self.dns),
|
94
|
+
ip=[interface.ip for interface in self.ip_interfaces],
|
95
|
+
network=[interface.network for interface in self.ip_interfaces],
|
96
|
+
gateway=list(self.gateways),
|
97
|
+
vlan=list(self.vlan),
|
98
|
+
configurator="NetworkManager",
|
99
|
+
)
|
100
|
+
|
101
|
+
def interfaces(self) -> Iterator[UnixInterfaceRecord]:
|
102
|
+
connections: list[NetworkManagerConfigParser.ParserContext] = []
|
103
|
+
vlan_id_by_interface: VlanIdByInterface = {}
|
104
|
+
|
105
|
+
for connection_file_path in self._config_files(self.config_paths, "*"):
|
106
|
+
try:
|
107
|
+
config = configutil.parse(connection_file_path, hint="ini")
|
108
|
+
context = self.ParserContext(source=connection_file_path)
|
109
|
+
common_section: dict[str, str] = config.get("connection", {})
|
110
|
+
context.type = common_section.get("type", "")
|
111
|
+
sub_type: dict[str, str] = config.get(context.type, {})
|
112
|
+
|
113
|
+
if context.type == "vlan":
|
114
|
+
self._parse_vlan(sub_type, vlan_id_by_interface)
|
115
|
+
continue
|
116
|
+
|
117
|
+
for ip_version in ["ipv4", "ipv6"]:
|
118
|
+
ip_section: dict[str, str] = config.get(ip_version, {})
|
119
|
+
for key, value in ip_section.items():
|
120
|
+
self._parse_ip_section_key(key, value, context, ip_version)
|
121
|
+
|
122
|
+
context.name = common_section.get("interface-name")
|
123
|
+
context.mac_address = sub_type.get("mac-address")
|
124
|
+
context.uuid = common_section.get("uuid")
|
125
|
+
context.source = str(connection_file_path)
|
126
|
+
context.last_connected = self._parse_lastconnected(common_section.get("timestamp", ""))
|
127
|
+
|
128
|
+
connections.append(context)
|
129
|
+
|
130
|
+
except Exception as e:
|
131
|
+
self._target.log.warning("Error parsing network config file %s", connection_file_path)
|
132
|
+
self._target.log.debug("", exc_info=e)
|
133
|
+
|
134
|
+
for connection in connections:
|
135
|
+
vlan_ids_from_interface = vlan_id_by_interface.get(connection.name, set())
|
136
|
+
connection.vlan.update(vlan_ids_from_interface)
|
137
|
+
|
138
|
+
vlan_ids_from_uuid = vlan_id_by_interface.get(connection.uuid, set())
|
139
|
+
connection.vlan.update(vlan_ids_from_uuid)
|
140
|
+
|
141
|
+
yield connection.to_record()
|
142
|
+
|
143
|
+
def _parse_route(self, route: str) -> NetAddress | None:
|
144
|
+
"""Parse a route and return gateway IP address."""
|
145
|
+
if (elements := route.split(",")) and len(elements) > 1:
|
146
|
+
return ip_address(elements[1])
|
147
|
+
|
148
|
+
return None
|
149
|
+
|
150
|
+
def _parse_lastconnected(self, last_connected: str) -> datetime | None:
|
151
|
+
"""Parse last connected timestamp."""
|
152
|
+
if not last_connected:
|
153
|
+
return None
|
154
|
+
|
155
|
+
return datetime.fromtimestamp(int(last_connected), timezone.utc)
|
156
|
+
|
157
|
+
def _parse_ip_section_key(
|
158
|
+
self, key: str, value: str, context: ParserContext, ip_version: Literal["ipv4", "ipv6"]
|
159
|
+
) -> None:
|
160
|
+
if not (trimmed := value.strip()):
|
161
|
+
return
|
162
|
+
|
163
|
+
if key == "dns":
|
164
|
+
context.dns.update(ip_address(addr) for addr in trimmed.split(";") if addr)
|
165
|
+
elif key.startswith("address"):
|
166
|
+
# Undocumented: single gateway on address line. Observed when running:
|
167
|
+
# nmcli connection add type ethernet ... ip4 192.168.2.138/24 gw4 192.168.2.1
|
168
|
+
ip, *gateway = trimmed.split(",", 1)
|
169
|
+
context.ip_interfaces.add(ip_interface(ip))
|
170
|
+
if gateway:
|
171
|
+
context.gateways.add(ip_address(gateway[0]))
|
172
|
+
elif key.startswith("gateway"):
|
173
|
+
context.gateways.add(ip_address(trimmed))
|
174
|
+
elif key == "method":
|
175
|
+
if ip_version == "ipv4":
|
176
|
+
context.dhcp_ipv4 = trimmed == "auto"
|
177
|
+
elif ip_version == "ipv6":
|
178
|
+
context.dhcp_ipv6 = trimmed == "auto"
|
179
|
+
elif key.startswith("route"):
|
180
|
+
if gateway := self._parse_route(value):
|
181
|
+
context.gateways.add(gateway)
|
182
|
+
|
183
|
+
def _parse_vlan(self, sub_type: dict[str, Any], vlan_id_by_interface: VlanIdByInterface) -> None:
|
184
|
+
parent_interface = sub_type.get("parent")
|
185
|
+
vlan_id = sub_type.get("id")
|
186
|
+
if not parent_interface or not vlan_id:
|
187
|
+
return
|
188
|
+
|
189
|
+
ids = vlan_id_by_interface.setdefault(parent_interface, set())
|
190
|
+
ids.add(int(vlan_id))
|
191
|
+
|
192
|
+
|
193
|
+
class SystemdNetworkConfigParser(LinuxNetworkConfigParser):
|
194
|
+
"""Systemd network configuration parser.
|
195
|
+
|
196
|
+
Systemd network configuration files are generally in an INI-like format with some quirks.
|
197
|
+
Note that drop-in directories are not yet supported.
|
198
|
+
|
199
|
+
Documentation: https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html
|
200
|
+
"""
|
201
|
+
|
202
|
+
config_paths: list[str] = [
|
203
|
+
"/etc/systemd/network/",
|
204
|
+
"/run/systemd/network/",
|
205
|
+
"/usr/lib/systemd/network/",
|
206
|
+
"/usr/local/lib/systemd/network/",
|
207
|
+
]
|
208
|
+
|
209
|
+
class DhcpConfig(NamedTuple):
|
210
|
+
ipv4: bool
|
211
|
+
ipv6: bool
|
212
|
+
|
213
|
+
# Can be enclosed in brackets for IPv6. Can also have port, iface name, and SNI, which we ignore.
|
214
|
+
# Example: [1111:2222::3333]:9953%ifname#example.com
|
215
|
+
dns_ip_patttern = re.compile(
|
216
|
+
r"(?P<withoutBrackets>(?:\d{1,3}\.){3}\d{1,3})|\[(?P<withBrackets>\[?[0-9a-fA-F:]+\]?)\]"
|
217
|
+
)
|
218
|
+
|
219
|
+
def interfaces(self) -> Iterator:
|
220
|
+
virtual_networks = self._parse_virtual_networks()
|
221
|
+
yield from self._parse_networks(virtual_networks)
|
222
|
+
|
223
|
+
def _parse_virtual_networks(self) -> VlanIdByInterface:
|
224
|
+
"""Parse virtual network configurations from systemd network configuration files."""
|
225
|
+
|
226
|
+
virtual_networks: VlanIdByInterface = {}
|
227
|
+
for config_file in self._config_files(self.config_paths, "*.netdev"):
|
228
|
+
try:
|
229
|
+
virtual_network_config = configutil.parse(config_file, hint="systemd")
|
230
|
+
net_dev_section: dict[str, str] = virtual_network_config.get("NetDev", {})
|
231
|
+
if net_dev_section.get("Kind") != "vlan":
|
232
|
+
continue
|
233
|
+
|
234
|
+
vlan_id = virtual_network_config.get("VLAN", {}).get("Id")
|
235
|
+
if (name := net_dev_section.get("Name")) and vlan_id:
|
236
|
+
vlan_ids = virtual_networks.setdefault(name, set())
|
237
|
+
vlan_ids.add(int(vlan_id))
|
238
|
+
except Exception as e:
|
239
|
+
self._target.log.warning("Error parsing virtual network config file %s", config_file)
|
240
|
+
self._target.log.debug("", exc_info=e)
|
241
|
+
|
242
|
+
return virtual_networks
|
243
|
+
|
244
|
+
def _parse_networks(self, virtual_networks: VlanIdByInterface) -> Iterator[UnixInterfaceRecord]:
|
245
|
+
"""Parse network configurations from systemd network configuration files."""
|
246
|
+
for config_file in self._config_files(self.config_paths, "*.network"):
|
247
|
+
try:
|
248
|
+
config = configutil.parse(config_file, hint="systemd")
|
249
|
+
|
250
|
+
match_section: dict[str, str] = config.get("Match", {})
|
251
|
+
network_section: dict[str, str] = config.get("Network", {})
|
252
|
+
link_section: dict[str, str] = config.get("Link", {})
|
253
|
+
|
254
|
+
ip_interfaces: set[NetInterface] = set()
|
255
|
+
gateways: set[NetAddress] = set()
|
256
|
+
dns: set[NetAddress] = set()
|
257
|
+
mac_addresses: set[str] = set()
|
258
|
+
|
259
|
+
if link_mac := link_section.get("MACAddress"):
|
260
|
+
mac_addresses.add(link_mac)
|
261
|
+
mac_addresses.update(match_section.get("MACAddress", "").split())
|
262
|
+
mac_addresses.update(match_section.get("PermanentMACAddress", "").split())
|
263
|
+
|
264
|
+
dns_value = to_list(network_section.get("DNS", []))
|
265
|
+
dns.update(self._parse_dns_ip(dns_ip) for dns_ip in dns_value)
|
266
|
+
|
267
|
+
address_value = to_list(network_section.get("Address", []))
|
268
|
+
ip_interfaces.update(ip_interface(addr) for addr in address_value)
|
269
|
+
|
270
|
+
gateway_value = to_list(network_section.get("Gateway", []))
|
271
|
+
gateways.update(ip_address(gateway) for gateway in gateway_value)
|
272
|
+
|
273
|
+
vlan_ids: set[int] = set()
|
274
|
+
vlan_names = to_list(network_section.get("VLAN", []))
|
275
|
+
for vlan_name in vlan_names:
|
276
|
+
if ids := virtual_networks.get(vlan_name):
|
277
|
+
vlan_ids.update(ids)
|
278
|
+
|
279
|
+
# There are possibly multiple route sections, but they are collapsed into one by the parser.
|
280
|
+
route_section: dict[str, Any] = config.get("Route", {})
|
281
|
+
gateway_values = to_list(route_section.get("Gateway", []))
|
282
|
+
gateways.update(filter(None, map(self._parse_gateway, gateway_values)))
|
283
|
+
|
284
|
+
dhcp_ipv4, dhcp_ipv6 = self._parse_dhcp(network_section.get("DHCP"))
|
285
|
+
|
286
|
+
yield UnixInterfaceRecord(
|
287
|
+
source=str(config_file),
|
288
|
+
type=match_section.get("Type"),
|
289
|
+
enabled=None, # Unknown, dependent on run-time state
|
290
|
+
dhcp_ipv4=dhcp_ipv4,
|
291
|
+
dhcp_ipv6=dhcp_ipv6,
|
292
|
+
name=match_section.get("Name"),
|
293
|
+
dns=list(dns),
|
294
|
+
mac=list(mac_addresses),
|
295
|
+
ip=[interface.ip for interface in ip_interfaces],
|
296
|
+
network=[interface.network for interface in ip_interfaces],
|
297
|
+
gateway=list(gateways),
|
298
|
+
vlan=list(vlan_ids),
|
299
|
+
configurator="systemd-networkd",
|
300
|
+
)
|
301
|
+
except Exception as e:
|
302
|
+
self._target.log.warning("Error parsing network config file %s", config_file)
|
303
|
+
self._target.log.debug("", exc_info=e)
|
304
|
+
|
305
|
+
def _parse_dns_ip(self, address: str) -> NetAddress:
|
306
|
+
"""Parse DNS address from systemd network configuration file.
|
307
|
+
|
308
|
+
The optional brackets and port number make this hard to parse.
|
309
|
+
See https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html and search for DNS.
|
310
|
+
"""
|
311
|
+
|
312
|
+
if match := self.dns_ip_patttern.search(address):
|
313
|
+
return ip_address(match.group("withoutBrackets") or match.group("withBrackets"))
|
314
|
+
|
315
|
+
raise ValueError(f"Invalid DNS address format: {address}")
|
316
|
+
|
317
|
+
def _parse_dhcp(self, value: str | None) -> DhcpConfig:
|
318
|
+
"""Parse DHCP value from systemd network configuration file to a named tuple (ipv4, ipv6)."""
|
319
|
+
|
320
|
+
if value is None or value == "no":
|
321
|
+
return self.DhcpConfig(ipv4=False, ipv6=False)
|
322
|
+
elif value == "yes":
|
323
|
+
return self.DhcpConfig(ipv4=True, ipv6=True)
|
324
|
+
elif value == "ipv4":
|
325
|
+
return self.DhcpConfig(ipv4=True, ipv6=False)
|
326
|
+
elif value == "ipv6":
|
327
|
+
return self.DhcpConfig(ipv4=False, ipv6=True)
|
328
|
+
|
329
|
+
raise ValueError(f"Invalid DHCP value: {value}")
|
330
|
+
|
331
|
+
def _parse_gateway(self, value: str | None) -> NetAddress | None:
|
332
|
+
if (not value) or (value in {"_dhcp4", "_ipv6ra"}):
|
333
|
+
return None
|
334
|
+
|
335
|
+
return ip_address(value)
|
336
|
+
|
337
|
+
|
338
|
+
MANAGERS = [NetworkManagerConfigParser, SystemdNetworkConfigParser]
|
@@ -31,15 +31,25 @@ class GnomeTrashPlugin(Plugin):
|
|
31
31
|
|
32
32
|
def __init__(self, target: Target):
|
33
33
|
super().__init__(target)
|
34
|
-
self.trashes =
|
34
|
+
self.trashes = set(self._garbage_collector())
|
35
35
|
|
36
36
|
def _garbage_collector(self) -> Iterator[tuple[UserDetails, TargetPath]]:
|
37
37
|
"""it aint much, but its honest work"""
|
38
|
+
|
39
|
+
# home trash folders
|
38
40
|
for user_details in self.target.user_details.all_with_home():
|
39
41
|
for trash_path in self.PATHS:
|
40
42
|
if (path := user_details.home_path.joinpath(trash_path)).exists():
|
41
43
|
yield user_details, path
|
42
44
|
|
45
|
+
# mounted devices trash folders
|
46
|
+
for mount_path in list(self.target.fs.mounts) + ["/mnt", "/media"]:
|
47
|
+
if mount_path == "/":
|
48
|
+
continue
|
49
|
+
|
50
|
+
for mount_trash in self.target.fs.path(mount_path).rglob(".Trash-*"):
|
51
|
+
yield UserDetails(None, None), mount_trash
|
52
|
+
|
43
53
|
def check_compatible(self) -> None:
|
44
54
|
if not self.trashes:
|
45
55
|
raise UnsupportedPluginError("No Trash folder(s) found")
|
@@ -52,7 +62,8 @@ class GnomeTrashPlugin(Plugin):
|
|
52
62
|
Recovers deleted files and artifacts from ``$HOME/.local/share/Trash``.
|
53
63
|
Probably also works with other desktop interfaces as long as they follow the Trash specification from FreeDesktop.
|
54
64
|
|
55
|
-
|
65
|
+
Also parses media trash locations such as ``/media/$USER/$Label/.Trash-*``, ``/mnt/$Label/.Trash-*`` and other
|
66
|
+
locations as defined in ``/etc/fstab``.
|
56
67
|
|
57
68
|
Resources:
|
58
69
|
- https://specifications.freedesktop.org/trash-spec/latest/
|
@@ -1,5 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
import re
|
3
4
|
from enum import IntEnum
|
4
5
|
from functools import lru_cache
|
5
6
|
from typing import Iterator
|
@@ -224,11 +225,13 @@ def _try_value(subkey: RegistryKey, value: str) -> str | list | None:
|
|
224
225
|
return None
|
225
226
|
|
226
227
|
|
227
|
-
def _get_config_value(key: RegistryKey, name: str) -> set:
|
228
|
+
def _get_config_value(key: RegistryKey, name: str, sep: str | None = None) -> set:
|
228
229
|
value = _try_value(key, name)
|
229
230
|
if not value or value in ("", "0.0.0.0", None, [], ["0.0.0.0"]):
|
230
231
|
return set()
|
231
|
-
|
232
|
+
if sep and isinstance(value, str):
|
233
|
+
re_sep = "|".join(map(re.escape, sep))
|
234
|
+
value = re.split(re_sep, value)
|
232
235
|
if isinstance(value, list):
|
233
236
|
return set(value)
|
234
237
|
|
@@ -281,7 +284,8 @@ class WindowsNetworkPlugin(NetworkPlugin):
|
|
281
284
|
pass
|
282
285
|
|
283
286
|
# Extract the rest of the device information
|
284
|
-
|
287
|
+
if mac_address := _try_value(subkey, "NetworkAddress"):
|
288
|
+
device_info["mac"] = [mac_address]
|
285
289
|
device_info["vlan"] = _try_value(subkey, "VlanID")
|
286
290
|
|
287
291
|
if timestamp := _try_value(subkey, "NetworkInterfaceInstallTimestamp"):
|
@@ -354,11 +358,11 @@ class WindowsNetworkPlugin(NetworkPlugin):
|
|
354
358
|
dhcp_config["ip"].update(_get_config_value(key, "DhcpIPAddress"))
|
355
359
|
dhcp_config["subnetmask"].update(_get_config_value(key, "DhcpSubnetMask"))
|
356
360
|
dhcp_config["search_domain"].update(_get_config_value(key, "DhcpDomain"))
|
357
|
-
dhcp_config["dns"].update(_get_config_value(key, "DhcpNameServer"))
|
361
|
+
dhcp_config["dns"].update(_get_config_value(key, "DhcpNameServer", " ,"))
|
358
362
|
|
359
363
|
# Extract static configuration from the registry
|
360
364
|
static_config["gateway"].update(_get_config_value(key, "DefaultGateway"))
|
361
|
-
static_config["dns"].update(_get_config_value(key, "NameServer"))
|
365
|
+
static_config["dns"].update(_get_config_value(key, "NameServer", " ,"))
|
362
366
|
static_config["search_domain"].update(_get_config_value(key, "Domain"))
|
363
367
|
static_config["ip"].update(_get_config_value(key, "IPAddress"))
|
364
368
|
static_config["subnetmask"].update(_get_config_value(key, "SubnetMask"))
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: dissect.target
|
3
|
-
Version: 3.20.
|
3
|
+
Version: 3.20.1
|
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
|
@@ -23,81 +23,81 @@ Description-Content-Type: text/markdown
|
|
23
23
|
License-File: LICENSE
|
24
24
|
License-File: COPYRIGHT
|
25
25
|
Requires-Dist: defusedxml
|
26
|
-
Requires-Dist: dissect.cstruct
|
27
|
-
Requires-Dist: dissect.eventlog
|
28
|
-
Requires-Dist: dissect.evidence
|
29
|
-
Requires-Dist: dissect.hypervisor
|
30
|
-
Requires-Dist: dissect.ntfs
|
31
|
-
Requires-Dist: dissect.regf
|
32
|
-
Requires-Dist: dissect.util
|
33
|
-
Requires-Dist: dissect.volume
|
34
|
-
Requires-Dist: flow.record
|
26
|
+
Requires-Dist: dissect.cstruct<5,>=4
|
27
|
+
Requires-Dist: dissect.eventlog<4,>=3
|
28
|
+
Requires-Dist: dissect.evidence<4,>=3
|
29
|
+
Requires-Dist: dissect.hypervisor<4,>=3
|
30
|
+
Requires-Dist: dissect.ntfs<4,>=3.4
|
31
|
+
Requires-Dist: dissect.regf<4,>=3.3
|
32
|
+
Requires-Dist: dissect.util<4,>=3
|
33
|
+
Requires-Dist: dissect.volume<4,>=2
|
34
|
+
Requires-Dist: flow.record~=3.18.0
|
35
35
|
Requires-Dist: structlog
|
36
|
-
Provides-Extra: cb
|
37
|
-
Requires-Dist: dissect.target[full] ; extra == 'cb'
|
38
|
-
Requires-Dist: carbon-black-cloud-sdk ~=1.4.3 ; extra == 'cb'
|
39
|
-
Provides-Extra: dev
|
40
|
-
Requires-Dist: dissect.target[full,mqtt,yara] ; extra == 'dev'
|
41
|
-
Requires-Dist: dissect.archive[dev] <2.0.dev,>=1.0.dev ; extra == 'dev'
|
42
|
-
Requires-Dist: dissect.btrfs[dev] <2.0.dev,>=1.0.dev ; extra == 'dev'
|
43
|
-
Requires-Dist: dissect.cim[dev] <4.0.dev,>=3.0.dev ; extra == 'dev'
|
44
|
-
Requires-Dist: dissect.clfs[dev] <2.0.dev,>=1.0.dev ; extra == 'dev'
|
45
|
-
Requires-Dist: dissect.cstruct <5.0.dev,>=4.0.dev ; extra == 'dev'
|
46
|
-
Requires-Dist: dissect.esedb[dev] <4.0.dev,>=3.0.dev ; extra == 'dev'
|
47
|
-
Requires-Dist: dissect.etl[dev] <4.0.dev,>=3.0.dev ; extra == 'dev'
|
48
|
-
Requires-Dist: dissect.eventlog[dev] <4.0.dev,>=3.0.dev ; extra == 'dev'
|
49
|
-
Requires-Dist: dissect.evidence[dev] <4.0.dev,>=3.0.dev ; extra == 'dev'
|
50
|
-
Requires-Dist: dissect.extfs[dev] <4.0.dev,>=3.0.dev ; extra == 'dev'
|
51
|
-
Requires-Dist: dissect.fat[dev] <4.0.dev,>=3.0.dev ; extra == 'dev'
|
52
|
-
Requires-Dist: dissect.ffs[dev] <4.0.dev,>=3.0.dev ; extra == 'dev'
|
53
|
-
Requires-Dist: dissect.hypervisor[dev] <4.0.dev,>=3.0.dev ; extra == 'dev'
|
54
|
-
Requires-Dist: dissect.jffs[dev] <2.0.dev,>=1.0.dev ; extra == 'dev'
|
55
|
-
Requires-Dist: dissect.ntfs[dev] <4.0.dev,>=3.4.dev ; extra == 'dev'
|
56
|
-
Requires-Dist: dissect.regf[dev] <4.0.dev,>=3.3.dev ; extra == 'dev'
|
57
|
-
Requires-Dist: dissect.shellitem[dev] <4.0.dev,>=3.0.dev ; extra == 'dev'
|
58
|
-
Requires-Dist: dissect.sql[dev] <4.0.dev,>=3.0.dev ; extra == 'dev'
|
59
|
-
Requires-Dist: dissect.squashfs[dev] <2.0.dev,>=1.0.dev ; extra == 'dev'
|
60
|
-
Requires-Dist: dissect.thumbcache[dev] <2.0.dev,>=1.0.dev ; extra == 'dev'
|
61
|
-
Requires-Dist: dissect.util <4.0.dev,>=3.0.dev ; extra == 'dev'
|
62
|
-
Requires-Dist: dissect.vmfs[dev] <4.0.dev,>=3.0.dev ; extra == 'dev'
|
63
|
-
Requires-Dist: dissect.volume[dev] <4.0.dev,>=3.0.dev ; extra == 'dev'
|
64
|
-
Requires-Dist: dissect.xfs[dev] <4.0.dev,>=3.0.dev ; extra == 'dev'
|
65
|
-
Requires-Dist: dissect.fve[dev] <5.0.dev,>=4.0.dev ; (platform_system != "Windows" or platform_python_implementation != "PyPy") and extra == 'dev'
|
66
36
|
Provides-Extra: full
|
67
|
-
Requires-Dist: asn1crypto
|
68
|
-
Requires-Dist: dissect.archive
|
69
|
-
Requires-Dist: dissect.btrfs
|
70
|
-
Requires-Dist: dissect.cim
|
71
|
-
Requires-Dist: dissect.clfs
|
72
|
-
Requires-Dist: dissect.esedb
|
73
|
-
Requires-Dist: dissect.etl
|
74
|
-
Requires-Dist: dissect.extfs
|
75
|
-
Requires-Dist: dissect.fat
|
76
|
-
Requires-Dist: dissect.ffs
|
77
|
-
Requires-Dist: dissect.
|
78
|
-
Requires-Dist: dissect.
|
79
|
-
Requires-Dist: dissect.
|
80
|
-
Requires-Dist: dissect.
|
81
|
-
Requires-Dist: dissect.
|
82
|
-
Requires-Dist: dissect.
|
83
|
-
Requires-Dist: dissect.
|
84
|
-
Requires-Dist: dissect.
|
85
|
-
Requires-Dist:
|
86
|
-
Requires-Dist:
|
87
|
-
Requires-Dist:
|
88
|
-
Requires-Dist:
|
89
|
-
Requires-Dist:
|
90
|
-
Requires-Dist:
|
91
|
-
Requires-Dist:
|
92
|
-
Provides-Extra:
|
93
|
-
Requires-Dist: dissect.target[full]
|
94
|
-
Requires-Dist:
|
95
|
-
|
96
|
-
Requires-Dist: dissect.
|
97
|
-
Requires-Dist:
|
37
|
+
Requires-Dist: asn1crypto; extra == "full"
|
38
|
+
Requires-Dist: dissect.archive<2,>=1; extra == "full"
|
39
|
+
Requires-Dist: dissect.btrfs<2,>=1; extra == "full"
|
40
|
+
Requires-Dist: dissect.cim<4,>=3; extra == "full"
|
41
|
+
Requires-Dist: dissect.clfs<2,>=1; extra == "full"
|
42
|
+
Requires-Dist: dissect.esedb<4,>=3; extra == "full"
|
43
|
+
Requires-Dist: dissect.etl<4,>=3; extra == "full"
|
44
|
+
Requires-Dist: dissect.extfs<4,>=3; extra == "full"
|
45
|
+
Requires-Dist: dissect.fat<4,>=3; extra == "full"
|
46
|
+
Requires-Dist: dissect.ffs<4,>=3; extra == "full"
|
47
|
+
Requires-Dist: dissect.fve<5,>=4; (platform_system != "Windows" or platform_python_implementation != "PyPy") and extra == "full"
|
48
|
+
Requires-Dist: dissect.jffs<2,>=1; extra == "full"
|
49
|
+
Requires-Dist: dissect.ole<4,>=3; extra == "full"
|
50
|
+
Requires-Dist: dissect.shellitem<4,>=3; extra == "full"
|
51
|
+
Requires-Dist: dissect.squashfs<2,>=1; extra == "full"
|
52
|
+
Requires-Dist: dissect.sql<4,>=3; extra == "full"
|
53
|
+
Requires-Dist: dissect.thumbcache<2,>=1; extra == "full"
|
54
|
+
Requires-Dist: dissect.vmfs<4,>=3; extra == "full"
|
55
|
+
Requires-Dist: dissect.xfs<4,>=3; extra == "full"
|
56
|
+
Requires-Dist: ipython; extra == "full"
|
57
|
+
Requires-Dist: fusepy; extra == "full"
|
58
|
+
Requires-Dist: pycryptodome; extra == "full"
|
59
|
+
Requires-Dist: ruamel.yaml; extra == "full"
|
60
|
+
Requires-Dist: tomli; python_version < "3.11" and extra == "full"
|
61
|
+
Requires-Dist: zstandard; extra == "full"
|
62
|
+
Provides-Extra: dev
|
63
|
+
Requires-Dist: dissect.target[full,mqtt,yara]; extra == "dev"
|
64
|
+
Requires-Dist: dissect.archive[dev]<2.0.dev,>=1.0.dev; extra == "dev"
|
65
|
+
Requires-Dist: dissect.btrfs[dev]<2.0.dev,>=1.0.dev; extra == "dev"
|
66
|
+
Requires-Dist: dissect.cim[dev]<4.0.dev,>=3.0.dev; extra == "dev"
|
67
|
+
Requires-Dist: dissect.clfs[dev]<2.0.dev,>=1.0.dev; extra == "dev"
|
68
|
+
Requires-Dist: dissect.cstruct<5.0.dev,>=4.0.dev; extra == "dev"
|
69
|
+
Requires-Dist: dissect.esedb[dev]<4.0.dev,>=3.0.dev; extra == "dev"
|
70
|
+
Requires-Dist: dissect.etl[dev]<4.0.dev,>=3.0.dev; extra == "dev"
|
71
|
+
Requires-Dist: dissect.eventlog[dev]<4.0.dev,>=3.0.dev; extra == "dev"
|
72
|
+
Requires-Dist: dissect.evidence[dev]<4.0.dev,>=3.0.dev; extra == "dev"
|
73
|
+
Requires-Dist: dissect.extfs[dev]<4.0.dev,>=3.0.dev; extra == "dev"
|
74
|
+
Requires-Dist: dissect.fat[dev]<4.0.dev,>=3.0.dev; extra == "dev"
|
75
|
+
Requires-Dist: dissect.ffs[dev]<4.0.dev,>=3.0.dev; extra == "dev"
|
76
|
+
Requires-Dist: dissect.fve[dev]<5.0.dev,>=4.0.dev; (platform_system != "Windows" or platform_python_implementation != "PyPy") and extra == "dev"
|
77
|
+
Requires-Dist: dissect.hypervisor[dev]<4.0.dev,>=3.0.dev; extra == "dev"
|
78
|
+
Requires-Dist: dissect.jffs[dev]<2.0.dev,>=1.0.dev; extra == "dev"
|
79
|
+
Requires-Dist: dissect.ntfs[dev]<4.0.dev,>=3.4.dev; extra == "dev"
|
80
|
+
Requires-Dist: dissect.regf[dev]<4.0.dev,>=3.3.dev; extra == "dev"
|
81
|
+
Requires-Dist: dissect.shellitem[dev]<4.0.dev,>=3.0.dev; extra == "dev"
|
82
|
+
Requires-Dist: dissect.sql[dev]<4.0.dev,>=3.0.dev; extra == "dev"
|
83
|
+
Requires-Dist: dissect.squashfs[dev]<2.0.dev,>=1.0.dev; extra == "dev"
|
84
|
+
Requires-Dist: dissect.thumbcache[dev]<2.0.dev,>=1.0.dev; extra == "dev"
|
85
|
+
Requires-Dist: dissect.util<4.0.dev,>=3.0.dev; extra == "dev"
|
86
|
+
Requires-Dist: dissect.vmfs[dev]<4.0.dev,>=3.0.dev; extra == "dev"
|
87
|
+
Requires-Dist: dissect.volume[dev]<4.0.dev,>=3.0.dev; extra == "dev"
|
88
|
+
Requires-Dist: dissect.xfs[dev]<4.0.dev,>=3.0.dev; extra == "dev"
|
98
89
|
Provides-Extra: yara
|
99
|
-
Requires-Dist: dissect.target[full]
|
100
|
-
Requires-Dist: yara-python
|
90
|
+
Requires-Dist: dissect.target[full]; extra == "yara"
|
91
|
+
Requires-Dist: yara-python; extra == "yara"
|
92
|
+
Provides-Extra: smb
|
93
|
+
Requires-Dist: dissect.target[full]; extra == "smb"
|
94
|
+
Requires-Dist: impacket==0.10.0; extra == "smb"
|
95
|
+
Provides-Extra: cb
|
96
|
+
Requires-Dist: dissect.target[full]; extra == "cb"
|
97
|
+
Requires-Dist: carbon-black-cloud-sdk~=1.4.3; extra == "cb"
|
98
|
+
Provides-Extra: mqtt
|
99
|
+
Requires-Dist: dissect.target[full]; extra == "mqtt"
|
100
|
+
Requires-Dist: paho-mqtt==1.6.1; extra == "mqtt"
|
101
101
|
|
102
102
|
# dissect.target
|
103
103
|
|