Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions impacket/ese.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,12 +567,26 @@ def getTag(self, tagNum):
tag = tags[-4:]

if self.__DBHeader['Version'] == 0x620 and self.__DBHeader['FileFormatRevision'] >= 17 and self.__DBHeader['PageSize'] > 8192:
# Large page format (16KB / 32KB): page tag flags are stored in the
# upper 3 bits of the first 16-bit value of the entry data itself,
# not in the tag entry. Tag entries use full 15-bit fields.
valueSize = unpack('<H', tag[:2])[0] & 0x7fff
valueOffset = unpack('<H',tag[2:])[0] & 0x7fff
tmpData = bytearray(self.data[baseOffset+valueOffset:][:valueSize])
pageFlags = tmpData[1] >> 5
tmpData[1] = tmpData[1:2][0] & 0x1f
tmpData = bytes(tmpData)
if valueSize >= 2:
# Extract page tag flags from the upper 3 bits of the first
# 16-bit little-endian value in the entry data (byte index 1
# holds the high byte of that 16-bit word).
pageFlags = tmpData[1] >> 5
tmpData[1] = tmpData[1] & 0x1f
tmpData = bytes(tmpData)
elif valueSize == 1:
pageFlags = 0
tmpData = bytes(tmpData)
else:
# Empty entry (e.g. leaf/branch page header with no common key)
pageFlags = 0
tmpData = b''
tagData = tmpData
else:
valueSize = unpack('<H', tag[:2])[0] & 0x1fff
Expand Down
17 changes: 15 additions & 2 deletions tests/misc/test_ese.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class TestESENTLargePageTags(unittest.TestCase):
VERSION = 0x620
REVISION = 0x122

def _build_page(self, raw_tag_state):
def _build_page(self, raw_tag_state, payloads=None):
tag_count = raw_tag_state & FIRST_AVAILABLE_PAGE_TAG_MASK
header = ESENT_PAGE_HEADER(self.VERSION, self.REVISION, self.PAGE_SIZE)
header['FirstAvailableDataOffset'] = tag_count * 4
Expand All @@ -37,7 +37,10 @@ def _build_page(self, raw_tag_state):
page[:len(header_bytes)] = header_bytes

base_offset = len(header_bytes)
payloads = [bytes([i, i, i, i]) for i in range(tag_count)]
if payloads is None:
payloads = [bytes([i, i, i, i]) for i in range(tag_count)]
self.assertEqual(len(payloads), tag_count)

tags = []
offset = 0
for payload in payloads:
Expand Down Expand Up @@ -79,6 +82,16 @@ def test_iter_data_tags_skips_all_reserved_large_page_tags(self):
iterated_payloads = [page.getTag(tag_num)[1] for tag_num in page.iterDataTagNums()]
self.assertEqual(iterated_payloads, payloads[page.firstDataTag:])

def test_large_page_tag_handles_empty_and_single_byte_values(self):
page, _ = self._build_page(0x1003, [
b'\x11\x22',
b'',
b'\xab',
])

self.assertEqual(page.getTag(1), (0, b''))
self.assertEqual(page.getTag(2), (0, b'\xab'))


if __name__ == '__main__':
unittest.main(verbosity=1)