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