* hivex_open: when looping over hbin sections (aka pages), handle a
case where following hbin section may not begin at exactly at the end
of previous one. If this happens, scan the page section until next
one is found and validate it by checking declared offset with actual
one - if they match, all is good and we can safely move on.
Rationale: there are registry hives there is some garbage data between
hbin section but the hive is still perfectly usable as long as the
offsets stated in hbin headers are correct.
---
lib/handle.c | 39 ++++++++++++++++++++++++++++++++++-----
1 file changed, 34 insertions(+), 5 deletions(-)
diff --git a/lib/handle.c b/lib/handle.c
index 4565d7d..1e122ea 100644
--- a/lib/handle.c
+++ b/lib/handle.c
@@ -226,11 +226,30 @@ hivex_open (const char *filename, int flags)
page->magic[1] != 'b' ||
page->magic[2] != 'i' ||
page->magic[3] != 'n') {
- SET_ERRNO (ENOTSUP,
- "%s: trailing garbage at end of file "
- "(at 0x%zx, after %zu pages)",
- filename, off, pages);
- goto error;
+
+ DEBUG(2,
+ "page not found at expected offset 0x%zx, "
+ "seeking until one is found or EOF is reached",
+ off);
+
+ int found = 0;
+ while (off < h->endpages) {
+ off += 0x1000;
+ page = (struct ntreg_hbin_page *) ((char *) h->addr + off);
+ if (page->magic[0] == 'h' &&
+ page->magic[1] == 'b' &&
+ page->magic[2] == 'i' &&
+ page->magic[3] == 'n') {
+ DEBUG(2, "found next page by seeking at 0x%zx", off);
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ DEBUG(2, "page not found and end of pages section reached");
+ break;
+ }
}
size_t page_size = le32toh (page->page_size);
@@ -254,6 +273,16 @@ hivex_open (const char *filename, int flags)
goto error;
}
+ size_t page_offset = le32toh(page->offset_first) + 0x1000;
+
+ if (page_offset != off) {
+ SET_ERRNO(ENOTSUP,
+ "%s: declared page offset (0x%zx) does not match computed "
+ "offset (0x%zx), bad registry",
+ filename, page_offset, off);
+ goto error;
+ }
+
/* Read the blocks in this page. */
size_t blkoff;
struct ntreg_hbin_block *block;
--
2.9.3