Changes to support Windows Server 2025 32KiB databases#79
Changes to support Windows Server 2025 32KiB databases#79takker-hero-se wants to merge 2 commits into
Conversation
Windows Server 2025 introduced optional 32KiB ESE database pages. This fixes two issues that prevented libesedb from parsing such databases: 1. In the 32KiB page format the upper 4 bits of available_page_tag are reserved (ctagReserved) and only the lower 12 bits contain the actual number of page tags. Masked the reserved bits when page_size >= 32768. 2. The leaf page backward and forward walk functions did not validate the IS_LEAF page flag. In 32KiB databases some pages in the leaf chain may not be actual leaf pages. Added IS_LEAF check with proper error handling.
CI failure analysisThe 2 failed jobs ( Both fail with: This is a shared library path issue in the CI environment, not an API incompatibility. This PR only modifies internal page parsing logic in Additionally, The remaining 21/23 jobs (including all C compilation and test jobs) pass successfully. |
In Windows Server 2025 the ESE pagesize increased to 32kb. The AvailablePageTag field is therefore reduced to only 12 bits with the rest of the bits used for something else. This caused this library to break in parsing the pages and crash. This PR also adds some more resilience in parsing corrupted data to avoid some crashes. Credit for this fix goes to https://github.com/takker-hero-se libyal/libesedb#79
In Windows Server 2025 the ESE pagesize increased to 32kb. The AvailablePageTag field is therefore reduced to only 12 bits with the rest of the bits used for something else. This caused this library to break in parsing the pages and crash. This PR also adds some more resilience in parsing corrupted data to avoid some crashes. Credit for this fix goes to https://github.com/takker-hero-se libyal/libesedb#79
eee0e90 to
baed490
Compare
The WS2025 itagState reinterpretation (upper 4 bits = ctagReserved, lower
12 bits = tag count) is not specific to 32 KiB pages: it also affects
16 KiB DataStore.edb and 4 KiB SRUDB.dat on WS2025. Gating the & 0x0fff
mask on page_size >= 32768 therefore left those databases unparseable.
Gate on io_handle->format_revision >= 0x0122 instead. This:
* covers all WS2025 page sizes (revision 0x0122 for NTDS.dit, 0x012C
for DataStore.edb and SRUDB.dat), and
* is a provable no-op on every pre-WS2025 database (WS2019 = 0x0014),
including dense 32 KiB legacy pages whose tag count could exceed the
12-bit field and be truncated by an unconditional/size-gated mask.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #79 +/- ##
===========================================
+ Coverage 22.09% 33.30% +11.20%
===========================================
Files 52 54 +2
Lines 12277 12399 +122
Branches 2836 2890 +54
===========================================
+ Hits 2713 4129 +1416
+ Misses 9140 7145 -1995
- Partials 424 1125 +701 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Thanks for the proposed changes will take a look when time permits. |
|
No need to address the failing tests. I'll make comparable changes in a separate change list.
Note that this appears not to be limited to 32k page size. To reproduce https://github.com/dfirlabs/esedb-specimens on Windows 11 (0x620,300) |
Interesting do you have some examples that could be shared? Note that in your changes both libesedb_page_tree_get_get_first_leaf_page_number and libesedb_page_tree_get_number_of_leaf_values now can stop prematurely if there is non-leaf page in the chain. |
|
Closing in favor of 768a047 |
Fixes #78
Summary
Windows Server 2025 introduced optional 32KiB ESE database pages for Active Directory (NTDS.dit). This PR fixes two issues that prevented libesedb from parsing such databases.
Changes
1. Page tag count mask (
libesedb_page_header.c, +9 lines)In the 32KiB page format, the
available_page_tagfield (uint16) uses a new layout:ctagReserved(reserved, must be masked out)Without masking, libesedb reads all 16 bits as the tag count, inflating the value and causing out-of-bounds page tag reads.
Fix:
page_header->available_page_tag &= 0x0fffwhenio_handle->page_size >= 32768.2. Leaf page validation in B-tree walk (
libesedb_page_tree.c, +45 lines)The backward walk in
libesedb_page_tree_get_get_first_leaf_page_number()and forward walk inlibesedb_page_tree_get_number_of_leaf_values()did not check whether each page in the leaf chain is actually a leaf page. In 32KiB databases, some pages referenced in the chain may be zeroed or non-leaf pages, causing errors or incorrect record counts.Fix: Check
LIBESEDB_PAGE_FLAG_IS_LEAFbefore processing each page. Added properlibcerror_error_set()error handling for thelibesedb_page_get_flags()calls.Testing
Tested with real Active Directory NTDS.dit databases:
No regression on 8KiB page databases.
References