dissect.target 3.20.dev38__py3-none-any.whl → 3.20.dev40__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.
@@ -185,3 +185,24 @@ MacInterfaceRecord = TargetRecordDescriptor(
185
185
  ("boolean", "dhcp"),
186
186
  ],
187
187
  )
188
+
189
+
190
+ COMMON_APPLICATION_FIELDS = [
191
+ ("datetime", "ts_modified"),
192
+ ("datetime", "ts_installed"),
193
+ ("string", "name"),
194
+ ("string", "version"),
195
+ ("string", "author"),
196
+ ("string", "type"),
197
+ ("path", "path"),
198
+ ]
199
+
200
+ UnixApplicationRecord = TargetRecordDescriptor(
201
+ "unix/application",
202
+ COMMON_APPLICATION_FIELDS,
203
+ )
204
+
205
+ WindowsApplicationRecord = TargetRecordDescriptor(
206
+ "windows/application",
207
+ COMMON_APPLICATION_FIELDS,
208
+ )
@@ -310,6 +310,7 @@ class VirtualKey(RegistryKey):
310
310
  self._class_name = class_name
311
311
  self._values: dict[str, RegistryValue] = {}
312
312
  self._subkeys: dict[str, RegistryKey] = {}
313
+ self._timestamp: datetime = None
313
314
  self.top: RegistryKey = None
314
315
  super().__init__(hive=hive)
315
316
 
@@ -339,11 +340,19 @@ class VirtualKey(RegistryKey):
339
340
  return self._path
340
341
 
341
342
  @property
342
- def timestamp(self) -> datetime:
343
+ def timestamp(self) -> datetime | None:
343
344
  if self.top:
344
345
  return self.top.timestamp
346
+
347
+ if self._timestamp:
348
+ return self._timestamp
349
+
345
350
  return None
346
351
 
352
+ @timestamp.setter
353
+ def timestamp(self, ts: datetime) -> None:
354
+ self._timestamp = ts
355
+
347
356
  def subkey(self, subkey: str) -> RegistryKey:
348
357
  try:
349
358
  return self._subkeys[subkey.lower()]
@@ -0,0 +1,23 @@
1
+ from dissect.target.plugin import NamespacePlugin, export
2
+
3
+ COMMON_EDITOR_FIELDS = [
4
+ ("datetime", "ts"),
5
+ ("string", "editor"),
6
+ ("path", "source"),
7
+ ]
8
+
9
+
10
+ class EditorPlugin(NamespacePlugin):
11
+ """Editor plugin."""
12
+
13
+ __namespace__ = "editor"
14
+
15
+ @export
16
+ def extensions(self) -> None:
17
+ """Yields installed extensions."""
18
+ raise NotImplementedError
19
+
20
+ @export
21
+ def history(self) -> None:
22
+ """Yields history of files."""
23
+ raise NotImplementedError
@@ -16,11 +16,8 @@ from dissect.target.helpers.record import (
16
16
  WindowsUserRecord,
17
17
  create_extended_descriptor,
18
18
  )
19
- from dissect.target.plugin import export
20
- from dissect.target.plugins.apps.texteditor.texteditor import (
21
- GENERIC_TAB_CONTENTS_RECORD_FIELDS,
22
- TexteditorPlugin,
23
- )
19
+ from dissect.target.plugin import alias, export
20
+ from dissect.target.plugins.apps.editor.editor import COMMON_EDITOR_FIELDS, EditorPlugin
24
21
  from dissect.target.target import Target
25
22
 
26
23
  # Thanks to @Nordgaren, @daddycocoaman, @JustArion and @ogmini for their suggestions and feedback in the PR
@@ -94,16 +91,25 @@ struct options_v2 {
94
91
  };
