dissect.target 3.17.dev25__py3-none-any.whl → 3.17.dev27__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/network_managers.py +66 -49
- dissect/target/plugins/apps/ssh/openssh.py +4 -0
- dissect/target/plugins/apps/ssh/putty.py +35 -13
- dissect/target/plugins/apps/ssh/ssh.py +40 -0
- dissect/target/plugins/os/unix/log/messages.py +53 -8
- {dissect.target-3.17.dev25.dist-info → dissect.target-3.17.dev27.dist-info}/METADATA +1 -1
- {dissect.target-3.17.dev25.dist-info → dissect.target-3.17.dev27.dist-info}/RECORD +12 -12
- {dissect.target-3.17.dev25.dist-info → dissect.target-3.17.dev27.dist-info}/COPYRIGHT +0 -0
- {dissect.target-3.17.dev25.dist-info → dissect.target-3.17.dev27.dist-info}/LICENSE +0 -0
- {dissect.target-3.17.dev25.dist-info → dissect.target-3.17.dev27.dist-info}/WHEEL +0 -0
- {dissect.target-3.17.dev25.dist-info → dissect.target-3.17.dev27.dist-info}/entry_points.txt +0 -0
- {dissect.target-3.17.dev25.dist-info → dissect.target-3.17.dev27.dist-info}/top_level.txt +0 -0
@@ -5,6 +5,7 @@ import re
|
|
5
5
|
from collections import defaultdict
|
6
6
|
from configparser import ConfigParser, MissingSectionHeaderError
|
7
7
|
from io import StringIO
|
8
|
+
from itertools import chain
|
8
9
|
from re import compile, sub
|
9
10
|
from typing import Any, Callable, Iterable, Match, Optional
|
10
11
|
|
@@ -299,7 +300,8 @@ class Parser:
|
|
299
300
|
return
|
300
301
|
|
301
302
|
if section:
|
302
|
-
|
303
|
+
# account for values of sections which are None
|
304
|
+
config = config.get(section, {}) or {}
|
303
305
|
|
304
306
|
for key, value in config.items():
|
305
307
|
if key == option:
|
@@ -508,7 +510,7 @@ class LinuxNetworkManager:
|
|
508
510
|
|
509
511
|
|
510
512
|
def parse_unix_dhcp_log_messages(target) -> list[str]:
|
511
|
-
"""Parse local syslog and cloud init
|
513
|
+
"""Parse local syslog, journal and cloud init-log files for DHCP lease IPs.
|
512
514
|
|
513
515
|
Args:
|
514
516
|
target: Target to discover and obtain network information from.
|
@@ -516,53 +518,68 @@ def parse_unix_dhcp_log_messages(target) -> list[str]:
|
|
516
518
|
Returns:
|
517
519
|
List of DHCP ip addresses.
|
518
520
|
"""
|
519
|
-
ips =
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
521
|
+
ips = set()
|
522
|
+
messages = set()
|
523
|
+
|
524
|
+
for log_func in ["messages", "journal"]:
|
525
|
+
try:
|
526
|
+
messages = chain(messages, getattr(target, log_func)())
|
527
|
+
except PluginError:
|
528
|
+
target.log.debug(f"Could not search for DHCP leases in {log_func} files.")
|
529
|
+
|
530
|
+
if not messages:
|
531
|
+
target.log.warning(f"Could not search for DHCP leases using {log_func}: No log entries found.")
|
532
|
+
|
533
|
+
for record in messages:
|
534
|
+
line = record.message
|
535
|
+
|
536
|
+
# Ubuntu cloud-init
|
537
|
+
if "Received dhcp lease on" in line:
|
538
|
+
interface, ip, netmask = re.search(r"Received dhcp lease on (\w{0,}) for (\S+)\/(\S+)", line).groups()
|
539
|
+
ips.add(ip)
|
540
|
+
continue
|
541
|
+
|
542
|
+
# Ubuntu DHCP
|
543
|
+
if ("DHCPv4" in line or "DHCPv6" in line) and " address " in line and " via " in line:
|
544
|
+
ip = line.split(" address ")[1].split(" via ")[0].strip().split("/")[0]
|
545
|
+
ips.add(ip)
|
546
|
+
continue
|
547
|
+
|
548
|
+
# Ubuntu DHCP NetworkManager
|
549
|
+
if "option ip_address" in line and ("dhcp4" in line or "dhcp6" in line) and "=> '" in line:
|
550
|
+
ip = line.split("=> '")[1].replace("'", "").strip()
|
551
|
+
ips.add(ip)
|
552
|
+
continue
|
553
|
+
|
554
|
+
# Debian and CentOS dhclient
|
555
|
+
if hasattr(record, "daemon") and record.daemon == "dhclient" and "bound to" in line:
|
556
|
+
ip = line.split("bound to")[1].split(" ")[1].strip()
|
557
|
+
ips.add(ip)
|
558
|
+
continue
|
559
|
+
|
560
|
+
# CentOS DHCP and general NetworkManager
|
561
|
+
if " address " in line and ("dhcp4" in line or "dhcp6" in line):
|
562
|
+
ip = line.split(" address ")[1].strip()
|
563
|
+
ips.add(ip)
|
564
|
+
continue
|
565
|
+
|
566
|
+
# Ubuntu/Debian DHCP networkd (Journal)
|
567
|
+
if (
|
568
|
+
hasattr(record, "code_func")
|
569
|
+
and record.code_func == "dhcp_lease_acquired"
|
570
|
+
and " address " in line
|
571
|
+
and " via " in line
|
572
|
+
):
|
573
|
+
interface, ip, netmask, gateway = re.search(
|
574
|
+
r"^(\S+): DHCPv[4|6] address (\S+)\/(\S+) via (\S+)", line
|
575
|
+
).groups()
|
576
|
+
ips.add(ip)
|
577
|
+
continue
|
578
|
+
|
579
|
+
# Journals and syslogs can be large and slow to iterate,
|
580
|
+
# so we stop if we have some results and have reached the journal plugin.
|
581
|
+
if len(ips) >= 2 and record._desc.name == "linux/log/journal":
|
582
|
+
break
|
566
583
|
|
567
584
|
return ips
|
568
585
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import base64
|
1
2
|
import re
|
2
3
|
from itertools import product
|
3
4
|
from pathlib import Path
|
@@ -14,6 +15,7 @@ from dissect.target.plugins.apps.ssh.ssh import (
|
|
14
15
|
PrivateKeyRecord,
|
15
16
|
PublicKeyRecord,
|
16
17
|
SSHPlugin,
|
18
|
+
calculate_fingerprints,
|
17
19
|
)
|
18
20
|
|
19
21
|
|
@@ -143,12 +145,14 @@ class OpenSSHPlugin(SSHPlugin):
|
|
143
145
|
continue
|
144
146
|
|
145
147
|
key_type, public_key, comment = parse_ssh_public_key_file(file_path)
|
148
|
+
fingerprints = calculate_fingerprints(base64.b64decode(public_key))
|
146
149
|
|
147
150
|
yield PublicKeyRecord(
|
148
151
|
mtime_ts=file_path.stat().st_mtime,
|
149
152
|
key_type=key_type,
|
150
153
|
public_key=public_key,
|
151
154
|
comment=comment,
|
155
|
+
fingerprint=fingerprints,
|
152
156
|
path=file_path,
|
153
157
|
_target=self.target,
|
154
158
|
_user=user,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import logging
|
2
|
+
from base64 import b64decode
|
2
3
|
from datetime import datetime
|
3
4
|
from pathlib import Path
|
4
5
|
from typing import Iterator, Optional, Union
|
@@ -12,7 +13,11 @@ from dissect.target.helpers.fsutil import TargetPath, open_decompress
|
|
12
13
|
from dissect.target.helpers.record import create_extended_descriptor
|
13
14
|
from dissect.target.helpers.regutil import RegistryKey
|
14
15
|
from dissect.target.plugin import export
|
15
|
-
from dissect.target.plugins.apps.ssh.ssh import
|
16
|
+
from dissect.target.plugins.apps.ssh.ssh import (
|
17
|
+
KnownHostRecord,
|
18
|
+
SSHPlugin,
|
19
|
+
calculate_fingerprints,
|
20
|
+
)
|
16
21
|
from dissect.target.plugins.general.users import UserDetails
|
17
22
|
|
18
23
|
log = logging.getLogger(__name__)
|
@@ -96,12 +101,15 @@ class PuTTYPlugin(SSHPlugin):
|
|
96
101
|
key_type, host = entry.name.split("@")
|
97
102
|
port, host = host.split(":")
|
98
103
|
|
104
|
+
public_key, fingerprints = construct_public_key(key_type, entry.value)
|
105
|
+
|
99
106
|
yield KnownHostRecord(
|
100
107
|
mtime_ts=ssh_host_keys.ts,
|
101
108
|
host=host,
|
102
109
|
port=port,
|
103
110
|
key_type=key_type,
|
104
|
-
public_key=
|
111
|
+
public_key=public_key,
|
112
|
+
fingerprint=fingerprints,
|
105
113
|
comment="",
|
106
114
|
marker=None,
|
107
115
|
path=windows_path(ssh_host_keys.path),
|
@@ -121,12 +129,15 @@ class PuTTYPlugin(SSHPlugin):
|
|
121
129
|
key_type, host = parts[0].split("@")
|
122
130
|
port, host = host.split(":")
|
123
131
|
|
132
|
+
public_key, fingerprints = construct_public_key(key_type, parts[1])
|
133
|
+
|
124
134
|
yield KnownHostRecord(
|
125
135
|
mtime_ts=ts,
|
126
136
|
host=host,
|
127
137
|
port=port,
|
128
138
|
key_type=key_type,
|
129
|
-
public_key=
|
139
|
+
public_key=public_key,
|
140
|
+
fingerprint=fingerprints,
|
130
141
|
comment="",
|
131
142
|
marker=None,
|
132
143
|
path=posix_path(ssh_host_keys_path),
|
@@ -197,8 +208,8 @@ def parse_host_user(host: str, user: str) -> tuple[str, str]:
|
|
197
208
|
return host, user
|
198
209
|
|
199
210
|
|
200
|
-
def construct_public_key(key_type: str, iv: str) -> str:
|
201
|
-
"""Returns OpenSSH format public key calculated from PuTTY SshHostKeys format.
|
211
|
+
def construct_public_key(key_type: str, iv: str) -> tuple[str, tuple[str, str, str]]:
|
212
|
+
"""Returns OpenSSH format public key calculated from PuTTY SshHostKeys format and set of fingerprints.
|
202
213
|
|
203
214
|
PuTTY stores raw public key components instead of OpenSSH-formatted public keys
|
204
215
|
or fingerprints. With RSA public keys the exponent and modulus are stored.
|
@@ -206,9 +217,7 @@ def construct_public_key(key_type: str, iv: str) -> str:
|
|
206
217
|
|
207
218
|
Currently supports ``ssh-ed25519``, ``ecdsa-sha2-nistp256`` and ``rsa2`` key types.
|
208
219
|
|
209
|
-
NOTE:
|
210
|
-
- Sha256 fingerprints of the reconstructed public keys are currently not generated.
|
211
|
-
- More key types could be supported in the future.
|
220
|
+
NOTE: More key types could be supported in the future.
|
212
221
|
|
213
222
|
Resources:
|
214
223
|
- https://github.com/github/putty/blob/master/contrib/kh2reg.py
|
@@ -217,20 +226,33 @@ def construct_public_key(key_type: str, iv: str) -> str:
|
|
217
226
|
- https://github.com/mkorthof/reg2kh
|
218
227
|
"""
|
219
228
|
|
229
|
+
if not isinstance(key_type, str) or not isinstance(iv, str):
|
230
|
+
raise ValueError("Invalid key_type or iv")
|
231
|
+
|
232
|
+
key = None
|
233
|
+
|
220
234
|
if key_type == "ssh-ed25519":
|
221
235
|
x, y = iv.split(",")
|
222
236
|
key = ECC.construct(curve="ed25519", point_x=int(x, 16), point_y=int(y, 16))
|
223
|
-
return key.public_key().export_key(format="OpenSSH").split()[-1]
|
224
237
|
|
225
238
|
if key_type == "ecdsa-sha2-nistp256":
|
226
239
|
_, x, y = iv.split(",")
|
227
240
|
key = ECC.construct(curve="NIST P-256", point_x=int(x, 16), point_y=int(y, 16))
|
228
|
-
return key.public_key().export_key(format="OpenSSH").split()[-1]
|
229
241
|
|
230
242
|
if key_type == "rsa2":
|
231
243
|
exponent, modulus = iv.split(",")
|
232
244
|
key = RSA.construct((int(modulus, 16), int(exponent, 16)))
|
233
|
-
return key.public_key().export_key(format="OpenSSH").decode("utf-8").split()[-1]
|
234
245
|
|
235
|
-
|
236
|
-
|
246
|
+
if key is None:
|
247
|
+
log.warning("Could not reconstruct public key: type %s not implemented", key_type)
|
248
|
+
return iv, (None, None, None)
|
249
|
+
|
250
|
+
openssh_public_key = key.public_key().export_key(format="OpenSSH")
|
251
|
+
|
252
|
+
if isinstance(openssh_public_key, bytes):
|
253
|
+
# RSA's export_key() returns bytes
|
254
|
+
openssh_public_key = openssh_public_key.decode()
|
255
|
+
|
256
|
+
key_part = openssh_public_key.split()[-1]
|
257
|
+
fingerprints = calculate_fingerprints(b64decode(key_part))
|
258
|
+
return key_part, fingerprints
|
@@ -1,3 +1,6 @@
|
|
1
|
+
import base64
|
2
|
+
from hashlib import md5, sha1, sha256
|
3
|
+
|
1
4
|
from dissect.target.helpers.descriptor_extensions import UserRecordDescriptorExtension
|
2
5
|
from dissect.target.helpers.record import create_extended_descriptor
|
3
6
|
from dissect.target.plugin import NamespacePlugin
|
@@ -29,6 +32,7 @@ KnownHostRecord = OpenSSHUserRecordDescriptor(
|
|
29
32
|
("varint", "port"),
|
30
33
|
("string", "public_key"),
|
31
34
|
("string", "marker"),
|
35
|
+
("digest", "fingerprint"),
|
32
36
|
],
|
33
37
|
)
|
34
38
|
|
@@ -50,9 +54,45 @@ PublicKeyRecord = OpenSSHUserRecordDescriptor(
|
|
50
54
|
("datetime", "mtime_ts"),
|
51
55
|
*COMMON_ELLEMENTS,
|
52
56
|
("string", "public_key"),
|
57
|
+
("digest", "fingerprint"),
|
53
58
|
],
|
54
59
|
)
|
55
60
|
|
56
61
|
|
57
62
|
class SSHPlugin(NamespacePlugin):
|
58
63
|
__namespace__ = "ssh"
|
64
|
+
|
65
|
+
|
66
|
+
def calculate_fingerprints(public_key_decoded: bytes, ssh_keygen_format: bool = False) -> tuple[str, str, str]:
|
67
|
+
"""Calculate the MD5, SHA1 and SHA256 digest of the given decoded public key.
|
68
|
+
|
69
|
+
Adheres as much as possible to the output provided by ssh-keygen when ``ssh_keygen_format``
|
70
|
+
parameter is set to ``True``. When set to ``False`` (default) hexdigests are calculated
|
71
|
+
instead for ``sha1``and ``sha256``.
|
72
|
+
|
73
|
+
Resources:
|
74
|
+
- https://en.wikipedia.org/wiki/Public_key_fingerprint
|
75
|
+
- https://man7.org/linux/man-pages/man1/ssh-keygen.1.html
|
76
|
+
- ``ssh-keygen -l -E <alg> -f key.pub``
|
77
|
+
"""
|
78
|
+
if not public_key_decoded:
|
79
|
+
raise ValueError("No decoded public key provided")
|
80
|
+
|
81
|
+
if not isinstance(public_key_decoded, bytes):
|
82
|
+
raise ValueError("Provided public key should be bytes")
|
83
|
+
|
84
|
+
if public_key_decoded[0:3] != b"\x00\x00\x00":
|
85
|
+
raise ValueError("Provided value does not look like a public key")
|
86
|
+
|
87
|
+
digest_md5 = md5(public_key_decoded).digest()
|
88
|
+
digest_sha1 = sha1(public_key_decoded).digest()
|
89
|
+
digest_sha256 = sha256(public_key_decoded).digest()
|
90
|
+
|
91
|
+
if ssh_keygen_format:
|
92
|
+
fingerprint_sha1 = base64.b64encode(digest_sha1).rstrip(b"=").decode()
|
93
|
+
fingerprint_sha256 = base64.b64encode(digest_sha256).rstrip(b"=").decode()
|
94
|
+
else:
|
95
|
+
fingerprint_sha1 = digest_sha1.hex()
|
96
|
+
fingerprint_sha256 = digest_sha256.hex()
|
97
|
+
|
98
|
+
return digest_md5.hex(), fingerprint_sha1, fingerprint_sha256
|
@@ -1,7 +1,8 @@
|
|
1
1
|
import re
|
2
|
-
from
|
2
|
+
from pathlib import Path
|
3
3
|
from typing import Iterator
|
4
4
|
|
5
|
+
from dissect.target import Target
|
5
6
|
from dissect.target.exceptions import UnsupportedPluginError
|
6
7
|
from dissect.target.helpers.record import TargetRecordDescriptor
|
7
8
|
from dissect.target.helpers.utils import year_rollover_helper
|
@@ -23,17 +24,28 @@ RE_TS = re.compile(r"(\w+\s{1,2}\d+\s\d{2}:\d{2}:\d{2})")
|
|
23
24
|
RE_DAEMON = re.compile(r"^[^:]+:\d+:\d+[^\[\]:]+\s([^\[:]+)[\[|:]{1}")
|
24
25
|
RE_PID = re.compile(r"\w\[(\d+)\]")
|
25
26
|
RE_MSG = re.compile(r"[^:]+:\d+:\d+[^:]+:\s(.*)$")
|
27
|
+
RE_CLOUD_INIT_LINE = re.compile(r"(?P<ts>.*) - (?P<daemon>.*)\[(?P<log_level>\w+)\]\: (?P<message>.*)$")
|
26
28
|
|
27
29
|
|
28
30
|
class MessagesPlugin(Plugin):
|
31
|
+
def __init__(self, target: Target):
|
32
|
+
super().__init__(target)
|
33
|
+
self.log_files = set(self._find_log_files())
|
34
|
+
|
35
|
+
def _find_log_files(self) -> Iterator[Path]:
|
36
|
+
log_dirs = ["/var/log/", "/var/log/installer/"]
|
37
|
+
file_globs = ["syslog*", "messages*", "cloud-init.log*"]
|
38
|
+
for log_dir in log_dirs:
|
39
|
+
for glob in file_globs:
|
40
|
+
yield from self.target.fs.path(log_dir).glob(glob)
|
41
|
+
|
29
42
|
def check_compatible(self) -> None:
|
30
|
-
|
31
|
-
|
32
|
-
raise UnsupportedPluginError("No message files found")
|
43
|
+
if not self.log_files:
|
44
|
+
raise UnsupportedPluginError("No log files found")
|
33
45
|
|
34
46
|
@export(record=MessagesRecord)
|
35
47
|
def syslog(self) -> Iterator[MessagesRecord]:
|
36
|
-
"""Return contents of /var/log/messages
|
48
|
+
"""Return contents of /var/log/messages*, /var/log/syslog* and cloud-init logs.
|
37
49
|
|
38
50
|
See ``messages`` for more information.
|
39
51
|
"""
|
@@ -41,7 +53,7 @@ class MessagesPlugin(Plugin):
|
|
41
53
|
|
42
54
|
@export(record=MessagesRecord)
|
43
55
|
def messages(self) -> Iterator[MessagesRecord]:
|
44
|
-
"""Return contents of /var/log/messages
|
56
|
+
"""Return contents of /var/log/messages*, /var/log/syslog* and cloud-init logs.
|
45
57
|
|
46
58
|
Note: due to year rollover detection, the contents of the files are returned in reverse.
|
47
59
|
|
@@ -52,12 +64,16 @@ class MessagesPlugin(Plugin):
|
|
52
64
|
References:
|
53
65
|
- https://geek-university.com/linux/var-log-messages-file/
|
54
66
|
- https://www.geeksforgeeks.org/file-timestamps-mtime-ctime-and-atime-in-linux/
|
67
|
+
- https://cloudinit.readthedocs.io/en/latest/development/logging.html#logging-command-output
|
55
68
|
"""
|
56
69
|
|
57
70
|
tzinfo = self.target.datetime.tzinfo
|
58
71
|
|
59
|
-
|
60
|
-
|
72
|
+
for log_file in self.log_files:
|
73
|
+
if "cloud-init" in log_file.name:
|
74
|
+
yield from self._parse_cloud_init_log(log_file)
|
75
|
+
continue
|
76
|
+
|
61
77
|
for ts, line in year_rollover_helper(log_file, RE_TS, DEFAULT_TS_LOG_FORMAT, tzinfo):
|
62
78
|
daemon = dict(enumerate(RE_DAEMON.findall(line))).get(0)
|
63
79
|
pid = dict(enumerate(RE_PID.findall(line))).get(0)
|
@@ -71,3 +87,32 @@ class MessagesPlugin(Plugin):
|
|
71
87
|
source=log_file,
|
72
88
|
_target=self.target,
|
73
89
|
)
|
90
|
+
|
91
|
+
def _parse_cloud_init_log(self, log_file: Path) -> Iterator[MessagesRecord]:
|
92
|
+
"""Parse a cloud-init.log file.
|
93
|
+
|
94
|
+
Lines are structured in the following format:
|
95
|
+
``YYYY-MM-DD HH:MM:SS,000 - dhcp.py[DEBUG]: Received dhcp lease on IFACE for IP/MASK``
|
96
|
+
|
97
|
+
NOTE: ``cloud-init-output.log`` files are not supported as they do not contain structured logs.
|
98
|
+
|
99
|
+
Args:
|
100
|
+
``log_file``: path to cloud-init.log file.
|
101
|
+
|
102
|
+
Returns: ``MessagesRecord``
|
103
|
+
"""
|
104
|
+
for line in log_file.open("rt").readlines():
|
105
|
+
if line := line.strip():
|
106
|
+
if match := RE_CLOUD_INIT_LINE.match(line):
|
107
|
+
match = match.groupdict()
|
108
|
+
yield MessagesRecord(
|
109
|
+
ts=match["ts"].split(",")[0],
|
110
|
+
daemon=match["daemon"],
|
111
|
+
pid=None,
|
112
|
+
message=match["message"],
|
113
|
+
source=log_file,
|
114
|
+
_target=self.target,
|
115
|
+
)
|
116
|
+
else:
|
117
|
+
self.target.log.warning("Could not match cloud-init log line")
|
118
|
+
self.target.log.debug("No match for line '%s'", line)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: dissect.target
|
3
|
-
Version: 3.17.
|
3
|
+
Version: 3.17.dev27
|
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
|
@@ -57,7 +57,7 @@ dissect/target/helpers/loaderutil.py,sha256=kiyMWra_gVxfNSGwLlgxLcuuqAYuCMDc5NiC
|
|
57
57
|
dissect/target/helpers/localeutil.py,sha256=Y4Fh4jDSGfm5356xSLMriUCN8SZP_FAHg_iodkAxNq4,1504
|
58
58
|
dissect/target/helpers/mount.py,sha256=JxhUYyEbDnHfzPpfuWy4nV9OwCJPoDSGdHHNiyvd_l0,3949
|
59
59
|
dissect/target/helpers/mui.py,sha256=i-7XoHbu4WO2fYapK9yGAMW04rFlgRispknc1KQIS5Q,22258
|
60
|
-
dissect/target/helpers/network_managers.py,sha256=
|
60
|
+
dissect/target/helpers/network_managers.py,sha256=uRh_P8ICbKke2N7eFJ6AS2-I5DmIRiaQUlxR7oqxPaU,24975
|
61
61
|
dissect/target/helpers/polypath.py,sha256=h8p7m_OCNiQljGwoZh5Aflr9H2ot6CZr6WKq1OSw58o,2175
|
62
62
|
dissect/target/helpers/protobuf.py,sha256=NwKrZD4q9v7J8GnZX9gbzMUMV5pR78eAV17jgWOz_EY,1730
|
63
63
|
dissect/target/helpers/record.py,sha256=lWl7k2Mp9Axllm0tXzPGJx2zj2zONsyY_p5g424T0Lc,4826
|
@@ -133,10 +133,10 @@ dissect/target/plugins/apps/remoteaccess/teamviewer.py,sha256=SiEH36HM2NvdPuCjfL
|
|
133
133
|
dissect/target/plugins/apps/shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
134
134
|
dissect/target/plugins/apps/shell/powershell.py,sha256=biPSMRWxPI6kRqP0-75yMtrw0Ti2Bzfl_xI3xbmmF48,2641
|
135
135
|
dissect/target/plugins/apps/ssh/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
136
|
-
dissect/target/plugins/apps/ssh/openssh.py,sha256=
|
136
|
+
dissect/target/plugins/apps/ssh/openssh.py,sha256=yt3bX93Q9wfF25_vG9APMwfZWUUqCPyLlVJdhu20syI,7250
|
137
137
|
dissect/target/plugins/apps/ssh/opensshd.py,sha256=DaXKdgGF3GYHHA4buEvphcm6FF4C8YFjgD96Dv6rRnM,5510
|
138
|
-
dissect/target/plugins/apps/ssh/putty.py,sha256=
|
139
|
-
dissect/target/plugins/apps/ssh/ssh.py,sha256=
|
138
|
+
dissect/target/plugins/apps/ssh/putty.py,sha256=bTX6ZU6zsc78zBdsBGUotc_ek_E1a7HSowoqD1y4PzA,9927
|
139
|
+
dissect/target/plugins/apps/ssh/ssh.py,sha256=tTA87u0B8yY1yVCPV0VJdRUct6ggkir_pIziP-eKnVo,3009
|
140
140
|
dissect/target/plugins/apps/vpn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
141
141
|
dissect/target/plugins/apps/vpn/openvpn.py,sha256=d-DGINTIHP_bvv3T09ZwbezHXGctvCyAhJ482m2_-a0,7654
|
142
142
|
dissect/target/plugins/apps/vpn/wireguard.py,sha256=SoAMED_bwWJQ3nci5qEY-qV4wJKSSDZQ8K7DoJRYq0k,6521
|
@@ -247,7 +247,7 @@ dissect/target/plugins/os/unix/log/audit.py,sha256=OjorWTmCFvCI5RJq6m6WNW0Lhb-po
|
|
247
247
|
dissect/target/plugins/os/unix/log/auth.py,sha256=l7gCuRdvv9gL0U1N0yrR9hVsMnr4t_k4t-n-f6PrOxg,2388
|
248
248
|
dissect/target/plugins/os/unix/log/journal.py,sha256=eiNNVLmKWFj4dTQX8PNRNgKpVwzQWEHEsKyYfGUAPXQ,17376
|
249
249
|
dissect/target/plugins/os/unix/log/lastlog.py,sha256=eL_dbB1sPoy0tyavIjT457ZLVfXcCr17GiwDrMEEh8A,2458
|
250
|
-
dissect/target/plugins/os/unix/log/messages.py,sha256=
|
250
|
+
dissect/target/plugins/os/unix/log/messages.py,sha256=CXA-SkMPLaCgnTQg9nzII-7tO8Il_ENQmuYvDxo33rI,4698
|
251
251
|
dissect/target/plugins/os/unix/log/utmp.py,sha256=21tvzG977LqzRShV6uAoU-83WDcLUrI_Tv__2ZVi9rw,7756
|
252
252
|
dissect/target/plugins/os/windows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
253
253
|
dissect/target/plugins/os/windows/_os.py,sha256=EA9B9Rgb1C9NMvlX3gXhTRFXYaI6zrrKRg0OYq4v1ts,12589
|
@@ -336,10 +336,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
|
|
336
336
|
dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
|
337
337
|
dissect/target/volumes/md.py,sha256=j1K1iKmspl0C_OJFc7-Q1BMWN2OCC5EVANIgVlJ_fIE,1673
|
338
338
|
dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
|
339
|
-
dissect.target-3.17.
|
340
|
-
dissect.target-3.17.
|
341
|
-
dissect.target-3.17.
|
342
|
-
dissect.target-3.17.
|
343
|
-
dissect.target-3.17.
|
344
|
-
dissect.target-3.17.
|
345
|
-
dissect.target-3.17.
|
339
|
+
dissect.target-3.17.dev27.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
|
340
|
+
dissect.target-3.17.dev27.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
341
|
+
dissect.target-3.17.dev27.dist-info/METADATA,sha256=3-kTMZehcHT31jjm50J9_Msj1Pw6LqWUMsiMaSaLiBY,11300
|
342
|
+
dissect.target-3.17.dev27.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
343
|
+
dissect.target-3.17.dev27.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
|
344
|
+
dissect.target-3.17.dev27.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
|
345
|
+
dissect.target-3.17.dev27.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
{dissect.target-3.17.dev25.dist-info → dissect.target-3.17.dev27.dist-info}/entry_points.txt
RENAMED
File without changes
|
File without changes
|