dissect.target 3.19.dev12__py3-none-any.whl → 3.19.dev14__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,91 +1,111 @@
1
- from datetime import datetime
1
+ import re
2
+ from datetime import datetime, timezone
3
+ from typing import Iterator
2
4
 
3
5
  from dissect.target.exceptions import UnsupportedPluginError
6
+ from dissect.target.helpers.descriptor_extensions import UserRecordDescriptorExtension
7
+ from dissect.target.helpers.fsutil import TargetPath
8
+ from dissect.target.helpers.record import create_extended_descriptor
4
9
  from dissect.target.plugin import export
5
10
  from dissect.target.plugins.apps.remoteaccess.remoteaccess import (
11
+ GENERIC_LOG_RECORD_FIELDS,
6
12
  RemoteAccessPlugin,
7
- RemoteAccessRecord,
8
13
  )
14
+ from dissect.target.plugins.general.users import UserDetails
9
15
 
10
16
 
11
17
  class AnydeskPlugin(RemoteAccessPlugin):
12
- """
13
- Anydesk plugin.
14
- """
18
+ """Anydesk plugin."""
15
19
 
16
20
  __namespace__ = "anydesk"
17
21
 
18
22
  # Anydesk logs when installed as a service
19
23
  SERVICE_GLOBS = [
20
- "/sysvol/ProgramData/AnyDesk/*.trace", # Standard client >= Windows 7
21
- "/sysvol/ProgramData/AnyDesk/ad_*/*.trace", # Custom client >= Windows 7
22
- "/var/log/anydesk*.trace", # Standard/Custom client Linux/MacOS
24
+ # Standard client >= Windows 7
25
+ "sysvol/ProgramData/AnyDesk/*.trace",
26
+ # Custom client >= Windows 7
27
+ "sysvol/ProgramData/AnyDesk/ad_*/*.trace",
28
+ # Windows XP / 2003
29
+ "sysvol/Documents and Settings/Public/AnyDesk/*.trace",
30
+ "sysvol/Documents and Settings/Public/AnyDesk/ad_*/*.trace",
31
+ # Standard/Custom client Linux/MacOS
32
+ "var/log/anydesk*/*.trace",
23
33
  ]
24
34
 
25
35
  # User specific Anydesk logs
26
36
  USER_GLOBS = [
27
- "appdata/roaming/AnyDesk/*.trace", # Standard client Windows
28
- "appdata/roaming/AnyDesk/ad_*/*.trace", # Custom client Windows
29
- ".anydesk/*.trace", # Standard client Linux/MacOS
30
- ".anydesk_ad_*/*.trace", # Custom client Linux/MacOS
37
+ # Standard client Windows
38
+ "AppData/Roaming/AnyDesk/*.trace",
39
+ # Custom client Windows
40
+ "AppData/Roaming/AnyDesk/ad_*/*.trace",
41
+ # Windows XP / 2003
42
+ "AppData/AnyDesk/*.trace",
43
+ # Standard client Linux/MacOS
44
+ ".anydesk/*.trace",
45
+ # Custom client Linux/MacOS
46
+ ".anydesk_ad_*/*.trace",
31
47
  ]
32
48
 
49
+ RemoteAccessLogRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
50
+ "remoteaccess/anydesk/log", GENERIC_LOG_RECORD_FIELDS
51
+ )
52
+
33
53
  def __init__(self, target):
34
54
  super().__init__(target)
35
55
 
36
- self.logfiles = []
56
+ self.trace_files: set[tuple[TargetPath, UserDetails]] = set()
37
57
 
38
- # Check service globs
58
+ # Service globs
39
59
  user = None
40
- for log_glob in self.SERVICE_GLOBS:
41
- for logfile in self.target.fs.glob(log_glob):
42
- self.logfiles.append([logfile, user])
60
+ for trace_glob in self.SERVICE_GLOBS:
61
+ for trace_file in self.target.fs.path().glob(trace_glob):
62
+ self.trace_files.add((trace_file, user))
43
63
 
44
- # Anydesk logs when as user
64
+ # User globs
45
65
  for user_details in self.target.user_details.all_with_home():
