dissect.target 3.17.dev25__py3-none-any.whl → 3.17.dev27__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- 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
|