95
92
  """
96
93
 
97
- WINDOWS_SAVED_TABS_EXTRA_FIELDS = [("datetime", "modification_time"), ("digest", "hashes"), ("path", "saved_path")]
94
+ GENERIC_TAB_CONTENTS_RECORD_FIELDS = [
95
+ ("string", "content"),
96
+ ("path", "path"),
97
+ ("string", "deleted_content"),
98
+ ]
98
99
 
99
100
  WindowsNotepadUnsavedTabRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
100
- "texteditor/windowsnotepad/tab/unsaved",
101
- GENERIC_TAB_CONTENTS_RECORD_FIELDS,
101
+ "application/editor/windowsnotepad/tab/unsaved",
102
+ COMMON_EDITOR_FIELDS + GENERIC_TAB_CONTENTS_RECORD_FIELDS,
102
103
  )
103
104
 
104
105
  WindowsNotepadSavedTabRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
105
- "texteditor/windowsnotepad/tab/saved",
106
- GENERIC_TAB_CONTENTS_RECORD_FIELDS + WINDOWS_SAVED_TABS_EXTRA_FIELDS,
106
+ "application/editor/windowsnotepad/tab/saved",
107
+ COMMON_EDITOR_FIELDS
108
+ + GENERIC_TAB_CONTENTS_RECORD_FIELDS
109
+ + [
110
+ ("digest", "digest"),
111
+ ("path", "saved_path"),
112
+ ],
107
113
  )
108
114
 
109
115
  c_windowstab = cstruct().load(windowstab_def)
@@ -264,7 +270,7 @@ class WindowsNotepadTab:
264
270
  self.deleted_content = deleted_content if deleted_content else None
265
271
 
266
272
 
267
- class WindowsNotepadPlugin(TexteditorPlugin):
273
+ class WindowsNotepadPlugin(EditorPlugin):
268
274
  """Windows notepad tab content plugin."""
269
275
 
270
276
  __namespace__ = "windowsnotepad"
@@ -273,28 +279,27 @@ class WindowsNotepadPlugin(TexteditorPlugin):
273
279
 
274
280
  def __init__(self, target: Target):
275
281
  super().__init__(target)
276
- self.users_tabs: list[TargetPath, UnixUserRecord | WindowsUserRecord] = []
282
+ self.users_tabs: set[TargetPath, UnixUserRecord | WindowsUserRecord] = set()
277
283
  for user_details in self.target.user_details.all_with_home():
278
284
  for tab_file in user_details.home_path.glob(self.GLOB):
279
- # These files seem to contain information on different settings / configurations,
280
- # and are skipped for now
285
+ # These files contain information on different settings / configurations, and are skipped for now.
281
286
  if tab_file.name.endswith(".1.bin") or tab_file.name.endswith(".0.bin"):
282
287
  continue
283
288
 
284
- self.users_tabs.append((tab_file, user_details.user))
289
+ self.users_tabs.add((tab_file, user_details.user))
285
290
 
286
291
  def check_compatible(self) -> None:
287
292
  if not self.users_tabs:
288
293
  raise UnsupportedPluginError("No Windows Notepad tab files found")
289
294
 
295
+ @alias("tabs")
290
296
  @export(record=[WindowsNotepadSavedTabRecord, WindowsNotepadUnsavedTabRecord])
291
- def tabs(self) -> Iterator[WindowsNotepadSavedTabRecord | WindowsNotepadUnsavedTabRecord]:
297
+ def history(self) -> Iterator[WindowsNotepadSavedTabRecord | WindowsNotepadUnsavedTabRecord]:
292
298
  """Return contents from Windows 11 Notepad tabs - and its deleted content if available.
293
299
 
294
300
  Windows Notepad application for Windows 11 is now able to restore both saved and unsaved tabs when you re-open
295
301
  the application.
296
302
 
297
-
298
303
  Resources:
299
304
  - https://github.com/fox-it/dissect.target/pull/540
300
305
  - https://github.com/JustArion/Notepad-Tabs
@@ -304,37 +309,41 @@ class WindowsNotepadPlugin(TexteditorPlugin):
304
309
  - https://github.com/Nordgaren/tabstate-util/issues/1
305
310
  - https://medium.com/@mahmoudsoheem/new-digital-forensics-artifact-from-windows-notepad-527645906b7b
306
311
 
