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