3d1215
From f80b9b31f99ccdc06887c23dab46a37fc4f4ce74 Mon Sep 17 00:00:00 2001
3d1215
From: Dawid Zamirski <dzamirski@datto.com>
3d1215
Date: Thu, 16 Feb 2017 18:17:23 -0500
3d1215
Subject: [PATCH 09/12] lib: change how hbin sections are read.
3d1215
3d1215
Only when HIVEX_OPEN_UNSAFE flag is set:
3d1215
3d1215
* hivex_open: when looping over hbin sections (aka pages), handle a
3d1215
  case where following hbin section may not begin at exactly at the end
3d1215
  of previous one. If this happens, scan the page section until next
3d1215
  one is found and validate it by checking declared offset with actual
3d1215
  one - if they match, all is good and we can safely move on.
3d1215
3d1215
Rationale: there are registry hives there is some garbage data between
3d1215
hbin section but the hive is still perfectly usable as long as the
3d1215
offsets stated in hbin headers are correct.
3d1215
3d1215
(cherry picked from commit 8d092a746dbd9e61ec85cf17449c201bc0719721)
3d1215
---
3d1215
 lib/handle.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
3d1215
 1 file changed, 46 insertions(+), 5 deletions(-)
3d1215
3d1215
diff --git a/lib/handle.c b/lib/handle.c
3d1215
index dff2780..8c64b6d 100644
3d1215
--- a/lib/handle.c
3d1215
+++ b/lib/handle.c
3d1215
@@ -227,11 +227,42 @@ hivex_open (const char *filename, int flags)
3d1215
         page->magic[1] != 'b' ||
3d1215
         page->magic[2] != 'i' ||
3d1215
         page->magic[3] != 'n') {
3d1215
-      SET_ERRNO (ENOTSUP,
3d1215
-                 "%s: trailing garbage at end of file "
3d1215
-                 "(at 0x%zx, after %zu pages)",
3d1215
-                 filename, off, pages);
3d1215
-      goto error;
3d1215
+
3d1215
+      if (!h->unsafe) {
3d1215
+        SET_ERRNO (ENOTSUP,
3d1215
+                   "%s: trailing garbage at end of file "
3d1215
+                   "(at 0x%zx, after %zu pages)",
3d1215
+                   filename, off, pages);
3d1215
+        goto error;
3d1215
+      }
3d1215
+
3d1215
+      DEBUG (2,
3d1215
+             "page not found at expected offset 0x%zx, "
3d1215
+             "seeking until one is found or EOF is reached",
3d1215
+             off);
3d1215
+
3d1215
+      int found = 0;
3d1215
+      while (off < h->size) {
3d1215
+        off += 0x1000;
3d1215
+
3d1215
+        if (off >= h->endpages)
3d1215
+          break;
3d1215
+
3d1215
+        page = (struct ntreg_hbin_page *) ((char *) h->addr + off);
3d1215
+        if (page->magic[0] == 'h' &&
3d1215
+            page->magic[1] == 'b' &&
3d1215
+            page->magic[2] == 'i' &&
3d1215
+            page->magic[3] == 'n') {
3d1215
+          DEBUG (2, "found next page by seeking at 0x%zx", off);
3d1215
+          found = 1;
3d1215
+          break;
3d1215
+        }
3d1215
+      }
3d1215
+
3d1215
+      if (!found) {
3d1215
+        DEBUG (2, "page not found and end of pages section reached");
3d1215
+        break;
3d1215
+      }
3d1215
     }
3d1215
 
3d1215
     size_t page_size = le32toh (page->page_size);
3d1215
@@ -255,6 +286,16 @@ hivex_open (const char *filename, int flags)
3d1215
       goto error;
3d1215
     }
3d1215
 
3d1215
+    size_t page_offset = le32toh(page->offset_first) + 0x1000;
3d1215
+
3d1215
+    if (page_offset != off) {
3d1215
+      SET_ERRNO (ENOTSUP,
3d1215
+                 "%s: declared page offset (0x%zx) does not match computed "
3d1215
+                 "offset (0x%zx), bad registry",
3d1215
+                 filename, page_offset, off);
3d1215
+      goto error;
3d1215
+    }
3d1215
+
3d1215
     /* Read the blocks in this page. */
3d1215
     size_t blkoff;
3d1215
     struct ntreg_hbin_block *block;
3d1215
-- 
3d1215
1.8.3.1
3d1215