46
- for log_glob in self.USER_GLOBS:
47
- for logfile in user_details.home_path.glob(log_glob):
48
- self.logfiles.append([logfile, user_details.user])
66
+ for trace_glob in self.USER_GLOBS:
67
+ for trace_file in user_details.home_path.glob(trace_glob):
68
+ self.trace_files.add((trace_file, user_details.user))
49
69
 
50
70
  def check_compatible(self) -> None:
51
- if not (len(self.logfiles)):
52
- raise UnsupportedPluginError("No Anydesk logs found")
71
+ if not self.trace_files:
72
+ raise UnsupportedPluginError("No Anydesk trace files found on target")
53
73
 
54
- @export(record=RemoteAccessRecord)
55
- def logs(self):
56
- """Return the content of the AnyDesk logs.
74
+ @export(record=RemoteAccessLogRecord)
75
+ def logs(self) -> Iterator[RemoteAccessLogRecord]:
76
+ """Parse AnyDesk trace files.
57
77
 
58
78
  AnyDesk is a remote desktop application and can be used by adversaries to get (persistent) access to a machine.
59
- Log files (.trace files) are retrieved from various location based on OS and client type.
79
+ Log files (.trace files) can be stored on various locations, based on target OS and client type.
80
+ Timestamps in trace files do not carry a time zone designator (TZD) but are in fact UTC.
60
81
 
61
82
  References:
62
83
  - https://www.inversecos.com/2021/02/forensic-analysis-of-anydesk-logs.html
63
84
  - https://support.anydesk.com/knowledge/trace-files#trace-file-locations
64
85
  """
65
- for logfile, user in self.logfiles:
66
- logfile = self.target.fs.path(logfile)
67
-
68
- for line in logfile.open("rt"):
86
+ for trace_file, user in self.trace_files:
87
+ for line in trace_file.open("rt", errors="backslashreplace"):
69
88
  line = line.strip()
70
89
 
71
- # Skip empty lines
72
- if not line:
73
- continue
74
-
75
- if "* * * * * * * * * * * * * *" in line:
90
+ if not line or "* * * * * * * * * * * * * *" in line:
76
91
  continue
77
92
 
78
- level, ts_day, ts_time, description = line.split(" ", 3)
79
- description = f"{level} {description}"
80
- ts_time = ts_time.split(".")[0]
81
-
82
- timestamp = datetime.strptime(f"{ts_day} {ts_time}", "%Y-%m-%d %H:%M:%S")
83
-
84
- yield RemoteAccessRecord(
85
- ts=timestamp,
86
- tool="anydesk",
87
- logfile=str(logfile),
88
- description=description,
89
- _target=self.target,
90
- _user=user,
91
- )
93
+ try:
94
+ level, ts_date, ts_time, message = line.split(" ", 3)
95
+
96
+ timestamp = datetime.strptime(f"{ts_date} {ts_time}", "%Y-%m-%d %H:%M:%S.%f").replace(
97
+ tzinfo=timezone.utc
98
+ )
99
+ message = re.sub(r"\s\s+", " ", f"{level} {message}")
100
+
101
+ yield self.RemoteAccessLogRecord(
102
+ ts=timestamp,
103
+ message=message,
104
+ source=trace_file,
105
+ _target=self.target,
106
+ _user=user,
107
+ )
108
+
109
+ except ValueError as e:
110
+ self.target.log.warning("Could not parse log line in file %s: '%s'", trace_file, line)
111
+ self.target.log.debug("", exc_info=e)
@@ -2,14 +2,14 @@ from dissect.target.helpers.descriptor_extensions import UserRecordDescriptorExt
2
2
  from dissect.target.helpers.record import create_extended_descriptor
3
3
  from dissect.target.plugin import NamespacePlugin
4
4
 
5
- RemoteAccessRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
6
- "application/log/remoteaccess",
7
- [
8
- ("datetime", "ts"),
9
- ("string", "tool"),
10
- ("path", "logfile"),
11
- ("string", "description"),
12
- ],
5
+ GENERIC_LOG_RECORD_FIELDS = [
6
+ ("datetime", "ts"),
7
+ ("string", "message"),
8
+ ("path", "source"),
9
+ ]
10
+
11
+ RemoteAccessLogRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
12
+ "remoteaccess/log", GENERIC_LOG_RECORD_FIELDS
13
13
  )
14
14
 
15
15
 
@@ -1,60 +1,72 @@
1
1
  import re
2
- from datetime import datetime
2
+ from datetime import datetime, timezone
3
+ from typing import Iterator
3
4
 
4
5
  from dissect.target.exceptions import UnsupportedPluginError
6
+ from dissect.target.helpers.descriptor_extensions import UserRecordDescriptorExtension
7
+ from dissect.target.helpers.fsutil import TargetPath
8
+ from dissect.target.helpers.record import create_extended_descriptor
5
9
  from dissect.target.plugin import export
6
10
  from dissect.target.plugins.apps.remoteaccess.remoteaccess import (
11
+ GENERIC_LOG_RECORD_FIELDS,
7
12
  RemoteAccessPlugin,
8
- RemoteAccessRecord,
9
13
  )
14
+ from dissect.target.plugins.general.users import UserDetails
10
15
 
11
16
  START_PATTERN = re.compile(r"^(\d{2}|\d{4})/")
12
17
 
13
18
 
14
- class TeamviewerPlugin(RemoteAccessPlugin):
15
- """
16
- Teamviewer plugin.
19
+ class TeamViewerPlugin(RemoteAccessPlugin):
20
+ """TeamViewer client plugin.
21
+
22
+ Resources:
23
+ - https://teamviewer.com/en/global/support/knowledge-base/teamviewer-classic/contact-support/find-your-log-files
24
+ - https://www.systoolsgroup.com/forensics/teamviewer/
25
+ - https://benleeyr.wordpress.com/2020/05/19/teamviewer-forensics-tested-on-v15/
17
26
  """