307
- Yields a WindowsNotepadSavedTabRecord or WindowsNotepadUnsavedTabRecord. with fields:
312
+ Yields ``WindowsNotepadSavedTabRecord`` or ``WindowsNotepadUnsavedTabRecord`` records:
308
313
 
309
314
  .. code-block:: text
310
315
 
311
- content (string): The content of the tab.
312
- path (path): The path to the tab file.
313
- deleted_content (string): The deleted content of the tab, if available.
314
- hashes (digest): A digest of the tab content.
315
- saved_path (path): The path where the tab was saved.
316
- modification_time (datetime): The modification time of the tab.
316
+ ts (datetime): The modification time of the tab.
317
+ content (string): The content of the tab.
318
+ path (path): The path to the tab file.
319
+ deleted_content (string): The deleted content of the tab, if available.
320
+ digest (digest): A digest of the tab content.
321
+ saved_path (path): The path where the tab was saved.
317
322
  """
318
323
  for file, user in self.users_tabs:
319
- # Parse the file
320
- tab: WindowsNotepadTab = WindowsNotepadTab(file)
324
+ tab = WindowsNotepadTab(file)
321
325
 
322
326
  if tab.is_saved:
323
327
  yield WindowsNotepadSavedTabRecord(
328
+ ts=wintimestamp(tab.tab_header.timestamp),
329
+ editor="windowsnotepad",
324
330
  content=tab.content,
325
331
  path=tab.file,
326
332
  deleted_content=tab.deleted_content,
327
- hashes=digest((None, None, tab.tab_header.sha256.hex())),
333
+ digest=digest((None, None, tab.tab_header.sha256.hex())),
328
334
  saved_path=tab.tab_header.filePath,
329
- modification_time=wintimestamp(tab.tab_header.timestamp),
330
- _target=self.target,
335
+ source=file,
331
336
  _user=user,
337
+ _target=self.target,
332
338
  )
339
+
333
340
  else:
334
341
  yield WindowsNotepadUnsavedTabRecord(
342
+ editor="windowsnotepad",
335
343
  content=tab.content,
344
+ deleted_content=tab.deleted_content,
336
345
  path=tab.file,
337
- _target=self.target,
346
+ source=file,
338
347
  _user=user,
339
- deleted_content=tab.deleted_content,
348
+ _target=self.target,
340
349
  )
@@ -0,0 +1,78 @@
1
+ from typing import Iterator
2
+
3
+ from dissect.target.exceptions import UnsupportedPluginError
4
+ from dissect.target.helpers import configutil
5
+ from dissect.target.helpers.fsutil import TargetPath
6
+ from dissect.target.helpers.record import UnixApplicationRecord
7
+ from dissect.target.plugin import Plugin, export
8
+ from dissect.target.target import Target
9
+
10
+
11
+ class UnixApplicationsPlugin(Plugin):
12
+ """Unix Applications plugin."""
13
+
14
+ SYSTEM_PATHS = [
15
+ "/usr/share/applications/",
16
+ "/usr/local/share/applications/",
17
+ "/var/lib/snapd/desktop/applications/",
18
+ "/var/lib/flatpak/exports/share/applications/",
19
+ ]
20
+
21
+ USER_PATHS = [
22
+ ".local/share/applications/",
23
+ ]
24
+
25
+ SYSTEM_APPS = ("org.gnome.",)
26
+
27
+ def __init__(self, target: Target):
28
+ super().__init__(target)
29
+ self.desktop_files = list(self._find_desktop_files())
30
+
31
+ def _find_desktop_files(self) -> Iterator[TargetPath]:
32
+ for dir in self.SYSTEM_PATHS:
33
+ for file in self.target.fs.path(dir).glob("*.desktop"):
34
+ yield file
35
+
36
+ for user_details in self.target.user_details.all_with_home():
37
+ for dir in self.USER_PATHS:
38
+ for file in user_details.home_path.joinpath(dir).glob("*.desktop"):
39
+ yield file
40
+
41
+ def check_compatible(self) -> None:
42
+ if not self.desktop_files:
43
+ raise UnsupportedPluginError("No application .desktop files found")
44
+
45
+ @export(record=UnixApplicationRecord)
46
+ def applications(self) -> Iterator[UnixApplicationRecord]:
47
+ """Yield installed Unix GUI applications from GNOME and XFCE.
48
+
49
+ Resources:
50
+ - https://wiki.archlinux.org/title/Desktop_entries
51
+ - https://specifications.freedesktop.org/desktop-entry-spec/latest/
52
+ - https://unix.stackexchange.com/questions/582928/where-gnome-apps-are-installed
53
+
54
+ Yields ``UnixApplicationRecord`` records with the following fields:
55
+
56
+ .. code-block:: text
57
+
58
+ ts_modified (datetime): timestamp when the installation was modified
59
+ ts_installed (datetime): timestamp when the application was installed on the system
60
+ name (string): name of the application
61
+ version (string): version of the application
62
+ author (string): author of the application
63
+ type (string): type of the application, either user or system
64
+ path (string): path to the desktop file entry of the application
65
+ """
66
+ for file in self.desktop_files:
67
+ config = configutil.parse(file, hint="ini").get("Desktop Entry") or {}
68
+ stat = file.lstat()
69
+
70
+ yield UnixApplicationRecord(
71
+ ts_modified=stat.st_mtime,
72
+ ts_installed=stat.st_btime if hasattr(stat, "st_btime") else None,
73
+ name=config.get("Name"),
74
+ version=config.get("Version"),
75
+ path=config.get("Exec"),
76
+ type="system" if config.get("Icon", "").startswith(self.SYSTEM_APPS) else "user",
77
+ _target=self.target,
78
+ )
@@ -0,0 +1,79 @@
1
+ from typing import Iterator
2
+
3
+ from dissect.target.exceptions import UnsupportedPluginError
4
+ from dissect.target.filesystems.squashfs import SquashFSFilesystem
5
+ from dissect.target.helpers import configutil
6
+ from dissect.target.helpers.fsutil import TargetPath
7
+ from dissect.target.helpers.record import UnixApplicationRecord
8
+ from dissect.target.plugin import Plugin, alias, export
9
+ from dissect.target.target import Target
10
+
11
+
12
+ class SnapPlugin(Plugin):
13
+ """Canonical Linux Snapcraft plugin."""
14
+
15
+ PATHS = [
16
+ "/var/lib/snapd/snaps",
17
+ ]
18
+
19
+ def __init__(self, target: Target):
20
+ super().__init__(target)
21
+ self.installs = list(self._find_installs())
22
+
23
+ def check_compatible(self) -> None:
24
+ if not configutil.HAS_YAML:
25
+ raise UnsupportedPluginError("Missing required dependency ruamel.yaml")
26
+
27
+ if not self.installs:
28
+ raise UnsupportedPluginError("No snapd install folder(s) found")
29
+
30
+ def _find_installs(self) -> Iterator[TargetPath]:
31
+ for str_path in self.PATHS:
32
+ if (path := self.target.fs.path(str_path)).exists():
33
+ yield path
34
+
35
+ @export(record=UnixApplicationRecord)
36
+ @alias("snaps")
37
+ def snap(self) -> Iterator[UnixApplicationRecord]:
38
+ """Yields installed Canonical Linux Snapcraft (snaps) applications on the target system.
39
+
40
+ Reads information from installed SquashFS ``*.snap`` files found in ``/var/lib/snapd/snaps``.
41
+ Logs of the ``snapd`` daemon can be parsed using the ``journal`` or ``syslog`` plugins.
42
+
43
+ Resources:
44
+ - https://github.com/canonical/snapcraft
45
+ - https://en.wikipedia.org/wiki/Snap_(software)
46
+
47
+ Yields ``UnixApplicationRecord`` records with the following fields:
48
+
49
+ .. code-block:: text
50
+
51
+ ts_modified (datetime): timestamp when the installation was modified
52
+ name (string): name of the application
53
+ version (string): version of the application
54
+ path (string): path to the application snap file
55
+ """
56
+
57
+ for install_path in self.installs:
58
+ for snap in install_path.glob("*.snap"):
59
+ try:
60
+ squashfs = SquashFSFilesystem(snap.open())
61
+
62
+ except (ValueError, NotImplementedError) as e:
63
+ self.target.log.warning("Unable to open snap file %s", snap)
64
+ self.target.log.debug("", exc_info=e)
65
+ continue
66
+
67
+ if not (meta := squashfs.path("meta/snap.yaml")).exists():
68
+ self.target.log.warning("Snap %s has no meta/snap.yaml file")
69
+ continue
70
+
71
+ meta_data = configutil.parse(meta, hint="yaml")
72
+
73
+ yield UnixApplicationRecord(
74
+ ts_modified=meta.lstat().st_mtime,
75
+ name=meta_data.get("name"),
76
+ version=meta_data.get("version"),
77
+ path=snap,
78
+ _target=self.target,
79
+ )
@@ -6,7 +6,7 @@ from dissect.target.helpers.record import TargetRecordDescriptor
6
6
  from dissect.target.plugin import NamespacePlugin
7
7
 
8
8
  PackageManagerLogRecord = TargetRecordDescriptor(
9
- "unix/log/packagemanager",
9
+ "unix/packagemanager/log",
10
10
  [
11
11
  ("datetime", "ts"),
12
12
  ("string", "package_manager"),
@@ -0,0 +1,62 @@
1
+ from datetime import datetime
2
+ from typing import Iterator
3
+
4
+ from dissect.target.exceptions import UnsupportedPluginError
5
+ from dissect.target.helpers.record import WindowsApplicationRecord
6
+ from dissect.target.plugin import Plugin, export
7
+ from dissect.target.target import Target
8
+
9
+
10
+ class WindowsApplicationsPlugin(Plugin):
11
+ """Windows Applications plugin."""
12
+
13
+ def __init__(self, target: Target):
14
+ super().__init__(target)
15
+ self.keys = list(self.target.registry.keys("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"))
16
+
17
+ def check_compatible(self) -> None:
18
+ if not self.target.has_function("registry"):
19
+ raise UnsupportedPluginError("No Windows registry found")
20
+
21
+ if not self.keys:
22
+ raise UnsupportedPluginError("No 'Uninstall' registry keys found")
23
+
24
+ @export(record=WindowsApplicationRecord)
25
+ def applications(self) -> Iterator[WindowsApplicationRecord]:
26
+ """Yields currently installed applications from the Windows registry.
27
+
28
+ Use the Windows eventlog plugin (``evtx``, ``evt``) to parse install and uninstall events
29
+ of applications and services (e.g. ``4697``, ``110707``, ``1034`` and ``11724``).
30
+
31
+ Resources:
32
+ - https://learn.microsoft.com/en-us/windows/win32/msi/uninstall-registry-key
33
+
34
+ Yields ``WindowsApplicationRecord`` records with the following fields:
35
+
36
+ .. code-block:: text
37
+
38
+ ts_modified (datetime): timestamp when the installation was modified according to the registry
39
+ ts_installed (datetime): timestamp when the application was installed according to the application
40
+ name (string): name of the application
41
+ version (string): version of the application
42
+ author (string): author of the application
43
+ type (string): type of the application, either user or system
44
+ path (string): path to the installed location or installer of the application
45
+ """
46
+ for uninstall in self.keys:
47
+ for app in uninstall.subkeys():
48
+ values = {value.name: value.value for value in app.values()}
49
+
50
+ if install_date := values.get("InstallDate"):
51
+ install_date = datetime.strptime(install_date, "%Y%m%d")
52
+
53
+ yield WindowsApplicationRecord(
54
+ ts_modified=app.ts,
55
+ ts_installed=install_date,
56
+ name=values.get("DisplayName") or app.name,
57
+ version=values.get("DisplayVersion"),
58
+ author=values.get("Publisher"),
59
+ type="system" if values.get("SystemComponent") or not values else "user",
60
+ path=values.get("DisplayIcon") or values.get("InstallLocation") or values.get("InstallSource"),
61
+ _target=self.target,
62
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.20.dev38
3
+ Version: 3.20.dev40
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
@@ -60,9 +60,9 @@ dissect/target/helpers/mount.py,sha256=7Y4B0uY2c00p23hmuMKSgwAwxkKcY4spyAMO1kdcV
60
60
  dissect/target/helpers/mui.py,sha256=i-7XoHbu4WO2fYapK9yGAMW04rFlgRispknc1KQIS5Q,22258
61
61
  dissect/target/helpers/polypath.py,sha256=h8p7m_OCNiQljGwoZh5Aflr9H2ot6CZr6WKq1OSw58o,2175
62
62
  dissect/target/helpers/protobuf.py,sha256=b4DsnqrRLrefcDjx7rQno-_LBcwtJXxuKf5RdOegzfE,1537
63
- dissect/target/helpers/record.py,sha256=7Se6ZV8cvwEaGSjRd9bKhVnUAn4W4KR2eqP6AbQhTH4,5892
63
+ dissect/target/helpers/record.py,sha256=TxG1lwW5N0V-7kuq4s2vnQh-hAbT7rVwwZLf4sIDNjM,6334
64
64
  dissect/target/helpers/record_modifier.py,sha256=cRNDhUYMmx4iEKyEr5Pqy9xiFgxr_GBNJPp_omkQsEU,4094
65
- dissect/target/helpers/regutil.py,sha256=ti-ht2N9UxbMjhUBP2bybY76_dAvbCz0txPBszvSKVw,28171
65
+ dissect/target/helpers/regutil.py,sha256=dnmpceitwTeS-9L8HU_HG5OXMzCcH58o8uhj5olDWyg,28383
66
66
  dissect/target/helpers/shell_application_ids.py,sha256=hYxrP-YtHK7ZM0ectJFHfoMB8QUXLbYNKmKXMWLZRlA,38132
67
67
  dissect/target/helpers/shell_folder_ids.py,sha256=Behhb8oh0kMxrEk6YYKYigCDZe8Hw5QS6iK_d2hTs2Y,24978
68
68
  dissect/target/helpers/utils.py,sha256=K3xVq9D0FwIhTBAuiWN8ph7Pq2GABgG3hOz-3AmKuEA,4244
@@ -127,6 +127,9 @@ dissect/target/plugins/apps/browser/firefox.py,sha256=mZBBagFfIdiz9kUyK4Hi989I4g
127
127
  dissect/target/plugins/apps/browser/iexplore.py,sha256=g_xw0toaiyjevxO8g9XPCOqc-CXZp39FVquRhPFGdTE,8801
128
128
  dissect/target/plugins/apps/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
129
129
  dissect/target/plugins/apps/container/docker.py,sha256=LTsZplaECSfO1Ysp_Y-9WsnNocsreu_iHO8fbSif3g0,16221
130
+ dissect/target/plugins/apps/editor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
131
+ dissect/target/plugins/apps/editor/editor.py,sha256=yJctXY0XTfwW3GKy6XLO2WaWFQLssdBck9ZOcZSyf80,495
132
+ dissect/target/plugins/apps/editor/windowsnotepad.py,sha256=A9cfFrqbU2zjHRrzYsCnXr-uxKAIsVIKdXXJPYMt6MU,15068
130
133
  dissect/target/plugins/apps/other/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
131
134
  dissect/target/plugins/apps/other/env.py,sha256=_I12S_wjyT18WlUJ5cWOy5OTI140AheH6tq743iiyys,1874
132
135
  dissect/target/plugins/apps/remoteaccess/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -141,9 +144,6 @@ dissect/target/plugins/apps/ssh/openssh.py,sha256=e3bj9fWxvU2K9Gk9JqA2_E-opkzLTv
141
144
  dissect/target/plugins/apps/ssh/opensshd.py,sha256=VL78AuMaacn-pGNoPwvWm_9lbhj-ZNJDmRbL-UlQpIM,5545
142
145
  dissect/target/plugins/apps/ssh/putty.py,sha256=EmsXr2NbOB13-EWS5AkpEPMUhOkVl6FAy8JGUiaDhxk,10133
143
146
  dissect/target/plugins/apps/ssh/ssh.py,sha256=d3U8PJbtMvOV3K0wV_9KzGt2oRs-mfNQz1_Xd6SNx0Y,9320
144
- dissect/target/plugins/apps/texteditor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
145
- dissect/target/plugins/apps/texteditor/texteditor.py,sha256=h-tF1x2hLlgeNM3W-0Z9g0mjjkb9ietT1D5c-9GaMr8,543
146
- dissect/target/plugins/apps/texteditor/windowsnotepad.py,sha256=BXGhcwWIW6zlQyD_nHpc1r5Lxt6WMvhfqY2PWf0A6pw,14852
147
147
  dissect/target/plugins/apps/virtualization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
148
148
  dissect/target/plugins/apps/virtualization/vmware_workstation.py,sha256=7G-MRZCMN6aSYfs5NpaW2wkezqlx_EXq9-GzdbvtRrk,2088
149
149
  dissect/target/plugins/apps/vpn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -195,12 +195,13 @@ dissect/target/plugins/general/users.py,sha256=yy9gvRXfN9BT71v4Xqo5hpwfgN9he9Otu
195
195
  dissect/target/plugins/os/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
196
196
  dissect/target/plugins/os/unix/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
197
197
  dissect/target/plugins/os/unix/_os.py,sha256=I-waC7Hn9rMJRI2JUDreLnU_LS54Zj3hix7BfJLV-xg,14651
198
+ dissect/target/plugins/os/unix/applications.py,sha256=AUgZRP35FzswGyFyChj2o4dfGO34Amc6nqHgiMEaqdI,3129
198
199
  dissect/target/plugins/os/unix/cronjobs.py,sha256=tgWQ3BUZpfyvRzodMwGtwFUdPjZ17k7ZRbZ9Q8wmXPk,3393
199
200
  dissect/target/plugins/os/unix/datetime.py,sha256=gKfBdPyUirt3qmVYfOJ1oZXRPn8wRzssbZxR_ARrtk8,1518
200
201
  dissect/target/plugins/os/unix/generic.py,sha256=qC4zQiqpm8ilc-d1ITsccOQbbUUM8HylWB4dsFKJjAw,2171
201
202
  dissect/target/plugins/os/unix/history.py,sha256=95EXJrD5ko7iFLsYhAwvR-2wDbVBSNsyXsfZKEWMJq8,6533
202
203
  dissect/target/plugins/os/unix/locale.py,sha256=l42abqG1nGk90SDRt1DmkvqPvO5L-1GtaEwg6dj89qI,4323
203
- dissect/target/plugins/os/unix/packagemanager.py,sha256=XKKJuJ1p9mEQ4TGW7SEwcj1rg8fPp2aWIhnt_0i8Rhc,1279
204
+ dissect/target/plugins/os/unix/packagemanager.py,sha256=xmisH9vMY7uR2d6lFVNuWrZrbVnKa6mYk6C3sbcLtlc,1279
204
205
  dissect/target/plugins/os/unix/shadow.py,sha256=TVQQcGhPFYV685ouqOagk4P1AsqAHseFN5lWYHPf3tI,4172
205
206
  dissect/target/plugins/os/unix/trash.py,sha256=Z-1r5VQorLauj_85TgURRLQI7ns1Q1N_922Vq8q_v18,6106
206
207
  dissect/target/plugins/os/unix/bsd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -240,6 +241,7 @@ dissect/target/plugins/os/unix/linux/debian/__init__.py,sha256=47DEQpj8HBSa-_TIm
240
241
  dissect/target/plugins/os/unix/linux/debian/_os.py,sha256=GI19ZqcyfZ1mUYg2NCx93HkZje9MWMU8FYNKQv-G6go,498
241
242
  dissect/target/plugins/os/unix/linux/debian/apt.py,sha256=uKfW77pbgxYSe9g6hpih19-xfgvCB954Ygx21j-ydzk,4388
242
243
  dissect/target/plugins/os/unix/linux/debian/dpkg.py,sha256=6A3mb77NREdDWDTFrmcfCF_XxHMmD4_5eHqHEl_7Vqg,5816
244
+ dissect/target/plugins/os/unix/linux/debian/snap.py,sha256=YVz1N54eQsj2_22LUJIj6Gg-huwT4xDEcOAZn9Tvgw4,3023
243
245
  dissect/target/plugins/os/unix/linux/debian/vyos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
244
246
  dissect/target/plugins/os/unix/linux/debian/vyos/_os.py,sha256=TPjcfv1n68RCe3Er4aCVQwQDCZwJT-NLvje3kPjDfhk,1744
245
247
  dissect/target/plugins/os/unix/linux/fortios/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -324,6 +326,7 @@ dissect/target/plugins/os/windows/log/pfro.py,sha256=d53Mm7ovZa9crSwVRPwjMVxTd_j
324
326
  dissect/target/plugins/os/windows/log/schedlgu.py,sha256=JaP8H8eTEypWXhx2aFSR_IMam6rQiksbLKhMr_U4fz8,5570
325
327
  dissect/target/plugins/os/windows/regf/7zip.py,sha256=Ox8cLyQtbyYQS7m4eY3onNv1K8N2IkS5wexrC55Urd4,3444
326
328
  dissect/target/plugins/os/windows/regf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
329
+ dissect/target/plugins/os/windows/regf/applications.py,sha256=AZwaLXsVmqMjoZYI3dhYLvJL_8s1k1aRjSgjvqC2AxI,2898
327
330
  dissect/target/plugins/os/windows/regf/appxdebugkeys.py,sha256=X8MYLcD76pIZoIWwS_DgUp6q6pi2WO7jhZeoc4uGLak,3966
328
331
  dissect/target/plugins/os/windows/regf/auditpol.py,sha256=vTqWw0_vu9p_emWC8FuYcYQpOXhEFQQDLV0K6-18i9c,5208
329
332
  dissect/target/plugins/os/windows/regf/bam.py,sha256=jJ0i-82uteBU0hPgs81f8NV8NCeRtIklK82Me2S_ro0,2131
@@ -370,10 +373,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
370
373
  dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
371
374
  dissect/target/volumes/md.py,sha256=7ShPtusuLGaIv27SvEETtgsuoQyAa4iAAeOR1NEaajI,1689
372
375
  dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
373
- dissect.target-3.20.dev38.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
374
- dissect.target-3.20.dev38.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
375
- dissect.target-3.20.dev38.dist-info/METADATA,sha256=Ex7zBUuPOU3i3WWpjC0GWdIp7kFkai3r89cl9anlJ3A,12897
376
- dissect.target-3.20.dev38.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
377
- dissect.target-3.20.dev38.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
378
- dissect.target-3.20.dev38.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
379
- dissect.target-3.20.dev38.dist-info/RECORD,,
376
+ dissect.target-3.20.dev40.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
377
+ dissect.target-3.20.dev40.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
378
+ dissect.target-3.20.dev40.dist-info/METADATA,sha256=sfc-H38qJzXkx1449zv0Y7SgicuUfJeki3JFiC6EJ4c,12897
379
+ dissect.target-3.20.dev40.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
380
+ dissect.target-3.20.dev40.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
381
+ dissect.target-3.20.dev40.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
382
+ dissect.target-3.20.dev40.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- from dissect.target.helpers.descriptor_extensions import UserRecordDescriptorExtension
2
- from dissect.target.helpers.record import create_extended_descriptor
3
- from dissect.target.plugin import NamespacePlugin
4
-
5
- GENERIC_TAB_CONTENTS_RECORD_FIELDS = [("string", "content"), ("path", "path"), ("string", "deleted_content")]
6
-
7
- TexteditorTabContentRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
8
- "texteditor/tab", GENERIC_TAB_CONTENTS_RECORD_FIELDS
9
- )
10
-
11
-
12
- class TexteditorPlugin(NamespacePlugin):
13
- __namespace__ = "texteditor"