dfindexeddb 20240229__py3-none-any.whl → 20240301__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.
- dfindexeddb/cli.py +9 -1
- dfindexeddb/indexeddb/chromium.py +52 -29
- dfindexeddb/version.py +1 -1
- {dfindexeddb-20240229.dist-info → dfindexeddb-20240301.dist-info}/METADATA +1 -1
- {dfindexeddb-20240229.dist-info → dfindexeddb-20240301.dist-info}/RECORD +10 -10
- {dfindexeddb-20240229.dist-info → dfindexeddb-20240301.dist-info}/AUTHORS +0 -0
- {dfindexeddb-20240229.dist-info → dfindexeddb-20240301.dist-info}/LICENSE +0 -0
- {dfindexeddb-20240229.dist-info → dfindexeddb-20240301.dist-info}/WHEEL +0 -0
- {dfindexeddb-20240229.dist-info → dfindexeddb-20240301.dist-info}/entry_points.txt +0 -0
- {dfindexeddb-20240229.dist-info → dfindexeddb-20240301.dist-info}/top_level.txt +0 -0
dfindexeddb/cli.py
CHANGED
|
@@ -19,10 +19,12 @@ from datetime import datetime
|
|
|
19
19
|
import json
|
|
20
20
|
import pathlib
|
|
21
21
|
import sys
|
|
22
|
+
import traceback
|
|
22
23
|
|
|
23
24
|
from dfindexeddb.leveldb import log
|
|
24
25
|
from dfindexeddb.leveldb import ldb
|
|
25
26
|
from dfindexeddb.indexeddb import chromium
|
|
27
|
+
from dfindexeddb import errors
|
|
26
28
|
from dfindexeddb.indexeddb import v8
|
|
27
29
|
|
|
28
30
|
|
|
@@ -66,7 +68,13 @@ def IndexeddbCommand(args):
|
|
|
66
68
|
return
|
|
67
69
|
|
|
68
70
|
for record in records:
|
|
69
|
-
|
|
71
|
+
try:
|
|
72
|
+
record = chromium.IndexedDBRecord.FromLevelDBRecord(record)
|
|
73
|
+
except (errors.ParserError, errors.DecoderError) as err:
|
|
74
|
+
print(
|
|
75
|
+
(f'Error parsing blink value: {err} for {record.__class__.__name__} '
|
|
76
|
+
f'at offset {record.offset}'), file=sys.stderr)
|
|
77
|
+
print(f'Traceback: {traceback.format_exc()}', file=sys.stderr)
|
|
70
78
|
_Output(record, to_json=args.json)
|
|
71
79
|
|
|
72
80
|
|
|
@@ -17,8 +17,6 @@ from __future__ import annotations
|
|
|
17
17
|
from dataclasses import dataclass, field
|
|
18
18
|
from datetime import datetime
|
|
19
19
|
import io
|
|
20
|
-
import sys
|
|
21
|
-
import traceback
|
|
22
20
|
from typing import Any, BinaryIO, Optional, Tuple, Type, TypeVar, Union
|
|
23
21
|
|
|
24
22
|
from dfindexeddb import errors
|
|
@@ -406,7 +404,7 @@ class BaseIndexedDBKey:
|
|
|
406
404
|
The decoded key.
|
|
407
405
|
"""
|
|
408
406
|
decoder = utils.LevelDBDecoder(stream)
|
|
409
|
-
key_prefix = KeyPrefix.FromDecoder(decoder)
|
|
407
|
+
key_prefix = KeyPrefix.FromDecoder(decoder, base_offset=base_offset)
|
|
410
408
|
return cls.FromDecoder(
|
|
411
409
|
decoder=decoder, key_prefix=key_prefix, base_offset=base_offset)
|
|
412
410
|
|
|
@@ -963,6 +961,23 @@ class ObjectStoreMetaDataKey(BaseIndexedDBKey):
|
|
|
963
961
|
offset=base_offset + offset, key_prefix=key_prefix,
|
|
964
962
|
object_store_id=object_store_id, metadata_type=metadata_type)
|
|
965
963
|
|
|
964
|
+
@dataclass
|
|
965
|
+
class ObjectStoreDataValue:
|
|
966
|
+
"""The parsed values from an ObjectStoreDataKey.
|
|
967
|
+
|
|
968
|
+
Attributes:
|
|
969
|
+
unknown: an unknown integer (possibly a sequence number?).
|
|
970
|
+
is_wrapped: True if the value was wrapped.
|
|
971
|
+
blob_size: the blob size, only valid if wrapped.
|
|
972
|
+
blob_offset: the blob offset, only valid if wrapped.
|
|
973
|
+
value: the blink serialized value, only valid if not wrapped.
|
|
974
|
+
"""
|
|
975
|
+
unkown: int
|
|
976
|
+
is_wrapped: bool
|
|
977
|
+
blob_size: Optional[int]
|
|
978
|
+
blob_offset: Optional[int]
|
|
979
|
+
value: Any
|
|
980
|
+
|
|
966
981
|
|
|
967
982
|
@dataclass
|
|
968
983
|
class ObjectStoreDataKey(BaseIndexedDBKey):
|
|
@@ -974,11 +989,33 @@ class ObjectStoreDataKey(BaseIndexedDBKey):
|
|
|
974
989
|
encoded_user_key: IDBKey
|
|
975
990
|
|
|
976
991
|
def DecodeValue(
|
|
977
|
-
self, decoder: utils.LevelDBDecoder) ->
|
|
992
|
+
self, decoder: utils.LevelDBDecoder) -> ObjectStoreDataValue:
|
|
978
993
|
"""Decodes the object store data value."""
|
|
979
|
-
_,
|
|
980
|
-
|
|
981
|
-
|
|
994
|
+
_, unknown_integer = decoder.DecodeVarint()
|
|
995
|
+
|
|
996
|
+
_, wrapped_header_bytes = decoder.PeekBytes(3)
|
|
997
|
+
if len(wrapped_header_bytes) != 3:
|
|
998
|
+
raise errors.DecoderError('Insufficient bytes')
|
|
999
|
+
|
|
1000
|
+
if (wrapped_header_bytes[0] == definitions.BlinkSerializationTag.VERSION and
|
|
1001
|
+
wrapped_header_bytes[1] == 0x11 and
|
|
1002
|
+
wrapped_header_bytes[2] == 0x01):
|
|
1003
|
+
_, blob_size = decoder.DecodeVarint()
|
|
1004
|
+
_, blob_offset = decoder.DecodeVarint()
|
|
1005
|
+
return ObjectStoreDataValue(
|
|
1006
|
+
unkown=unknown_integer,
|
|
1007
|
+
is_wrapped=True,
|
|
1008
|
+
blob_size=blob_size,
|
|
1009
|
+
blob_offset=blob_offset,
|
|
1010
|
+
value=None)
|
|
1011
|
+
_, blink_bytes = decoder.ReadBytes()
|
|
1012
|
+
blink_value = blink.V8ScriptValueDecoder.FromBytes(blink_bytes)
|
|
1013
|
+
return ObjectStoreDataValue(
|
|
1014
|
+
unkown=unknown_integer,
|
|
1015
|
+
is_wrapped=False,
|
|
1016
|
+
blob_size=None,
|
|
1017
|
+
blob_offset=None,
|
|
1018
|
+
value=blink_value)
|
|
982
1019
|
|
|
983
1020
|
@classmethod
|
|
984
1021
|
def FromDecoder(
|
|
@@ -990,7 +1027,7 @@ class ObjectStoreDataKey(BaseIndexedDBKey):
|
|
|
990
1027
|
definitions.KeyPrefixType.OBJECT_STORE_DATA):
|
|
991
1028
|
raise errors.ParserError('Invalid KeyPrefix for ObjectStoreDataKey')
|
|
992
1029
|
offset = decoder.stream.tell()
|
|
993
|
-
encoded_user_key = IDBKey.FromDecoder(decoder,
|
|
1030
|
+
encoded_user_key = IDBKey.FromDecoder(decoder, offset)
|
|
994
1031
|
return cls(
|
|
995
1032
|
offset=base_offset + offset,
|
|
996
1033
|
key_prefix=key_prefix, encoded_user_key=encoded_user_key)
|
|
@@ -1017,7 +1054,7 @@ class ExistsEntryKey(BaseIndexedDBKey):
|
|
|
1017
1054
|
) -> ExistsEntryKey:
|
|
1018
1055
|
"""Decodes the exists entry key."""
|
|
1019
1056
|
offset = decoder.stream.tell()
|
|
1020
|
-
encoded_user_key = IDBKey.FromDecoder(decoder,
|
|
1057
|
+
encoded_user_key = IDBKey.FromDecoder(decoder, offset)
|
|
1021
1058
|
|
|
1022
1059
|
return cls(
|
|
1023
1060
|
offset=base_offset + offset,
|
|
@@ -1048,7 +1085,7 @@ class IndexDataKey(BaseIndexedDBKey):
|
|
|
1048
1085
|
base_offset: int = 0) -> IndexDataKey:
|
|
1049
1086
|
"""Decodes the index data key."""
|
|
1050
1087
|
offset = decoder.stream.tell()
|
|
1051
|
-
encoded_user_key = IDBKey.FromDecoder(decoder,
|
|
1088
|
+
encoded_user_key = IDBKey.FromDecoder(decoder, offset)
|
|
1052
1089
|
|
|
1053
1090
|
if decoder.NumRemainingBytes() > 0:
|
|
1054
1091
|
_, sequence_number = decoder.DecodeVarint()
|
|
@@ -1056,7 +1093,9 @@ class IndexDataKey(BaseIndexedDBKey):
|
|
|
1056
1093
|
sequence_number = None
|
|
1057
1094
|
|
|
1058
1095
|
if decoder.NumRemainingBytes() > 0:
|
|
1059
|
-
|
|
1096
|
+
encoded_primary_key_offset = decoder.stream.tell()
|
|
1097
|
+
encoded_primary_key = IDBKey.FromDecoder(
|
|
1098
|
+
decoder, encoded_primary_key_offset)
|
|
1060
1099
|
else:
|
|
1061
1100
|
encoded_primary_key = None
|
|
1062
1101
|
|
|
@@ -1089,7 +1128,7 @@ class BlobEntryKey(BaseIndexedDBKey):
|
|
|
1089
1128
|
) -> BlobEntryKey:
|
|
1090
1129
|
"""Decodes the blob entry key."""
|
|
1091
1130
|
offset = decoder.stream.tell()
|
|
1092
|
-
user_key = IDBKey.FromDecoder(decoder,
|
|
1131
|
+
user_key = IDBKey.FromDecoder(decoder, offset)
|
|
1093
1132
|
|
|
1094
1133
|
return cls(key_prefix=key_prefix, user_key=user_key,
|
|
1095
1134
|
offset=base_offset + offset)
|
|
@@ -1310,24 +1349,8 @@ class IndexedDBRecord:
|
|
|
1310
1349
|
cls, record: Union[ldb.LdbKeyValueRecord, log.ParsedInternalKey]
|
|
1311
1350
|
) -> IndexedDBRecord:
|
|
1312
1351
|
"""Returns an IndexedDBRecord from a ParsedInternalKey."""
|
|
1313
|
-
idb_key = IndexedDbKey.FromBytes(
|
|
1314
|
-
record.key, base_offset=record.offset)
|
|
1315
|
-
|
|
1352
|
+
idb_key = IndexedDbKey.FromBytes(record.key, base_offset=record.offset)
|
|
1316
1353
|
idb_value = idb_key.ParseValue(record.value)
|
|
1317
|
-
if isinstance(idb_key, ObjectStoreDataKey):
|
|
1318
|
-
|
|
1319
|
-
# The ObjectStoreDataKey value should decode as a 2-tuple comprising
|
|
1320
|
-
# a version integer and a SSV as a raw byte string
|
|
1321
|
-
if (isinstance(idb_value, tuple) and len(idb_value) == 2 and
|
|
1322
|
-
isinstance(idb_value[1], bytes)):
|
|
1323
|
-
|
|
1324
|
-
try:
|
|
1325
|
-
blink_value = blink.V8ScriptValueDecoder.FromBytes(idb_value[1])
|
|
1326
|
-
idb_value = idb_value[0], blink_value
|
|
1327
|
-
except (errors.ParserError, errors.DecoderError) as err:
|
|
1328
|
-
print(f'Error parsing blink value: {err}', file=sys.stderr)
|
|
1329
|
-
print(f'Traceback: {traceback.format_exc()}', file=sys.stderr)
|
|
1330
|
-
|
|
1331
1354
|
return cls(
|
|
1332
1355
|
offset=record.offset,
|
|
1333
1356
|
key=idb_key,
|
dfindexeddb/version.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dfindexeddb
|
|
3
|
-
Version:
|
|
3
|
+
Version: 20240301
|
|
4
4
|
Summary: dfindexeddb is an experimental Python tool for performing digital forensic analysis of IndexedDB and leveldb files.
|
|
5
5
|
Author-email: Syd Pleno <sydp@google.com>
|
|
6
6
|
Maintainer-email: dfIndexeddb Developers <dfindexeddb-dev@googlegroups.com>
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
dfindexeddb/__init__.py,sha256=KPYL9__l8od6_OyDfGRTgaJ6iy_fqIgZ-dS2S-e3Rac,599
|
|
2
|
-
dfindexeddb/cli.py,sha256=
|
|
2
|
+
dfindexeddb/cli.py,sha256=QsFPC_B_PW6E42kBPUO0Ny3oRspYJsXlDCQDHmKuDHQ,4866
|
|
3
3
|
dfindexeddb/errors.py,sha256=PNpwyf_lrPc4TE77oAakX3mu5D_YcP3f80wq8Y1LkvY,749
|
|
4
4
|
dfindexeddb/utils.py,sha256=g9iiGRX4DB1wFBSBHa6b9lg7JzAdE0SN0DrdB2aS_Co,10091
|
|
5
|
-
dfindexeddb/version.py,sha256=
|
|
5
|
+
dfindexeddb/version.py,sha256=d2fDd3V2U_CkGi3PawWMR77qU0DzHEC3_bk7Ywh3xlM,750
|
|
6
6
|
dfindexeddb/indexeddb/__init__.py,sha256=kExXSVBCTKCD5BZJkdMfUMqGksH-DMJxP2_lI0gq-BE,575
|
|
7
7
|
dfindexeddb/indexeddb/blink.py,sha256=MblpYfv-ByG7n_fjYKu2EUhpfVJdUveoW4oSAg5T4tY,3534
|
|
8
|
-
dfindexeddb/indexeddb/chromium.py,sha256=
|
|
8
|
+
dfindexeddb/indexeddb/chromium.py,sha256=oHHyGuy7BanRWRoJu4zqXo5QvxO2j_qLk2KMHBBwZvs,44692
|
|
9
9
|
dfindexeddb/indexeddb/definitions.py,sha256=yline3y3gmZx6s-dwjpPDNs5HO4zT6KZqPWQfEsHDoM,7413
|
|
10
10
|
dfindexeddb/indexeddb/v8.py,sha256=ldqpc9T1kG7BOdjnHjQ5hNO9OCXZ3_Zd6vRSpC-NrEA,21893
|
|
11
11
|
dfindexeddb/leveldb/__init__.py,sha256=KPYL9__l8od6_OyDfGRTgaJ6iy_fqIgZ-dS2S-e3Rac,599
|
|
12
12
|
dfindexeddb/leveldb/ldb.py,sha256=uShhXjQe4Sz3dn54IXbGxRtE6D8RNpu1NDy5Zb0P9LA,7927
|
|
13
13
|
dfindexeddb/leveldb/log.py,sha256=cyMfjDz5a6gfGb5NonxC1Y72OmHYBWzYK8UMVzP_umw,8532
|
|
14
|
-
dfindexeddb-
|
|
15
|
-
dfindexeddb-
|
|
16
|
-
dfindexeddb-
|
|
17
|
-
dfindexeddb-
|
|
18
|
-
dfindexeddb-
|
|
19
|
-
dfindexeddb-
|
|
20
|
-
dfindexeddb-
|
|
14
|
+
dfindexeddb-20240301.dist-info/AUTHORS,sha256=QbvjbAom57fpEkekkCVFUj0B9KUMGraR510aUMBC-PE,286
|
|
15
|
+
dfindexeddb-20240301.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
16
|
+
dfindexeddb-20240301.dist-info/METADATA,sha256=AYggbgjQv3dNPwO-f3e7tK3EPvKsnlNTKM2nPTbAQYg,15933
|
|
17
|
+
dfindexeddb-20240301.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
18
|
+
dfindexeddb-20240301.dist-info/entry_points.txt,sha256=UsfPLLhTiVAAtZ8Rq3ZR7JNFGMuHqJy-tugGWonQWtc,52
|
|
19
|
+
dfindexeddb-20240301.dist-info/top_level.txt,sha256=X9OTaub1c8S_JJ7g-f8JdkhhdiZ4x1j4eni1hdUCwE4,12
|
|
20
|
+
dfindexeddb-20240301.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|