dissect.target 3.17.dev35__py3-none-any.whl → 3.17.dev37__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -62,13 +62,16 @@ MODIFIER_MAPPING = {
62
62
 
63
63
  def _resolve_path_types(target: Target, record: Record) -> Iterator[tuple[str, TargetPath]]:
64
64
  for field_name, field_type in record._field_types.items():
65
- if not issubclass(field_type, fieldtypes.path):
65
+ if not issubclass(field_type, (fieldtypes.path, fieldtypes.command)):
66
66
  continue
67
67
 
68
68
  path = getattr(record, field_name, None)
69
69
  if path is None:
70
70
  continue
71
71
 
72
+ if isinstance(path, fieldtypes.command):
73
+ path = path.executable
74
+
72
75
  yield field_name, target.resolve(str(path))
73
76
 
74
77
 
@@ -18,6 +18,7 @@ from dissect.target.plugin import export
18
18
  from dissect.target.plugins.apps.browser.browser import (
19
19
  GENERIC_COOKIE_FIELDS,
20
20
  GENERIC_DOWNLOAD_RECORD_FIELDS,
21
+ GENERIC_EXTENSION_RECORD_FIELDS,
21
22
  GENERIC_HISTORY_RECORD_FIELDS,
22
23
  GENERIC_PASSWORD_RECORD_FIELDS,
23
24
  BrowserPlugin,
@@ -43,6 +44,7 @@ try:
43
44
  except ImportError:
44
45
  HAS_CRYPTO = False
45
46
 
47
+ FIREFOX_EXTENSION_RECORD_FIELDS = [("uri", "source_uri"), ("string[]", "optional_permissions")]
46
48
 
47
49
  log = logging.getLogger(__name__)
48
50
 
@@ -76,6 +78,10 @@ class FirefoxPlugin(BrowserPlugin):
76
78
  "browser/firefox/download", GENERIC_DOWNLOAD_RECORD_FIELDS
77
79
  )
78
80
 
81
+ BrowserExtensionRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
82
+ "browser/firefox/extension", GENERIC_EXTENSION_RECORD_FIELDS + FIREFOX_EXTENSION_RECORD_FIELDS
83
+ )
84
+
79
85
  BrowserPasswordRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
80
86
  "browser/firefox/password", GENERIC_PASSWORD_RECORD_FIELDS
81
87
  )
@@ -305,6 +311,72 @@ class FirefoxPlugin(BrowserPlugin):
305
311
  except SQLError as e:
306
312
  self.target.log.warning("Error processing history file: %s", db_file, exc_info=e)
307
313
 
314
+ @export(record=BrowserExtensionRecord)
315
+ def extensions(self) -> Iterator[BrowserExtensionRecord]:
316
+ """Return browser extension records for Firefox.
317
+
318
+ Yields BrowserExtensionRecord with the following fields::
319
+ ts_install (datetime): Extension install timestamp.
320
+ ts_update (datetime): Extension update timestamp.
321
+ browser (string): The browser from which the records are generated.
322
+ id (string): Extension unique identifier.
323
+ name (string): Name of the extension.
324
+ short_name (string): Short name of the extension.
325
+ default_title (string): Default title of the extension.
326
+ description (string): Description of the extension.
327
+ version (string): Version of the extension.
328
+ ext_path (path): Relative path of the extension.
329
+ from_webstore (boolean): Extension from webstore.
330
+ permissions (string[]): Permissions of the extension.
331
+ manifest (varint): Version of the extensions' manifest.
332
+ optional_permissions (string[]): Optional permissions of the extension.
333
+ source_uri (path): Source path from which the extension was downloaded.
334
+ source (path): The source file of the download record.
335
+ """
336
+ for user, _, profile_dir in self._iter_profiles():
337
+ extension_file = profile_dir.joinpath("extensions.json")
338
+
339
+ if not extension_file.exists():
340
+ self.target.log.warning(
341
+ "No 'extensions.json' addon file found for user %s in directory %s", user, profile_dir
342
+ )
343
+ continue
344
+
345
+ try:
346
+ extensions = json.load(extension_file.open())
347
+
348
+ for extension in extensions.get("addons", []):
349
+ yield self.BrowserExtensionRecord(
350
+ ts_install=extension.get("installDate", 0) // 1000,
351
+ ts_update=extension.get("updateDate", 0) // 1000,
352
+ browser="firefox",
353
+ id=extension.get("id"),
354
+ name=extension.get("defaultLocale", {}).get("name"),
355
+ short_name=None,
356
+ default_title=None,
357
+ description=extension.get("defaultLocale", {}).get("description"),
358
+ version=extension.get("version"),
359
+ ext_path=extension.get("path"),
360
+ from_webstore=None,
361
+ permissions=extension.get("userPermissions", {}).get("permissions"),
362
+ manifest_version=extension.get("manifestVersion"),
363
+ source_uri=extension.get("sourceURI"),
364
+ optional_permissions=extension.get("optionalPermissions", {}).get("permissions"),
365
+ source=extension_file,
366
+ _target=self.target,
367
+ _user=user.user,
368
+ )
369
+
370
+ except FileNotFoundError:
371
+ self.target.log.info(
372
+ "No 'extensions.json' addon file found for user %s in directory %s", user, profile_dir
373
+ )
374
+ except json.JSONDecodeError:
375
+ self.target.log.warning(
376
+ "extensions.json file in directory %s is malformed, consider inspecting the file manually",
377
+ profile_dir,
378
+ )
379
+
308
380
  @export(record=BrowserPasswordRecord)
