dissect.target 3.17.dev35__py3-none-any.whl → 3.17.dev36__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.
@@ -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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.17.dev35
3
+ Version: 3.17.dev36
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
@@ -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
@@ -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.dev36.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
344
+ dissect.target-3.17.dev36.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
345
+ dissect.target-3.17.dev36.dist-info/METADATA,sha256=jvQ5nLWplAsNNZMyR1nIBwBQZEe-FnQRkk56_YpDAtw,11300
346
+ dissect.target-3.17.dev36.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
347
+ dissect.target-3.17.dev36.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
348
+ dissect.target-3.17.dev36.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
349
+ dissect.target-3.17.dev36.dist-info/RECORD,,