dissect.target 3.16.dev11__py3-none-any.whl → 3.16.dev13__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- dissect/target/plugin.py +6 -1
- dissect/target/plugins/apps/browser/browser.py +1 -0
- dissect/target/plugins/apps/browser/chrome.py +1 -2
- dissect/target/plugins/apps/browser/chromium.py +100 -99
- dissect/target/plugins/apps/browser/edge.py +1 -2
- dissect/target/plugins/apps/browser/firefox.py +1 -0
- {dissect.target-3.16.dev11.dist-info → dissect.target-3.16.dev13.dist-info}/METADATA +1 -1
- {dissect.target-3.16.dev11.dist-info → dissect.target-3.16.dev13.dist-info}/RECORD +13 -13
- {dissect.target-3.16.dev11.dist-info → dissect.target-3.16.dev13.dist-info}/COPYRIGHT +0 -0
- {dissect.target-3.16.dev11.dist-info → dissect.target-3.16.dev13.dist-info}/LICENSE +0 -0
- {dissect.target-3.16.dev11.dist-info → dissect.target-3.16.dev13.dist-info}/WHEEL +0 -0
- {dissect.target-3.16.dev11.dist-info → dissect.target-3.16.dev13.dist-info}/entry_points.txt +0 -0
- {dissect.target-3.16.dev11.dist-info → dissect.target-3.16.dev13.dist-info}/top_level.txt +0 -0
dissect/target/plugin.py
CHANGED
@@ -1118,7 +1118,12 @@ def plugin_function_index(target: Optional[Target]) -> tuple[dict[str, PluginDes
|
|
1118
1118
|
# The get_all_records does not only need to be not present in the
|
1119
1119
|
# index, it also needs to be removed from the exports list, else
|
1120
1120
|
# the 'plugins' plugin will still display them.
|
1121
|
-
available["exports"].
|
1121
|
+
exports = available["exports"].copy()
|
1122
|
+
exports.remove("get_all_records")
|
1123
|
+
available["exports"] = exports
|
1124
|
+
|
1125
|
+
if "get_all_records" not in available_original["exports"]:
|
1126
|
+
raise Exception(f"get_all_records removed from {available_original}")
|
1122
1127
|
|
1123
1128
|
for exported in available["exports"]:
|
1124
1129
|
if available["is_osplugin"] and os_type == general.default.DefaultPlugin:
|
@@ -38,8 +38,7 @@ class ChromePlugin(ChromiumMixin, BrowserPlugin):
|
|
38
38
|
)
|
39
39
|
|
40
40
|
BrowserCookieRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
|
41
|
-
"browser/chrome/cookie",
|
42
|
-
GENERIC_COOKIE_FIELDS,
|
41
|
+
"browser/chrome/cookie", GENERIC_COOKIE_FIELDS
|
43
42
|
)
|
44
43
|
|
45
44
|
BrowserDownloadRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
|
@@ -117,59 +117,60 @@ class ChromiumMixin:
|
|
117
117
|
if not len(self._build_userdirs(self.DIRS)):
|
118
118
|
raise UnsupportedPluginError("No Chromium-based browser directories found")
|
119
119
|
|
120
|
-
def
|
121
|
-
"""Return browser
|
120
|
+
def history(self, browser_name: Optional[str] = None) -> Iterator[BrowserHistoryRecord]:
|
121
|
+
"""Return browser history records from supported Chromium-based browsers.
|
122
122
|
|
123
123
|
Args:
|
124
124
|
browser_name: The name of the browser as a string.
|
125
125
|
|
126
126
|
Yields:
|
127
127
|
Records with the following fields:
|
128
|
-
|
129
|
-
ts_end (datetime): Download end timestamp.
|
128
|
+
ts (datetime): Visit timestamp.
|
130
129
|
browser (string): The browser from which the records are generated from.
|
131
130
|
id (string): Record ID.
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
131
|
+
url (uri): History URL.
|
132
|
+
title (string): Page title.
|
133
|
+
description (string): Page description.
|
134
|
+
rev_host (string): Reverse hostname.
|
135
|
+
visit_type (varint): Visit type.
|
136
|
+
visit_count (varint): Amount of visits.
|
137
|
+
hidden (string): Hidden value.
|
138
|
+
typed (string): Typed value.
|
139
|
+
session (varint): Session value.
|
140
|
+
from_visit (varint): Record ID of the "from" visit.
|
141
|
+
from_url (uri): URL of the "from" visit.
|
142
|
+
source: (path): The source file of the history record.
|
140
143
|
"""
|
141
144
|
for user, db_file, db in self._iter_db("History"):
|
142
145
|
try:
|
143
|
-
|
144
|
-
|
145
|
-
download_chains[row.id].append(row)
|
146
|
-
|
147
|
-
for chain in download_chains.values():
|
148
|
-
chain.sort(key=lambda row: row.chain_index)
|
149
|
-
|
150
|
-
for row in db.table("downloads").rows():
|
151
|
-
if download_path := row.target_path:
|
152
|
-
download_path = self.target.fs.path(download_path)
|
146
|
+
urls = {row.id: row for row in db.table("urls").rows()}
|
147
|
+
visits = {}
|
153
148
|
|
154
|
-
|
155
|
-
|
149
|
+
for row in db.table("visits").rows():
|
150
|
+
visits[row.id] = row
|
151
|
+
url = urls[row.url]
|
156
152
|
|
157
|
-
if
|
158
|
-
|
159
|
-
|
153
|
+
if row.from_visit and row.from_visit in visits:
|
154
|
+
from_visit = visits[row.from_visit]
|
155
|
+
from_url = urls[from_visit.url]
|
156
|
+
else:
|
157
|
+
from_visit, from_url = None, None
|
160
158
|
|
161
|
-
yield self.
|
162
|
-
|
163
|
-
ts_end=webkittimestamp(row.end_time) if row.end_time else None,
|
159
|
+
yield self.BrowserHistoryRecord(
|
160
|
+
ts=webkittimestamp(row.visit_time),
|
164
161
|
browser=browser_name,
|
165
|
-
id=row.
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
162
|
+
id=row.id,
|
163
|
+
url=try_idna(url.url),
|
164
|
+
title=url.title,
|
165
|
+
description=None,
|
166
|
+
rev_host=None,
|
167
|
+
visit_type=None,
|
168
|
+
visit_count=url.visit_count,
|
169
|
+
hidden=url.hidden,
|
170
|
+
typed=None,
|
171
|
+
session=None,
|
172
|
+
from_visit=row.from_visit or None,
|
173
|
+
from_url=try_idna(from_url.url) if from_url else None,
|
173
174
|
source=db_file,
|
174
175
|
_target=self.target,
|
175
176
|
_user=user,
|
@@ -212,11 +213,72 @@ class ChromiumMixin:
|
|
212
213
|
is_secure=bool(cookie.is_secure),
|
213
214
|
is_http_only=bool(cookie.is_httponly),
|
214
215
|
same_site=bool(cookie.samesite),
|
216
|
+
source=db_file,
|
215
217
|
_user=user,
|
216
218
|
)
|
217
219
|
except SQLError as e:
|
218
220
|
self.target.log.warning("Error processing cookie file: %s", db_file, exc_info=e)
|
219
221
|
|
222
|
+
def downloads(self, browser_name: Optional[str] = None) -> Iterator[BrowserDownloadRecord]:
|
223
|
+
"""Return browser download records from supported Chromium-based browsers.
|
224
|
+
|
225
|
+
Args:
|
226
|
+
browser_name: The name of the browser as a string.
|
227
|
+
|
228
|
+
Yields:
|
229
|
+
Records with the following fields:
|
230
|
+
ts_start (datetime): Download start timestamp.
|
231
|
+
ts_end (datetime): Download end timestamp.
|
232
|
+
browser (string): The browser from which the records are generated from.
|
233
|
+
id (string): Record ID.
|
234
|
+
path (string): Download path.
|
235
|
+
url (uri): Download URL.
|
236
|
+
tab_url (string): Tab URL.
|
237
|
+
tab_referrer_url (string): Referrer URL.
|
238
|
+
size (varint): Download file size.
|
239
|
+
mime_type (string): MIME type.
|
240
|
+
state (varint): Download state number.
|
241
|
+
source: (path): The source file of the download record.
|
242
|
+
"""
|
243
|
+
for user, db_file, db in self._iter_db("History"):
|
244
|
+
try:
|
245
|
+
download_chains = defaultdict(list)
|
246
|
+
for row in db.table("downloads_url_chains"):
|
247
|
+
download_chains[row.id].append(row)
|
248
|
+
|
249
|
+
for chain in download_chains.values():
|
250
|
+
chain.sort(key=lambda row: row.chain_index)
|
251
|
+
|
252
|
+
for row in db.table("downloads").rows():
|
253
|
+
if download_path := row.target_path:
|
254
|
+
download_path = self.target.fs.path(download_path)
|
255
|
+
|
256
|
+
url = None
|
257
|
+
download_chain = download_chains.get(row.id)
|
258
|
+
|
259
|
+
if download_chain:
|
260
|
+
url = download_chain[-1].url
|
261
|
+
url = try_idna(url)
|
262
|
+
|
263
|
+
yield self.BrowserDownloadRecord(
|
264
|
+
ts_start=webkittimestamp(row.start_time),
|
265
|
+
ts_end=webkittimestamp(row.end_time) if row.end_time else None,
|
266
|
+
browser=browser_name,
|
267
|
+
id=row.get("id"),
|
268
|
+
tab_url=try_idna(row.get("tab_url")),
|
269
|
+
tab_referrer_url=try_idna(row.get("tab_referrer_url")),
|
270
|
+
path=download_path,
|
271
|
+
url=url,
|
272
|
+
size=row.get("total_bytes"),
|
273
|
+
mime_type=row.get("mime_type"),
|
274
|
+
state=row.get("state"),
|
275
|
+
source=db_file,
|
276
|
+
_target=self.target,
|
277
|
+
_user=user,
|
278
|
+
)
|
279
|
+
except SQLError as e:
|
280
|
+
self.target.log.warning("Error processing history file: %s", db_file, exc_info=e)
|
281
|
+
|
220
282
|
def extensions(self, browser_name: Optional[str] = None) -> Iterator[BrowserExtensionRecord]:
|
221
283
|
"""Iterates over all installed extensions for a given browser.
|
222
284
|
|
@@ -303,67 +365,6 @@ class ChromiumMixin:
|
|
303
365
|
except (AttributeError, KeyError) as e:
|
304
366
|
self.target.log.info("No browser extensions found in: %s", json_file, exc_info=e)
|
305
367
|
|
306
|
-
def history(self, browser_name: Optional[str] = None) -> Iterator[BrowserHistoryRecord]:
|
307
|
-
"""Return browser history records from supported Chromium-based browsers.
|
308
|
-
|
309
|
-
Args:
|
310
|
-
browser_name: The name of the browser as a string.
|
311
|
-
|
312
|
-
Yields:
|
313
|
-
Records with the following fields:
|
314
|
-
ts (datetime): Visit timestamp.
|
315
|
-
browser (string): The browser from which the records are generated from.
|
316
|
-
id (string): Record ID.
|
317
|
-
url (uri): History URL.
|
318
|
-
title (string): Page title.
|
319
|
-
description (string): Page description.
|
320
|
-
rev_host (string): Reverse hostname.
|
321
|
-
visit_type (varint): Visit type.
|
322
|
-
visit_count (varint): Amount of visits.
|
323
|
-
hidden (string): Hidden value.
|
324
|
-
typed (string): Typed value.
|
325
|
-
session (varint): Session value.
|
326
|
-
from_visit (varint): Record ID of the "from" visit.
|
327
|
-
from_url (uri): URL of the "from" visit.
|
328
|
-
source: (path): The source file of the history record.
|
329
|
-
"""
|
330
|
-
for user, db_file, db in self._iter_db("History"):
|
331
|
-
try:
|
332
|
-
urls = {row.id: row for row in db.table("urls").rows()}
|
333
|
-
visits = {}
|
334
|
-
|
335
|
-
for row in db.table("visits").rows():
|
336
|
-
visits[row.id] = row
|
337
|
-
url = urls[row.url]
|
338
|
-
|
339
|
-
if row.from_visit and row.from_visit in visits:
|
340
|
-
from_visit = visits[row.from_visit]
|
341
|
-
from_url = urls[from_visit.url]
|
342
|
-
else:
|
343
|
-
from_visit, from_url = None, None
|
344
|
-
|
345
|
-
yield self.BrowserHistoryRecord(
|
346
|
-
ts=webkittimestamp(row.visit_time),
|
347
|
-
browser=browser_name,
|
348
|
-
id=row.id,
|
349
|
-
url=try_idna(url.url),
|
350
|
-
title=url.title,
|
351
|
-
description=None,
|
352
|
-
rev_host=None,
|
353
|
-
visit_type=None,
|
354
|
-
visit_count=url.visit_count,
|
355
|
-
hidden=url.hidden,
|
356
|
-
typed=None,
|
357
|
-
session=None,
|
358
|
-
from_visit=row.from_visit or None,
|
359
|
-
from_url=try_idna(from_url.url) if from_url else None,
|
360
|
-
source=db_file,
|
361
|
-
_target=self.target,
|
362
|
-
_user=user,
|
363
|
-
)
|
364
|
-
except SQLError as e:
|
365
|
-
self.target.log.warning("Error processing history file: %s", db_file, exc_info=e)
|
366
|
-
|
367
368
|
|
368
369
|
class ChromiumPlugin(ChromiumMixin, BrowserPlugin):
|
369
370
|
"""Chromium browser plugin."""
|
@@ -36,8 +36,7 @@ class EdgePlugin(ChromiumMixin, BrowserPlugin):
|
|
36
36
|
)
|
37
37
|
|
38
38
|
BrowserCookieRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
|
39
|
-
"browser/edge/cookie",
|
40
|
-
GENERIC_COOKIE_FIELDS,
|
39
|
+
"browser/edge/cookie", GENERIC_COOKIE_FIELDS
|
41
40
|
)
|
42
41
|
|
43
42
|
BrowserDownloadRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: dissect.target
|
3
|
-
Version: 3.16.
|
3
|
+
Version: 3.16.dev13
|
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
|
@@ -3,7 +3,7 @@ dissect/target/container.py,sha256=9ixufT1_0WhraqttBWwQjG80caToJqvCX8VjFk8d5F0,9
|
|
3
3
|
dissect/target/exceptions.py,sha256=VVW_Rq_vQinapz-2mbJ3UkxBEZpb2pE_7JlhMukdtrY,2877
|
4
4
|
dissect/target/filesystem.py,sha256=aLkvZMgeah39Nhlscawh77cm2mzFYI9J5h3uT3Rigtc,53876
|
5
5
|
dissect/target/loader.py,sha256=0-LcZNi7S0qsXR7XGtrzxpuCh9BsLcqNR1T15O7SnBM,7257
|
6
|
-
dissect/target/plugin.py,sha256=
|
6
|
+
dissect/target/plugin.py,sha256=ndqz4RpbBCN6wagCBvfHzHkL0l0-gnbHjc7c8Blite4,48473
|
7
7
|
dissect/target/report.py,sha256=06uiP4MbNI8cWMVrC1SasNS-Yg6ptjVjckwj8Yhe0Js,7958
|
8
8
|
dissect/target/target.py,sha256=HxqqnGW0i0Y4a6Q4DjgNmqkJmJ-_IrkvksNgSPwa7LI,32143
|
9
9
|
dissect/target/volume.py,sha256=aQZAJiny8jjwkc9UtwIRwy7nINXjCxwpO-_UDfh6-BA,15801
|
@@ -112,11 +112,11 @@ dissect/target/plugins/apps/av/sophos.py,sha256=gSfTvjBZMuT0hsL-p4oYxuYmakbqApoO
|
|
112
112
|
dissect/target/plugins/apps/av/symantec.py,sha256=RFLyNW6FyuoGcirJ4xHbQM8oGjua9W4zXmC7YDF-H20,14109
|
113
113
|
dissect/target/plugins/apps/av/trendmicro.py,sha256=jloy_N4hHAqF1sVIEeD5Q7LRYal3_os14Umk-hGaAR4,4613
|
114
114
|
dissect/target/plugins/apps/browser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
115
|
-
dissect/target/plugins/apps/browser/browser.py,sha256=
|
116
|
-
dissect/target/plugins/apps/browser/chrome.py,sha256=
|
117
|
-
dissect/target/plugins/apps/browser/chromium.py,sha256=
|
118
|
-
dissect/target/plugins/apps/browser/edge.py,sha256=
|
119
|
-
dissect/target/plugins/apps/browser/firefox.py,sha256=
|
115
|
+
dissect/target/plugins/apps/browser/browser.py,sha256=_QP1u57-wOSiLvpTUotWDpqBdRn-WEWpBDzCMqZTYO0,2682
|
116
|
+
dissect/target/plugins/apps/browser/chrome.py,sha256=XMDq3v-fA0W16gm5jXryP73PEtF7bRw5Pfqy5JQd-U8,2635
|
117
|
+
dissect/target/plugins/apps/browser/chromium.py,sha256=Y1sS0EqF5F5abpLXNog2HwI5QV5d3qnBvZMnE0MPdyU,17774
|
118
|
+
dissect/target/plugins/apps/browser/edge.py,sha256=cjMbAGtlTVyJLuha3D0uNbai0mJnkXmp6d0gBfceWB4,2473
|
119
|
+
dissect/target/plugins/apps/browser/firefox.py,sha256=6dUTNfclNTsqB_GA-4q38tyHPuiw8lgNEmmtfIWbMUY,11373
|
120
120
|
dissect/target/plugins/apps/browser/iexplore.py,sha256=LUXXCjMBBFcFN2ceBpks8qM1PyOvrBPn1guA4WM4oSU,8706
|
121
121
|
dissect/target/plugins/apps/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
122
122
|
dissect/target/plugins/apps/container/docker.py,sha256=guFPqRLbeP4p8R6lDIZVKWnva5_S7rQUVKG21QDz-B4,6416
|
@@ -323,10 +323,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
|
|
323
323
|
dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
|
324
324
|
dissect/target/volumes/md.py,sha256=j1K1iKmspl0C_OJFc7-Q1BMWN2OCC5EVANIgVlJ_fIE,1673
|
325
325
|
dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
|
326
|
-
dissect.target-3.16.
|
327
|
-
dissect.target-3.16.
|
328
|
-
dissect.target-3.16.
|
329
|
-
dissect.target-3.16.
|
330
|
-
dissect.target-3.16.
|
331
|
-
dissect.target-3.16.
|
332
|
-
dissect.target-3.16.
|
326
|
+
dissect.target-3.16.dev13.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
|
327
|
+
dissect.target-3.16.dev13.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
328
|
+
dissect.target-3.16.dev13.dist-info/METADATA,sha256=3C3Z4nrLFNTsMdbf_ij7Tjztn8Yra3gKF232itkAgmM,11113
|
329
|
+
dissect.target-3.16.dev13.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
330
|
+
dissect.target-3.16.dev13.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
|
331
|
+
dissect.target-3.16.dev13.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
|
332
|
+
dissect.target-3.16.dev13.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
{dissect.target-3.16.dev11.dist-info → dissect.target-3.16.dev13.dist-info}/entry_points.txt
RENAMED
File without changes
|
File without changes
|