309
381
  def passwords(self) -> Iterator[BrowserPasswordRecord]:
310
382
  """Return Firefox browser password records.
@@ -1,3 +1,5 @@
1
+ from typing import Iterator
2
+
1
3
  from dissect.target.exceptions import UnsupportedPluginError
2
4
  from dissect.target.helpers.descriptor_extensions import (
3
5
  RegistryRecordDescriptorExtension,
@@ -11,7 +13,7 @@ RunKeyRecord = create_extended_descriptor([RegistryRecordDescriptorExtension, Us
11
13
  [
12
14
  ("datetime", "ts"),
13
15
  ("wstring", "name"),
14
- ("string", "path"),
16
+ ("command", "command"),
15
17
  ("string", "key"),
16
18
  ],
17
19
  )
@@ -48,7 +50,7 @@ class RunKeysPlugin(Plugin):
48
50
  raise UnsupportedPluginError("No registry run key found")
49
51
 
50
52
  @export(record=RunKeyRecord)
51
- def runkeys(self):
53
+ def runkeys(self) -> Iterator[RunKeyRecord]:
52
54
  """Iterate various run key locations. See source for all locations.
53
55
 
54
56
  Run keys (Run and RunOnce) are registry keys that make a program run when a user logs on. a Run key runs every
@@ -63,7 +65,7 @@ class RunKeysPlugin(Plugin):
63
65
  domain (string): The target domain.
64
66
  ts (datetime): The registry key last modified timestamp.
65
67
  name (string): The run key name.
66
- path (string): The run key path.
68
+ command (command): The run key command.
67
69
  key (string): The source key for this run key.