18
27
 
19
28
  __namespace__ = "teamviewer"
20
29
 
21
- # Teamviewer log when service (Windows)
22
- GLOBS = [
30
+ SYSTEM_GLOBS = [
23
31
  "sysvol/Program Files/TeamViewer/*.log",
24
32
  "sysvol/Program Files (x86)/TeamViewer/*.log",
25
33
  ]
26
34
 
35
+ USER_GLOBS = [
36
+ "AppData/Roaming/TeamViewer/teamviewer*_logfile.log",
37
+ ]
38
+
39
+ RemoteAccessLogRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
40
+ "remoteaccess/teamviewer/log", GENERIC_LOG_RECORD_FIELDS
41
+ )
42
+
27
43
  def __init__(self, target):
28
44
  super().__init__(target)
29
45
 
30
- self.logfiles = []
46
+ self.logfiles: list[list[TargetPath, UserDetails]] = []
31
47
 
32
- # Check service globs
33
- user = None
34
- for log_glob in self.GLOBS:
48
+ # Find system service log files.
49
+ for log_glob in self.SYSTEM_GLOBS:
35
50
  for logfile in self.target.fs.glob(log_glob):
36
- self.logfiles.append([logfile, user])
51
+ self.logfiles.append([logfile, None])
37
52
 
38
- # Teamviewer logs when as user (Windows)
53
+ # Find user log files.
39
54
  for user_details in self.target.user_details.all_with_home():
40
- for logfile in user_details.home_path.glob("appdata/roaming/teamviewer/teamviewer*_logfile.log"):
41
- self.logfiles.append([logfile, user_details.user])
55
+ for log_glob in self.USER_GLOBS:
56
+ for logfile in user_details.home_path.glob(log_glob):
57
+ self.logfiles.append([logfile, user_details])
42
58
 
43
59
  def check_compatible(self) -> None:
44
60
  if not len(self.logfiles):
45
61
  raise UnsupportedPluginError("No Teamviewer logs found")
46
62
 
47
- @export(record=RemoteAccessRecord)
48
- def logs(self):
49
- """Return the content of the TeamViewer logs.
50
-
51
- TeamViewer is a commercial remote desktop application. An adversary may use it to gain persistence on a
52
- system.
63
+ @export(record=RemoteAccessLogRecord)
64
+ def logs(self) -> Iterator[RemoteAccessLogRecord]:
65
+ """Yield TeamViewer client logs.
53
66
 
