dissect.database 1.2.dev5__py3-none-any.whl → 1.2.dev7__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.
- dissect/database/ese/ese.py +1 -1
- dissect/database/ese/ntds/database.py +68 -52
- dissect/database/ese/ntds/ntds.py +7 -7
- dissect/database/ese/ntds/objects/ntdsdsa.py +13 -1
- dissect/database/ese/ntds/objects/server.py +7 -1
- dissect/database/ese/ntds/query.py +4 -1
- dissect/database/ese/ntds/schema.py +2 -2
- dissect/database/ese/ntds/util.py +24 -7
- dissect/database/sqlite3/sqlite3.py +2 -1
- {dissect_database-1.2.dev5.dist-info → dissect_database-1.2.dev7.dist-info}/METADATA +1 -1
- {dissect_database-1.2.dev5.dist-info → dissect_database-1.2.dev7.dist-info}/RECORD +16 -16
- {dissect_database-1.2.dev5.dist-info → dissect_database-1.2.dev7.dist-info}/WHEEL +0 -0
- {dissect_database-1.2.dev5.dist-info → dissect_database-1.2.dev7.dist-info}/entry_points.txt +0 -0
- {dissect_database-1.2.dev5.dist-info → dissect_database-1.2.dev7.dist-info}/licenses/COPYRIGHT +0 -0
- {dissect_database-1.2.dev5.dist-info → dissect_database-1.2.dev7.dist-info}/licenses/LICENSE +0 -0
- {dissect_database-1.2.dev5.dist-info → dissect_database-1.2.dev7.dist-info}/top_level.txt +0 -0
dissect/database/ese/ese.py
CHANGED
|
@@ -31,7 +31,7 @@ class ESE:
|
|
|
31
31
|
impacket_compat: Whether to make the output impacket compatible.
|
|
32
32
|
|
|
33
33
|
Raises:
|
|
34
|
-
InvalidDatabase: If the file-like object does not look like an ESE database.
|
|
34
|
+
~dissect.database.ese.exception.InvalidDatabase: If the file-like object does not look like an ESE database.
|
|
35
35
|
"""
|
|
36
36
|
|
|
37
37
|
def __init__(self, fh: BinaryIO, impacket_compat: bool = False):
|
|
@@ -6,18 +6,18 @@ from typing import TYPE_CHECKING, BinaryIO
|
|
|
6
6
|
|
|
7
7
|
from dissect.database.ese.ese import ESE
|
|
8
8
|
from dissect.database.ese.exception import KeyNotFoundError
|
|
9
|
-
from dissect.database.ese.ntds.objects import
|
|
9
|
+
from dissect.database.ese.ntds.objects import Object
|
|
10
10
|
from dissect.database.ese.ntds.pek import PEK
|
|
11
11
|
from dissect.database.ese.ntds.query import Query
|
|
12
12
|
from dissect.database.ese.ntds.schema import Schema
|
|
13
13
|
from dissect.database.ese.ntds.sd import SecurityDescriptor
|
|
14
|
-
from dissect.database.ese.ntds.util import DN, SearchFlags, encode_value
|
|
14
|
+
from dissect.database.ese.ntds.util import DN, DatabaseFlags, SearchFlags, encode_value
|
|
15
15
|
|
|
16
16
|
if TYPE_CHECKING:
|
|
17
17
|
from collections.abc import Iterator
|
|
18
18
|
|
|
19
19
|
from dissect.database.ese.index import Index
|
|
20
|
-
from dissect.database.ese.ntds.objects import DMD, NTDSDSA, Top
|
|
20
|
+
from dissect.database.ese.ntds.objects import DMD, NTDSDSA, DomainDNS, Server, Top
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class Database:
|
|
@@ -34,78 +34,91 @@ class Database:
|
|
|
34
34
|
self.link = LinkTable(self)
|
|
35
35
|
self.sd = SecurityDescriptorTable(self)
|
|
36
36
|
|
|
37
|
-
self.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class DataTable:
|
|
41
|
-
"""Represents the ``datatable`` in the NTDS database."""
|
|
42
|
-
|
|
43
|
-
def __init__(self, db: Database):
|
|
44
|
-
self.db = db
|
|
45
|
-
self.table = self.db.ese.table("datatable")
|
|
46
|
-
self.hiddentable = self.db.ese.table("hiddentable")
|
|
37
|
+
self.hiddentable = self.ese.table("hiddentable")
|
|
47
38
|
self.hiddeninfo = next(self.hiddentable.records(), None)
|
|
48
39
|
|
|
49
|
-
self.schema
|
|
50
|
-
|
|
51
|
-
# Cache frequently used and "expensive" methods
|
|
52
|
-
self.get = lru_cache(4096)(self.get)
|
|
53
|
-
self._make_dn = lru_cache(4096)(self._make_dn)
|
|
54
|
-
|
|
55
|
-
def dsa(self) -> NTDSDSA:
|
|
56
|
-
"""Return the Directory System Agent (DSA) object."""
|
|
57
|
-
if not self.hiddeninfo:
|
|
58
|
-
raise ValueError("No hiddentable information available")
|
|
59
|
-
return self.get(self.hiddeninfo.get("dsa_col"))
|
|
60
|
-
|
|
61
|
-
def dmd(self) -> DMD:
|
|
62
|
-
"""Return the Directory Management Domain (DMD) object, a.k.a. the schema container."""
|
|
63
|
-
if not self.hiddeninfo:
|
|
64
|
-
raise ValueError("No hiddentable information available")
|
|
65
|
-
return self.get(self.dsa().get("dMDLocation", raw=True))
|
|
66
|
-
|
|
67
|
-
def root(self) -> Top:
|
|
68
|
-
"""Return the top-level object in the NTDS database."""
|
|
69
|
-
if (root := next(self.children_of(0), None)) is None:
|
|
70
|
-
raise ValueError("No root object found")
|
|
71
|
-
return root
|
|
40
|
+
self.data.schema.load(self)
|
|
72
41
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
while stack:
|
|
77
|
-
if (obj := stack.pop()).is_deleted:
|
|
78
|
-
continue
|
|
42
|
+
# Clear the cache of the data table to avoid caching results before the schema is loaded
|
|
43
|
+
self.data.get.cache_clear()
|
|
44
|
+
self.data._make_dn.cache_clear()
|
|
79
45
|
|
|
80
|
-
|
|
81
|
-
|
|
46
|
+
@cached_property
|
|
47
|
+
def flags(self) -> DatabaseFlags | None:
|
|
48
|
+
"""Return the database flags."""
|
|
49
|
+
if self.hiddeninfo is None:
|
|
50
|
+
return None
|
|
82
51
|
|
|
83
|
-
|
|
52
|
+
result = DatabaseFlags(0)
|
|
53
|
+
flags = self.hiddeninfo.get("flags_col")
|
|
54
|
+
for idx, member in enumerate(DatabaseFlags.__members__.values()):
|
|
55
|
+
if flags[idx] == ord(b"1"):
|
|
56
|
+
result = member if result is None else result | member
|
|
84
57
|
|
|
85
|
-
return
|
|
58
|
+
return result
|
|
86
59
|
|
|
87
60
|
@cached_property
|
|
88
61
|
def pek(self) -> PEK | None:
|
|
89
62
|
"""Return the PEK."""
|
|
90
|
-
if (
|
|
63
|
+
if (domain := self.domain()) is None:
|
|
91
64
|
# Maybe this is an AD LDS database
|
|
92
|
-
if (root_pek := self.root().get("pekList")) is None:
|
|
65
|
+
if (root_pek := self.data.root().get("pekList")) is None:
|
|
93
66
|
# It's not
|
|
94
67
|
return None
|
|
95
68
|
|
|
96
69
|
# Lookup the schema pek and permutate the boot key
|
|
97
70
|
# https://www.synacktiv.com/publications/using-ntdissector-to-extract-secrets-from-adam-ntds-files
|
|
98
|
-
schema_pek = self.
|
|
71
|
+
schema_pek = self.dmd().get("pekList")
|
|
99
72
|
boot_key = bytes(
|
|
100
73
|
[root_pek[i] for i in [2, 4, 25, 9, 7, 27, 5, 11]]
|
|
101
74
|
+ [schema_pek[i] for i in [37, 2, 17, 36, 20, 11, 22, 7]]
|
|
102
75
|
)
|
|
103
76
|
|
|
104
77
|
# Lookup the actual PEK and unlock it
|
|
105
|
-
pek = PEK(self.
|
|
78
|
+
pek = PEK(self.dmd().parent().get("pekList"))
|
|
106
79
|
pek.unlock(boot_key)
|
|
107
80
|
return pek
|
|
108
|
-
|
|
81
|
+
|
|
82
|
+
return domain.pek
|
|
83
|
+
|
|
84
|
+
def dsa(self) -> NTDSDSA:
|
|
85
|
+
"""Return the Directory System Agent (DSA) object, a.k.a. the NTDS Settings object."""
|
|
86
|
+
if not self.hiddeninfo:
|
|
87
|
+
raise ValueError("No hiddentable information available")
|
|
88
|
+
return self.data.get(self.hiddeninfo.get("dsa_col"))
|
|
89
|
+
|
|
90
|
+
def dmd(self) -> DMD:
|
|
91
|
+
"""Return the Directory Management Domain (DMD) object, a.k.a. the schema container."""
|
|
92
|
+
if not self.hiddeninfo:
|
|
93
|
+
raise ValueError("No hiddentable information available")
|
|
94
|
+
return self.data.get(self.dsa().get("dMDLocation", raw=True))
|
|
95
|
+
|
|
96
|
+
def dc(self) -> Server:
|
|
97
|
+
"""Return the Domain Controller (DC) server object that corresponds to this NTDS database."""
|
|
98
|
+
return self.dsa().parent()
|
|
99
|
+
|
|
100
|
+
def domain(self) -> DomainDNS | None:
|
|
101
|
+
"""Return the root domain object in the NTDS database. For AD LDS (ADAM), this will return ``None``."""
|
|
102
|
+
return self.dsa().domain()
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class DataTable:
|
|
106
|
+
"""Represents the ``datatable`` in the NTDS database."""
|
|
107
|
+
|
|
108
|
+
def __init__(self, db: Database):
|
|
109
|
+
self.db = db
|
|
110
|
+
self.table = self.db.ese.table("datatable")
|
|
111
|
+
self.schema = Schema()
|
|
112
|
+
|
|
113
|
+
# Cache frequently used and "expensive" methods
|
|
114
|
+
self.get = lru_cache(4096)(self.get)
|
|
115
|
+
self._make_dn = lru_cache(4096)(self._make_dn)
|
|
116
|
+
|
|
117
|
+
def root(self) -> Top:
|
|
118
|
+
"""Return the top-level object in the NTDS database."""
|
|
119
|
+
if (root := next(self.children_of(0), None)) is None:
|
|
120
|
+
raise ValueError("No root object found")
|
|
121
|
+
return root
|
|
109
122
|
|
|
110
123
|
def walk(self) -> Iterator[Object]:
|
|
111
124
|
"""Walk through all objects in the NTDS database."""
|
|
@@ -201,8 +214,11 @@ class DataTable:
|
|
|
201
214
|
cursor.seek([dnt])
|
|
202
215
|
|
|
203
216
|
record = cursor.record()
|
|
204
|
-
while record is not None
|
|
217
|
+
while record is not None:
|
|
205
218
|
yield Object.from_record(self.db, record)
|
|
219
|
+
if record == end:
|
|
220
|
+
break
|
|
221
|
+
|
|
206
222
|
record = cursor.next()
|
|
207
223
|
|
|
208
224
|
def _make_dn(self, dnt: int) -> DN:
|
|
@@ -41,18 +41,18 @@ class NTDS:
|
|
|
41
41
|
def __init__(self, fh: BinaryIO):
|
|
42
42
|
self.db = Database(fh)
|
|
43
43
|
|
|
44
|
+
@property
|
|
45
|
+
def pek(self) -> PEK | None:
|
|
46
|
+
"""Return the PEK associated with the root domain."""
|
|
47
|
+
return self.db.pek
|
|
48
|
+
|
|
44
49
|
def root(self) -> Object:
|
|
45
50
|
"""Return the root object of the Active Directory."""
|
|
46
51
|
return self.db.data.root()
|
|
47
52
|
|
|
48
|
-
def
|
|
53
|
+
def domain(self) -> DomainDNS | None:
|
|
49
54
|
"""Return the root domain object of the Active Directory."""
|
|
50
|
-
return self.db.
|
|
51
|
-
|
|
52
|
-
@property
|
|
53
|
-
def pek(self) -> PEK | None:
|
|
54
|
-
"""Return the PEK associated with the root domain."""
|
|
55
|
-
return self.db.data.pek
|
|
55
|
+
return self.db.domain()
|
|
56
56
|
|
|
57
57
|
def walk(self) -> Iterator[Object]:
|
|
58
58
|
"""Walk through all objects in the NTDS database."""
|
|
@@ -7,7 +7,7 @@ from dissect.database.ese.ntds.objects.applicationsettings import ApplicationSet
|
|
|
7
7
|
if TYPE_CHECKING:
|
|
8
8
|
from collections.abc import Iterator
|
|
9
9
|
|
|
10
|
-
from dissect.database.ese.ntds.objects import Object
|
|
10
|
+
from dissect.database.ese.ntds.objects import DomainDNS, MSDSOptionalFeature, Object
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class NTDSDSA(ApplicationSettings):
|
|
@@ -19,6 +19,18 @@ class NTDSDSA(ApplicationSettings):
|
|
|
19
19
|
|
|
20
20
|
__object_class__ = "nTDSDSA"
|
|
21
21
|
|
|
22
|
+
def domain(self) -> DomainDNS | None:
|
|
23
|
+
"""Return the domain object associated with this NTDS DSA object, if any."""
|
|
24
|
+
self._assert_local()
|
|
25
|
+
|
|
26
|
+
return next(self.db.link.links(self.dnt, "msDS-HasDomainNCs"), None)
|
|
27
|
+
|
|
28
|
+
def features(self) -> Iterator[MSDSOptionalFeature]:
|
|
29
|
+
"""Return the optional features that are enabled on this NTDS DSA object."""
|
|
30
|
+
self._assert_local()
|
|
31
|
+
|
|
32
|
+
yield from self.db.link.links(self.dnt, "msDS-EnabledFeature")
|
|
33
|
+
|
|
22
34
|
def managed_by(self) -> Iterator[Object]:
|
|
23
35
|
"""Return the objects that manage this NTDS DSA object."""
|
|
24
36
|
self._assert_local()
|
|
@@ -7,7 +7,7 @@ from dissect.database.ese.ntds.objects.top import Top
|
|
|
7
7
|
if TYPE_CHECKING:
|
|
8
8
|
from collections.abc import Iterator
|
|
9
9
|
|
|
10
|
-
from dissect.database.ese.ntds.objects import Object
|
|
10
|
+
from dissect.database.ese.ntds.objects import Computer, Object
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class Server(Top):
|
|
@@ -19,6 +19,12 @@ class Server(Top):
|
|
|
19
19
|
|
|
20
20
|
__object_class__ = "server"
|
|
21
21
|
|
|
22
|
+
def computer(self) -> Computer | None:
|
|
23
|
+
"""Return the computer object associated with this server, if any."""
|
|
24
|
+
self._assert_local()
|
|
25
|
+
|
|
26
|
+
return next(self.db.link.links(self.dnt, "serverReference"), None)
|
|
27
|
+
|
|
22
28
|
def managed_by(self) -> Iterator[Object]:
|
|
23
29
|
"""Return the objects that manage this server."""
|
|
24
30
|
self._assert_local()
|
|
@@ -124,6 +124,7 @@ class Query:
|
|
|
124
124
|
Yields:
|
|
125
125
|
Records matching any condition in the OR operation.
|
|
126
126
|
"""
|
|
127
|
+
records = list(records) if records is not None else None
|
|
127
128
|
for child in filter.children:
|
|
128
129
|
yield from self._process_query(child, records=records)
|
|
129
130
|
|
|
@@ -186,8 +187,10 @@ def _process_wildcard_tail(index: Index, filter_value: str) -> Iterator[Record]:
|
|
|
186
187
|
|
|
187
188
|
# Yield all records in range
|
|
188
189
|
record = cursor.record()
|
|
189
|
-
while record is not None
|
|
190
|
+
while record is not None:
|
|
190
191
|
yield record
|
|
192
|
+
if record == end:
|
|
193
|
+
break
|
|
191
194
|
record = cursor.next()
|
|
192
195
|
|
|
193
196
|
|
|
@@ -202,7 +202,7 @@ class Schema:
|
|
|
202
202
|
# This _should_ have all the attribute and class schema entries
|
|
203
203
|
# We used to perform an index search on objectClass (ATTc0, INDEX_00000000), but apparently
|
|
204
204
|
# not all databases have this index
|
|
205
|
-
dmd = db.
|
|
205
|
+
dmd = db.dmd()
|
|
206
206
|
|
|
207
207
|
# We bootstrapped these earlier
|
|
208
208
|
attribute_schema = self.lookup_class(name="attributeSchema")
|
|
@@ -232,7 +232,7 @@ class Schema:
|
|
|
232
232
|
)
|
|
233
233
|
|
|
234
234
|
# Load user-defined OID prefixes
|
|
235
|
-
if (prefix_map :=
|
|
235
|
+
if (prefix_map := dmd.get("prefixMap")) is not None:
|
|
236
236
|
self._oid_idx_to_prefix_index.update(parse_prefix_map(prefix_map))
|
|
237
237
|
# Rebuild the reverse index
|
|
238
238
|
self._oid_prefix_to_idx_index = {prefix: idx for idx, prefix in self._oid_idx_to_prefix_index.items()}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import struct
|
|
4
|
-
from enum import IntEnum, IntFlag
|
|
4
|
+
from enum import Flag, IntEnum, IntFlag, auto
|
|
5
5
|
from typing import TYPE_CHECKING, Any
|
|
6
6
|
from uuid import UUID
|
|
7
7
|
|
|
@@ -18,6 +18,23 @@ if TYPE_CHECKING:
|
|
|
18
18
|
from dissect.database.ese.ntds.schema import AttributeEntry
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
class DatabaseFlags(Flag):
|
|
22
|
+
"""Database flags that are stored in the hiddentable.
|
|
23
|
+
|
|
24
|
+
The flags are weirdly stored as ``1``, ``0`` or ``\x00`` in a byte array.
|
|
25
|
+
To make parsing a bit easier, we use the index of each flag in this class as the character offset in the byte array.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
AUXCLASS = auto()
|
|
29
|
+
SD_CONVERSION_REQUIRED = auto()
|
|
30
|
+
ROOT_GUID_UPDATED = auto()
|
|
31
|
+
ADAM = auto()
|
|
32
|
+
ASCII_INDICES_REBUILT = auto()
|
|
33
|
+
SHOW_IN_AB_ARRAY_REBUILD = auto()
|
|
34
|
+
UPDATE_NC_TYPE_REQUIRED = auto()
|
|
35
|
+
LINK_QUOTA_USN = auto()
|
|
36
|
+
|
|
37
|
+
|
|
21
38
|
# https://learn.microsoft.com/en-us/windows/win32/adschema/a-instancetype
|
|
22
39
|
class InstanceType(IntFlag):
|
|
23
40
|
HeadOfNamingContext = 0x00000001
|
|
@@ -102,10 +119,10 @@ def _pek_decrypt(db: Database, value: bytes) -> bytes:
|
|
|
102
119
|
Returns:
|
|
103
120
|
The decrypted data blob, or the original value if the PEK is locked.
|
|
104
121
|
"""
|
|
105
|
-
if db.
|
|
122
|
+
if db.pek is None or not db.pek.unlocked:
|
|
106
123
|
return value
|
|
107
124
|
|
|
108
|
-
return db.
|
|
125
|
+
return db.pek.decrypt(value)
|
|
109
126
|
|
|
110
127
|
|
|
111
128
|
def _decode_supplemental_credentials(db: Database, value: bytes) -> dict[str, bytes] | bytes:
|
|
@@ -118,10 +135,10 @@ def _decode_supplemental_credentials(db: Database, value: bytes) -> dict[str, by
|
|
|
118
135
|
Returns:
|
|
119
136
|
A dictionary mapping credential types to their data blobs, or the original value if the PEK is locked.
|
|
120
137
|
"""
|
|
121
|
-
if db.
|
|
138
|
+
if db.pek is None or not db.pek.unlocked:
|
|
122
139
|
return value
|
|
123
140
|
|
|
124
|
-
value = db.
|
|
141
|
+
value = db.pek.decrypt(value)
|
|
125
142
|
header = c_ds.USER_PROPERTIES_HEADER(value)
|
|
126
143
|
|
|
127
144
|
result = {}
|
|
@@ -222,12 +239,12 @@ def _decode_pwd_history(db: Database, value: list[bytes]) -> list[bytes]:
|
|
|
222
239
|
Returns:
|
|
223
240
|
A list of decrypted password hashes, or the original value if the PEK is locked.
|
|
224
241
|
"""
|
|
225
|
-
if db.
|
|
242
|
+
if db.pek is None or not db.pek.unlocked:
|
|
226
243
|
return value
|
|
227
244
|
|
|
228
245
|
result = []
|
|
229
246
|
for buf in value:
|
|
230
|
-
buf = db.
|
|
247
|
+
buf = db.pek.decrypt(buf)
|
|
231
248
|
# The history attributes can contain multiple hashes concatenated together, so we need to split them up
|
|
232
249
|
# NT and LM hashes are both 16 bytes long
|
|
233
250
|
result.extend(buf[i : i + 16] for i in range(0, len(buf), 16))
|
|
@@ -70,7 +70,8 @@ class SQLite3:
|
|
|
70
70
|
checkpoint: The checkpoint to apply from the WAL file. Can be a :class:`Checkpoint` object or an integer index.
|
|
71
71
|
|
|
72
72
|
Raises:
|
|
73
|
-
InvalidDatabase: If the file-like object does not look like a SQLite3
|
|
73
|
+
~dissect.database.sqlite3.exception.InvalidDatabase: If the file-like object does not look like a SQLite3
|
|
74
|
+
database based on the header magic.
|
|
74
75
|
|
|
75
76
|
References:
|
|
76
77
|
- https://sqlite.org/fileformat2.html
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dissect.database
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.dev7
|
|
4
4
|
Summary: A Dissect module implementing parsers for various database formats, including Berkeley DB, Microsofts Extensible Storage Engine (ESE) and SQLite3
|
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -13,7 +13,7 @@ dissect/database/ese/c_ese.py,sha256=kcn2GHTQ_fijY1CEX4gtNAUeTvu5feR-ya4C2_BzTpk
|
|
|
13
13
|
dissect/database/ese/c_ese.pyi,sha256=v-h3If5kUxS8HN8G23m6AHbIQUoGHQ2XZih4zurxWTM,18874
|
|
14
14
|
dissect/database/ese/compression.py,sha256=lLrriyvVjUuDEibUl_ECYVfvqmeU9ijKIaBnx38m98Q,2027
|
|
15
15
|
dissect/database/ese/cursor.py,sha256=ju-mUewhW22bVW0MMdsaKolKCiKnztRcyU0nJw5bNOg,14346
|
|
16
|
-
dissect/database/ese/ese.py,sha256=
|
|
16
|
+
dissect/database/ese/ese.py,sha256=MryiOFbbAE7G1spUk0d5liQTt14nLREVAFnfaj7QW18,3575
|
|
17
17
|
dissect/database/ese/exception.py,sha256=09xbltclWIBsGbk8Ry8RlKG-OwGSQvyLKsgj0d98T0k,210
|
|
18
18
|
dissect/database/ese/index.py,sha256=dYngAWmmX7X8lkP2_q3vgBm1woXYfwtTIOsWORmM2Q0,9859
|
|
19
19
|
dissect/database/ese/lcmapstring.py,sha256=sI0jnSHnuCYwXS3YqBruGixlHXm44L3au5llR2Ash4s,7039
|
|
@@ -29,13 +29,13 @@ dissect/database/ese/ntds/c_pek.py,sha256=YU_rRpOEf8uB8OE6bGb25KIGm9e-yrn0tTItRC
|
|
|
29
29
|
dissect/database/ese/ntds/c_pek.pyi,sha256=lHfhvHWABT1vLmknu66phOXsylgwzGIWVdbqDIZU5Qw,4683
|
|
30
30
|
dissect/database/ese/ntds/c_sd.py,sha256=DYICZsWCBzj0OtvhO6vhzzVjK9YP6tzBCsgKgr0pc-k,4294
|
|
31
31
|
dissect/database/ese/ntds/c_sd.pyi,sha256=7717Y0EBVu37Liu26rqsDWkLIdSCqWn9KK9svtniLqY,5279
|
|
32
|
-
dissect/database/ese/ntds/database.py,sha256=
|
|
33
|
-
dissect/database/ese/ntds/ntds.py,sha256=
|
|
32
|
+
dissect/database/ese/ntds/database.py,sha256=6T9JGxB0BD9JF9LP4DjWfozm7mPb5eiXP56Q6bGqKnk,16783
|
|
33
|
+
dissect/database/ese/ntds/ntds.py,sha256=ffE_yOvmwDUXwuQSjCDcGagKXx3nUajAkxDr1HpJbHQ,5060
|
|
34
34
|
dissect/database/ese/ntds/pek.py,sha256=BEmxO175T8QkGVvFQLN9MI9uDCcK4jztuZetbwbbYqU,4154
|
|
35
|
-
dissect/database/ese/ntds/query.py,sha256=
|
|
36
|
-
dissect/database/ese/ntds/schema.py,sha256=
|
|
35
|
+
dissect/database/ese/ntds/query.py,sha256=pDLLCVdrCRNq3ripvMDiyxXoFWsVJLwwsRMplRf7C9s,8063
|
|
36
|
+
dissect/database/ese/ntds/schema.py,sha256=xxVL--RRBM8-IP12L86hrz-EEGLqXKAXpQZyOT_Vhn0,16644
|
|
37
37
|
dissect/database/ese/ntds/sd.py,sha256=Y-oYnJPcLMDB_4X8TLEGtt-n_nC4HLA0WqIS8qYAwAs,5995
|
|
38
|
-
dissect/database/ese/ntds/util.py,sha256=
|
|
38
|
+
dissect/database/ese/ntds/util.py,sha256=nuY7NRSlr5V5Jz2NIOEhe3hbzPjFLVQnprXa3swSl_M,18856
|
|
39
39
|
dissect/database/ese/ntds/objects/__init__.py,sha256=3lI4f0SwILAY4zJRDVtJpe9YaxKspR-1kHXnhpw91e4,10739
|
|
40
40
|
dissect/database/ese/ntds/objects/applicationsettings.py,sha256=j7UzmF8yxm3LR2lLnmGb7vFvUhYokCUOdhJXnk9xxzE,358
|
|
41
41
|
dissect/database/ese/ntds/objects/attributeschema.py,sha256=0e_s5N5mnybxuufOEjGIVWlyuJkSgplz9LuIsaS2S38,342
|
|
@@ -111,7 +111,7 @@ dissect/database/ese/ntds/objects/mspki_privatekeyrecoveryagent.py,sha256=BA7NKZ
|
|
|
111
111
|
dissect/database/ese/ntds/objects/msspp_activationobjectscontainer.py,sha256=l_OpFUHcRZ7LYvXAdfrDXSClX9f78Ca5UJPgNszo3ZE,405
|
|
112
112
|
dissect/database/ese/ntds/objects/mstpm_informationobjectscontainer.py,sha256=84wqeKMwcShtr6uzgHoG6rMpk_3r22xe6BTvpt24pSg,404
|
|
113
113
|
dissect/database/ese/ntds/objects/ntdsconnection.py,sha256=mWgzUTQ0o6Gsc6CsyBoakyXV5UejzTlsVp8j3vm10bw,341
|
|
114
|
-
dissect/database/ese/ntds/objects/ntdsdsa.py,sha256=
|
|
114
|
+
dissect/database/ese/ntds/objects/ntdsdsa.py,sha256=pES4m9UCqxDI6sOQUjyp3Uc0alHN3pNGpr84L46L5ys,1226
|
|
115
115
|
dissect/database/ese/ntds/objects/ntdsservice.py,sha256=mTdpd2tzm8OOiGm6rJN35_dyeWtvzPYI_rVDBZz0gNc,326
|
|
116
116
|
dissect/database/ese/ntds/objects/ntdssitesettings.py,sha256=VNlke-Vgxjh0fzd5o2X-4fwCBrkEI1coR4oto5OenPo,709
|
|
117
117
|
dissect/database/ese/ntds/objects/ntfrssettings.py,sha256=PwIKT6t_zRxfdacWuvzMfq_mIhj_wyIhHzORNcF2eOU,745
|
|
@@ -130,7 +130,7 @@ dissect/database/ese/ntds/objects/rrasadministrationdictionary.py,sha256=dzS3xag
|
|
|
130
130
|
dissect/database/ese/ntds/objects/samserver.py,sha256=q32pI-Pjd1TOQle_LuR53rjZlDjCY2U2aAYCWjLEaDg,348
|
|
131
131
|
dissect/database/ese/ntds/objects/secret.py,sha256=0278o0wpy3n5JmhYKFpNDy1MgNcHBbjX0aUYXxeCUlQ,3392
|
|
132
132
|
dissect/database/ese/ntds/objects/securityobject.py,sha256=hR0a0wjyrLFtSMtRZOwPCYXpfuOCtNMhozK4bkzly-A,330
|
|
133
|
-
dissect/database/ese/ntds/objects/server.py,sha256=
|
|
133
|
+
dissect/database/ese/ntds/objects/server.py,sha256=9swxb2s6vNTAPsL_mjQBjZNGft-pUvA2-zds1gKfYJ8,889
|
|
134
134
|
dissect/database/ese/ntds/objects/serverscontainer.py,sha256=NnJ0M23RO-hsKd2vWcvViOMRV8psGJkwiaRC-ghmrk0,345
|
|
135
135
|
dissect/database/ese/ntds/objects/site.py,sha256=Yj5lLgivDumOaS8QaTdsS0XZfQEkYr7loN9aUwxj_Y4,640
|
|
136
136
|
dissect/database/ese/ntds/objects/sitelink.py,sha256=cNHis9jsxFPtxfiCfxd4klP495XfjcwrF507wduyADk,313
|
|
@@ -151,17 +151,17 @@ dissect/database/sqlite3/__init__.py,sha256=LIQQsLcZUMHAGzt_6rPDd1HSDXA6qcFyyvpu
|
|
|
151
151
|
dissect/database/sqlite3/c_sqlite3.py,sha256=rFUlUi0ZfUq4kKEyOLB6-E9SxWwIU4I8-pMCNTdR7l0,1883
|
|
152
152
|
dissect/database/sqlite3/c_sqlite3.pyi,sha256=49_sw1wNaNF3aqSRS_13SAk0i-9X6Eis1szb9oN7Wsk,5699
|
|
153
153
|
dissect/database/sqlite3/exception.py,sha256=xYdpjNV8i5KsjliEveB7gcg3DRJlSYCYhK3kOuN2wtE,319
|
|
154
|
-
dissect/database/sqlite3/sqlite3.py,sha256=
|
|
154
|
+
dissect/database/sqlite3/sqlite3.py,sha256=anSspNuyGbuGs5CplwIHsaWqkdo3ofnqJ8oMNvd_zY4,22065
|
|
155
155
|
dissect/database/sqlite3/util.py,sha256=Xif-MfjReWZSsOzMC_2KI-4a0iVVTwmF_eObdIoEBHM,5008
|
|
156
156
|
dissect/database/sqlite3/wal.py,sha256=HilseiVoKauqiDQ00wpcOFKB69YMNFzXS9Va9dDRMj0,6227
|
|
157
157
|
dissect/database/sqlite3/encryption/__init__.py,sha256=kJdFWXD9Z_O_QipC-_A9dlVfR6AOPSOoT8WBhpFbSsE,238
|
|
158
158
|
dissect/database/sqlite3/encryption/sqlcipher/__init__.py,sha256=kJdFWXD9Z_O_QipC-_A9dlVfR6AOPSOoT8WBhpFbSsE,238
|
|
159
159
|
dissect/database/sqlite3/encryption/sqlcipher/exception.py,sha256=GKNtzcnAKlWkvjLluruA8LfzCwjRRWubibbH8WM9l2o,121
|
|
160
160
|
dissect/database/sqlite3/encryption/sqlcipher/sqlcipher.py,sha256=y_oJRKZqoJBeOQaBbniesZKm1sVTFvXZ466rJYZj2xE,11217
|
|
161
|
-
dissect_database-1.2.
|
|
162
|
-
dissect_database-1.2.
|
|
163
|
-
dissect_database-1.2.
|
|
164
|
-
dissect_database-1.2.
|
|
165
|
-
dissect_database-1.2.
|
|
166
|
-
dissect_database-1.2.
|
|
167
|
-
dissect_database-1.2.
|
|
161
|
+
dissect_database-1.2.dev7.dist-info/licenses/COPYRIGHT,sha256=pFH-OBYz6Xj23UB0Odz5IhoTR8nsTbJQNlCRV_wMaiE,317
|
|
162
|
+
dissect_database-1.2.dev7.dist-info/licenses/LICENSE,sha256=PhUqiw6jAh2KbBdVRPBq_hfAvfcTBin7nZ3CK7NQbTM,11341
|
|
163
|
+
dissect_database-1.2.dev7.dist-info/METADATA,sha256=sHAOCCznUzKRwrx21qX2wt81eYmUmZ7_E78gmdUTPJA,5540
|
|
164
|
+
dissect_database-1.2.dev7.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
165
|
+
dissect_database-1.2.dev7.dist-info/entry_points.txt,sha256=ZVVKj3Nzjkgm1kBXGWyGNVUJzTbmVgivv9lgFcuLkpk,343
|
|
166
|
+
dissect_database-1.2.dev7.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
|
|
167
|
+
dissect_database-1.2.dev7.dist-info/RECORD,,
|
|
File without changes
|
{dissect_database-1.2.dev5.dist-info → dissect_database-1.2.dev7.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{dissect_database-1.2.dev5.dist-info → dissect_database-1.2.dev7.dist-info}/licenses/COPYRIGHT
RENAMED
|
File without changes
|
{dissect_database-1.2.dev5.dist-info → dissect_database-1.2.dev7.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|