68
70
  """
69
71
  for key in self.KEYS:
@@ -73,7 +75,7 @@ class RunKeysPlugin(Plugin):
73
75
  yield RunKeyRecord(
74
76
  ts=r.ts,
75
77
  name=entry.name,
76
- path=entry.value,
78
+ command=entry.value,
77
79
  key=key,
78
80
  _target=self.target,
79
81
  _key=r,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.17.dev35
3
+ Version: 3.17.dev37
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
@@ -31,7 +31,7 @@ Requires-Dist: dissect.ntfs <4.0.dev,>=3.4.dev
31
31
  Requires-Dist: dissect.regf <4.0.dev,>=3.3.dev
32
32
  Requires-Dist: dissect.util <4.0.dev,>=3.0.dev
33
33
  Requires-Dist: dissect.volume <4.0.dev,>=3.0.dev
34
- Requires-Dist: flow.record ~=3.14.0
34
+ Requires-Dist: flow.record ~=3.15.0
35
35
  Requires-Dist: structlog
36
36
  Provides-Extra: cb
37
37
  Requires-Dist: dissect.target[full] ; extra == 'cb'
@@ -62,7 +62,7 @@ dissect/target/helpers/network_managers.py,sha256=uRh_P8ICbKke2N7eFJ6AS2-I5DmIRi
62
62
  dissect/target/helpers/polypath.py,sha256=h8p7m_OCNiQljGwoZh5Aflr9H2ot6CZr6WKq1OSw58o,2175
63
63
  dissect/target/helpers/protobuf.py,sha256=NwKrZD4q9v7J8GnZX9gbzMUMV5pR78eAV17jgWOz_EY,1730
64
64
  dissect/target/helpers/record.py,sha256=lWl7k2Mp9Axllm0tXzPGJx2zj2zONsyY_p5g424T0Lc,4826
65
- dissect/target/helpers/record_modifier.py,sha256=BiZ_gtqVxuByLWrga1lfglk3X-TcMrJC0quxPpXoIRo,3138
65
+ dissect/target/helpers/record_modifier.py,sha256=3I_rC5jqvl0TsW3V8OQ6Dltz_D8J4PU1uhhzbJGKm9c,3245
66
66
  dissect/target/helpers/regutil.py,sha256=kX-sSZbW8Qkg29Dn_9zYbaQrwLumrr4Y8zJ1EhHXIAM,27337
67
67
  dissect/target/helpers/shell_folder_ids.py,sha256=Behhb8oh0kMxrEk6YYKYigCDZe8Hw5QS6iK_d2hTs2Y,24978
68
68
  dissect/target/helpers/ssh.py,sha256=LPssHXyfL8QYmLi2vpa3wElsGboLG_A1Y8kvOehpUr4,6338
@@ -124,7 +124,7 @@ dissect/target/plugins/apps/browser/browser.py,sha256=rBIwcgdl73gm-8APwx2jEUAYXR
124
124
  dissect/target/plugins/apps/browser/chrome.py,sha256=hxS8gqpBwoCrPaxNpllIa6K9DtsSGzn6XXcUaHyes6w,3048
125
125
  dissect/target/plugins/apps/browser/chromium.py,sha256=1oaQhMN5mJysw0VIVpTEmRCAifgv-mUQxZwrGmGHqAQ,27875
126
126
  dissect/target/plugins/apps/browser/edge.py,sha256=woXzZtHPWmfcV8vbxGKHELKru5JRb32MAXs43_b4K4E,2883
127
- dissect/target/plugins/apps/browser/firefox.py,sha256=Y8QdSgPZktYy4IF36aI1Jfbw_ucysx82PNljnyUCmRY,27025
127
+ dissect/target/plugins/apps/browser/firefox.py,sha256=Msicw-13AJWbXRRF6m_p4L84rXAjsIYGFRve29cPY2M,30806
128
128
  dissect/target/plugins/apps/browser/iexplore.py,sha256=MqMonoaM5lj0ZFqGwS4F-P1eLmnLvX7VQGE9S3hxXag,8739
129
129
  dissect/target/plugins/apps/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
130
130
  dissect/target/plugins/apps/container/docker.py,sha256=67Eih9AfUbqsP-HlnlwoHi4rSAnVCZWM76sEyO_1m18,15316
@@ -307,7 +307,7 @@ dissect/target/plugins/os/windows/regf/muicache.py,sha256=qoA7S8SiZakIreQqxc_QH1
307
307
  dissect/target/plugins/os/windows/regf/nethist.py,sha256=QHbG9fmZNmjSVhrgqMvMo12YBaQedzeToS7ZD9eIJ28,3111
308
308
  dissect/target/plugins/os/windows/regf/recentfilecache.py,sha256=Wr6u7SajA9BtUiypztak9ASJZuimOtWfQUAlfvskjMg,1838
309
309
  dissect/target/plugins/os/windows/regf/regf.py,sha256=IbLnOurtlprXAo12iYRdw6fv5J45SuMAqt-mXVYaZi4,3357
310
- dissect/target/plugins/os/windows/regf/runkeys.py,sha256=qX-6xOrgBq7_B00C1BoQtI0Ovzou6Sx3XemV0Ra4JMs,4178
310
+ dissect/target/plugins/os/windows/regf/runkeys.py,sha256=f10jOPTJlUVDEhSiH9JSltKQ-V7zfa8iPX0nKl1gBXo,4247
311
311
  dissect/target/plugins/os/windows/regf/shellbags.py,sha256=EKBWBjxvSfxc7WFKmICZs8QUJnjhsCKesjl_NHEnSUo,25621
312
312
  dissect/target/plugins/os/windows/regf/shimcache.py,sha256=4SHtwh-ajhgcyR2-vsBbjnsyBtEVPwlgk5j8e1TQkWM,9972
313
313
  dissect/target/plugins/os/windows/regf/trusteddocs.py,sha256=4g4m1FYljOpYqGG-7NGyj738Tfnz0uEaN2is2YzkMgg,3669
@@ -340,10 +340,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
340
340
  dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
341
341
  dissect/target/volumes/md.py,sha256=j1K1iKmspl0C_OJFc7-Q1BMWN2OCC5EVANIgVlJ_fIE,1673
342
342
  dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
343
- dissect.target-3.17.dev35.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
344
- dissect.target-3.17.dev35.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
345
- dissect.target-3.17.dev35.dist-info/METADATA,sha256=Dd4TxlQKuWjqnUY6nMqiEvR-YBsmXIbhGN6CLjdsGhI,11300
346
- dissect.target-3.17.dev35.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
347
- dissect.target-3.17.dev35.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
348
- dissect.target-3.17.dev35.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
349
- dissect.target-3.17.dev35.dist-info/RECORD,,
343
+ dissect.target-3.17.dev37.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
344
+ dissect.target-3.17.dev37.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
345
+ dissect.target-3.17.dev37.dist-info/METADATA,sha256=lG1EhM84cgxqVPODtlB_Ruvy2WmoUgjrea3a9pSWu20,11300
346
+ dissect.target-3.17.dev37.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
347
+ dissect.target-3.17.dev37.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
348
+ dissect.target-3.17.dev37.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
349
+ dissect.target-3.17.dev37.dist-info/RECORD,,