54
- References:
55
- - https://www.teamviewer.com/nl/
67
+ TeamViewer is a commercial remote desktop application. An adversary may use it to gain persistence on a system.
56
68
  """
57
- for logfile, user in self.logfiles:
69
+ for logfile, user_details in self.logfiles:
58
70
  logfile = self.target.fs.path(logfile)
59
71
 
60
72
  start_date = None
@@ -83,7 +95,7 @@ class TeamviewerPlugin(RemoteAccessPlugin):
83
95
  if not re.match(START_PATTERN, line):
84
96
  continue
85
97
 
86
- ts_day, ts_time, description = line.split(" ", 2)
98
+ ts_day, ts_time, message = line.split(" ", 2)
87
99
  ts_time = ts_time.split(".")[0]
88
100
 
89
101
  # Correct for use of : as millisecond separator
@@ -99,13 +111,14 @@ class TeamviewerPlugin(RemoteAccessPlugin):
99
111
  if ts_day.count("/") == 2 and len(ts_day.split("/")[0]) == 2:
100
112
  ts_day = "20" + ts_day
101
113
 
102
- timestamp = datetime.strptime(f"{ts_day} {ts_time}", "%Y/%m/%d %H:%M:%S")
114
+ timestamp = datetime.strptime(f"{ts_day} {ts_time}", "%Y/%m/%d %H:%M:%S").replace(
115
+ tzinfo=timezone.utc
116
+ )
103
117
 
104
- yield RemoteAccessRecord(
105
- tool="teamviewer",
118
+ yield self.RemoteAccessLogRecord(
106
119
  ts=timestamp,
107
- logfile=str(logfile),
108
- description=description,
120
+ message=message,
121
+ source=logfile,
109
122
  _target=self.target,
110
- _user=user,
123
+ _user=user_details.user if user_details else None,
111
124
  )
@@ -40,12 +40,18 @@ class UnixPlugin(OSPlugin):
40
40
  @export(record=UnixUserRecord)
41
41
  @arg("--sessions", action="store_true", help="Parse syslog for recent user sessions")
42
42
  def users(self, sessions: bool = False) -> Iterator[UnixUserRecord]:
43
- """Recover users from /etc/passwd, /etc/master.passwd or /var/log/syslog session logins."""
43
+ """Yield unix user records from passwd files or syslog session logins.
44
+
45
+ Resources:
46
+ - https://manpages.ubuntu.com/manpages/oracular/en/man5/passwd.5.html
47
+ """
48
+
49
+ PASSWD_FILES = ["/etc/passwd", "/etc/passwd-", "/etc/master.passwd"]
44
50
 
45
51
  seen_users = set()
46
52
 
47
53
  # Yield users found in passwd files.
48
- for passwd_file in ["/etc/passwd", "/etc/master.passwd"]:
54
+ for passwd_file in PASSWD_FILES:
49
55
  if (path := self.target.fs.path(passwd_file)).exists():
50
56
  for line in path.open("rt"):
51
57
  line = line.strip()
@@ -53,7 +59,12 @@ class UnixPlugin(OSPlugin):
53
59
  continue
54
60
 
55
61
  pwent = dict(enumerate(line.split(":")))
56
- seen_users.add((pwent.get(0), pwent.get(5), pwent.get(6)))
62
+
63
+ current_user = (pwent.get(0), pwent.get(5), pwent.get(6))
64
+ if current_user in seen_users:
65
+ continue
66
+
67
+ seen_users.add(current_user)
57
68
  yield UnixUserRecord(
58
69
  name=pwent.get(0),
59
70
  passwd=pwent.get(1),
@@ -29,39 +29,55 @@ class ShadowPlugin(Plugin):
29
29
  if not self.target.fs.path("/etc/shadow").exists():
30
30
  raise UnsupportedPluginError("No shadow file found")
31
31
 
32
+ SHADOW_FILES = ["/etc/shadow", "/etc/shadow-"]
33
+
32
34
  @export(record=UnixShadowRecord)
33
35
  def passwords(self) -> Iterator[UnixShadowRecord]:
34
- """Recover shadow records from /etc/shadow files."""
35
-
36
- if (path := self.target.fs.path("/etc/shadow")).exists():
37
- for line in path.open("rt"):
38
- line = line.strip()
39
- if line == "" or line.startswith("#"):
40
- continue
41
-
42
- shent = dict(enumerate(line.split(":")))
43
- crypt = extract_crypt_details(shent)
44
-
45
- # do not return a shadow record if we have no hash
46
- if crypt.get("hash") is None or crypt.get("hash") == "":
47
- continue
48
-
49
- yield UnixShadowRecord(
50
- name=shent.get(0),
51
- crypt=shent.get(1),
52
- algorithm=crypt.get("algo"),
53
- crypt_param=crypt.get("param"),
54
- salt=crypt.get("salt"),
55
- hash=crypt.get("hash"),
56
- last_change=shent.get(2),
57
- min_age=shent.get(3),
58
- max_age=shent.get(4),
59
- warning_period=shent.get(5),
60
- inactivity_period=shent.get(6),
61
- expiration_date=shent.get(7),
62
- unused_field=shent.get(8),
63
- _target=self.target,
64
- )
36
+ """Yield shadow records from /etc/shadow files.
37
+
38
+ Resources:
39
+ - https://manpages.ubuntu.com/manpages/oracular/en/man5/passwd.5.html#file:/etc/shadow
40
+ """
41
+
42
+ seen_hashes = set()
43
+
44
+ for shadow_file in self.SHADOW_FILES:
45
+ if (path := self.target.fs.path(shadow_file)).exists():
46
+ for line in path.open("rt"):
47
+ line = line.strip()
48
+ if line == "" or line.startswith("#"):
49
+ continue
50
+
51
+ shent = dict(enumerate(line.split(":")))
52
+ crypt = extract_crypt_details(shent)
53
+
54
+ # do not return a shadow record if we have no hash
55
+ if crypt.get("hash") is None or crypt.get("hash") == "":
56
+ continue
57
+
58
+ # prevent duplicate user hashes
59
+ current_hash = (shent.get(0), crypt.get("hash"))
60
+ if current_hash in seen_hashes:
61
+ continue
62
+
63
+ seen_hashes.add(current_hash)
64
+
65
+ yield UnixShadowRecord(
66
+ name=shent.get(0),
67
+ crypt=shent.get(1),
68
+ algorithm=crypt.get("algo"),
69
+ crypt_param=crypt.get("param"),
70
+ salt=crypt.get("salt"),
71
+ hash=crypt.get("hash"),
72
+ last_change=shent.get(2),
73
+ min_age=shent.get(3),
74
+ max_age=shent.get(4),
75
+ warning_period=shent.get(5),
76
+ inactivity_period=shent.get(6),
77
+ expiration_date=shent.get(7),
78
+ unused_field=shent.get(8),
79
+ _target=self.target,
80
+ )
65
81
 
66
82
 
67
83
  def extract_crypt_details(shent: dict) -> dict:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.19.dev12
3
+ Version: 3.19.dev14
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
@@ -128,9 +128,9 @@ dissect/target/plugins/apps/browser/iexplore.py,sha256=g_xw0toaiyjevxO8g9XPCOqc-
128
128
  dissect/target/plugins/apps/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
129
129
  dissect/target/plugins/apps/container/docker.py,sha256=KxQRbKGgxkf3YFBMa7fjeJ7qo8qjFys7zEmfQhDTnLw,15305
130
130
  dissect/target/plugins/apps/remoteaccess/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
131
- dissect/target/plugins/apps/remoteaccess/anydesk.py,sha256=lHtgINWXfVpPuCTRyQmT2ZO-1vkoqiXZ7coj8cZ8p4c,3185
132
- dissect/target/plugins/apps/remoteaccess/remoteaccess.py,sha256=UQDmDC4Y-KxYl_8kaAh6SG_BLJZ6SeGnxG0gyD8tzaE,833
133
- dissect/target/plugins/apps/remoteaccess/teamviewer.py,sha256=SiEH36HM2NvdPuCjfLjQcMDsluwkcHp_3io9SoY8qFk,4032
131
+ dissect/target/plugins/apps/remoteaccess/anydesk.py,sha256=IdijK3F6ppaB_IgKL-xDljlEbb8l9S2U0xSWKqK9xRs,4294
132
+ dissect/target/plugins/apps/remoteaccess/remoteaccess.py,sha256=DWXkRDVUpFr1icK2fYwSXdZD204Xz0yRuO7rcJOwIwc,825
133
+ dissect/target/plugins/apps/remoteaccess/teamviewer.py,sha256=0nGjgbzzrhESr1PeiXlGxYQ66-aOATO59CnVSwcGn4E,4889
134
134
  dissect/target/plugins/apps/shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
135
135
  dissect/target/plugins/apps/shell/powershell.py,sha256=biPSMRWxPI6kRqP0-75yMtrw0Ti2Bzfl_xI3xbmmF48,2641
136
136
  dissect/target/plugins/apps/ssh/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -183,7 +183,7 @@ dissect/target/plugins/general/scrape.py,sha256=Fz7BNXflvuxlnVulyyDhLpyU8D_hJdH6
183
183
  dissect/target/plugins/general/users.py,sha256=cQXPQ2XbkPjckCPHYTUW4JEhYN0_CT8JI8hJPZn3qSs,3030
184
184
  dissect/target/plugins/os/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
185
185
  dissect/target/plugins/os/unix/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
186
- dissect/target/plugins/os/unix/_os.py,sha256=VQHx8PDhJ0NHzNuo3RIN3DGXkLqpGXbQe8M5ZbtI5nM,14277
186
+ dissect/target/plugins/os/unix/_os.py,sha256=GcbP8HbK1XtwYFGbl8x0BdfoLAC2ROv9xieeFGI5dWM,14557
187
187
  dissect/target/plugins/os/unix/cronjobs.py,sha256=2ssj97UVJueyATVl7NMJmqd9uHflQ2tXUqdOCFIEje8,3182
188
188
  dissect/target/plugins/os/unix/datetime.py,sha256=gKfBdPyUirt3qmVYfOJ1oZXRPn8wRzssbZxR_ARrtk8,1518
189
189
  dissect/target/plugins/os/unix/etc.py,sha256=HoPEC1hxqurSnAXQAK-jf_HxdBIDe-1z_qSw_n-ViI4,258
@@ -191,7 +191,7 @@ dissect/target/plugins/os/unix/generic.py,sha256=6_MJrV1LbIxNQJwAZR0HEQljoxwF5BP
191
191
  dissect/target/plugins/os/unix/history.py,sha256=ptNGHkHOLJ5bE4r1PqtkQFcQHqzS6-qe5ms1tTGOJp8,6620
192
192
  dissect/target/plugins/os/unix/locale.py,sha256=V3R7mEyrH3f-h7SGAucByaYYDA2SIil9Qb-s3dPmDEA,3961
193
193
  dissect/target/plugins/os/unix/packagemanager.py,sha256=Wm2AAJOD_B3FAcZNXgWtSm_YwbvrHBYOP8bPmOXNjG4,2427
194
- dissect/target/plugins/os/unix/shadow.py,sha256=TvN04uzFnUttNMZAa6_1XdXSP-8V6ztbZNoetDvfD0w,3535
194
+ dissect/target/plugins/os/unix/shadow.py,sha256=W6W6rMru7IVnuBc6sl5wsRWTOrJdS1s7_2_q7QRf7Is,4148
195
195
  dissect/target/plugins/os/unix/bsd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
196
196
  dissect/target/plugins/os/unix/bsd/_os.py,sha256=e5rttTOFOmd7e2HqP9ZZFMEiPLBr-8rfH0XH1IIeroQ,1372
197
197
  dissect/target/plugins/os/unix/bsd/citrix/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -344,10 +344,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
344
344
  dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
345
345
  dissect/target/volumes/md.py,sha256=j1K1iKmspl0C_OJFc7-Q1BMWN2OCC5EVANIgVlJ_fIE,1673
346
346
  dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
347
- dissect.target-3.19.dev12.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
348
- dissect.target-3.19.dev12.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
349
- dissect.target-3.19.dev12.dist-info/METADATA,sha256=UR_OR6Mke9csuzDPtguApwOU8mClzRRkkWmmiqNv364,12719
350
- dissect.target-3.19.dev12.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
351
- dissect.target-3.19.dev12.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
352
- dissect.target-3.19.dev12.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
353
- dissect.target-3.19.dev12.dist-info/RECORD,,
347
+ dissect.target-3.19.dev14.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
348
+ dissect.target-3.19.dev14.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
349
+ dissect.target-3.19.dev14.dist-info/METADATA,sha256=QY-pX_0ABwGcA1nW1mG6NJZ_K2DoaG6-lOaFvH-ZORI,12719
350
+ dissect.target-3.19.dev14.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
351
+ dissect.target-3.19.dev14.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
352
+ dissect.target-3.19.dev14.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
353
+ dissect.target-3.19.dev14.dist-info/RECORD,,