|
|
33d974 |
From 8e187357f466c31a9e75ac4924b32bbf4823e73f Mon Sep 17 00:00:00 2001
|
|
|
33d974 |
From: Dawid Zamirski <dzamirski@datto.com>
|
|
|
33d974 |
Date: Thu, 16 Feb 2017 18:17:24 -0500
|
|
|
9ae7cd |
Subject: [PATCH 10/15] lib: allow to walk registry with corrupted blocks
|
|
|
33d974 |
|
|
|
33d974 |
Only when HIVEX_OPEN_UNSAFE flag is set.
|
|
|
33d974 |
|
|
|
33d974 |
There are some corrupted registry files that have invalid hbin cells
|
|
|
33d974 |
but are still readable. This patch makes the following changes:
|
|
|
33d974 |
|
|
|
33d974 |
* hivex_open - do not abort with complete failure if we run across a
|
|
|
33d974 |
block with invalid size (unless it's the root block). Instead just
|
|
|
33d974 |
log the event, and move on. This will allow open hives that have
|
|
|
33d974 |
apparent invalid blocks but the ones of potential interest might be
|
|
|
33d974 |
perfectly accessible.
|
|
|
33d974 |
* _hivex_get_children - similiarly, if the's invalid subkey, just skip
|
|
|
33d974 |
it instead of failing so one can continue to browse other valid
|
|
|
33d974 |
subkeys.
|
|
|
33d974 |
|
|
|
33d974 |
The above is similar to the behavior to Windows regedit where one can
|
|
|
33d974 |
load such corrupted hives with e.g. "reg load HKU\Corrupted" and
|
|
|
33d974 |
browse/change it despite some keys might be missing.
|
|
|
33d974 |
|
|
|
33d974 |
(cherry picked from commit 5345ec8f1df304dc93a6b1e4cbb40e7c1cf6f88d)
|
|
|
33d974 |
---
|
|
|
33d974 |
lib/handle.c | 16 ++++++++++++----
|
|
|
33d974 |
lib/node.c | 46 +++++++++++++++++++++++++++++++++++-----------
|
|
|
33d974 |
2 files changed, 47 insertions(+), 15 deletions(-)
|
|
|
33d974 |
|
|
|
33d974 |
diff --git a/lib/handle.c b/lib/handle.c
|
|
|
33d974 |
index 8c64b6d..0d2b24b 100644
|
|
|
33d974 |
--- a/lib/handle.c
|
|
|
33d974 |
+++ b/lib/handle.c
|
|
|
33d974 |
@@ -313,10 +313,18 @@ hivex_open (const char *filename, int flags)
|
|
|
33d974 |
int used;
|
|
|
33d974 |
seg_len = block_len (h, blkoff, &used);
|
|
|
33d974 |
if (seg_len <= 4 || (seg_len & 3) != 0) {
|
|
|
33d974 |
- SET_ERRNO (ENOTSUP,
|
|
|
33d974 |
- "%s: block size %" PRIu32 " at 0x%zx, bad registry",
|
|
|
33d974 |
- filename, le32toh (block->seg_len), blkoff);
|
|
|
33d974 |
- goto error;
|
|
|
33d974 |
+ if (is_root || !h->unsafe) {
|
|
|
33d974 |
+ SET_ERRNO (ENOTSUP,
|
|
|
33d974 |
+ "%s, the block at 0x%zx has invalid size %" PRIi32
|
|
|
33d974 |
+ ", bad registry",
|
|
|
33d974 |
+ filename, blkoff, le32toh (block->seg_len));
|
|
|
33d974 |
+ goto error;
|
|
|
33d974 |
+ } else {
|
|
|
33d974 |
+ DEBUG (2,
|
|
|
33d974 |
+ "%s: block at 0x%zx has invalid size %" PRIi32 ", skipping",
|
|
|
33d974 |
+ filename, blkoff, le32toh (block->seg_len));
|
|
|
33d974 |
+ break;
|
|
|
33d974 |
+ }
|
|
|
33d974 |
}
|
|
|
33d974 |
|
|
|
33d974 |
if (h->msglvl >= 2) {
|
|
|
33d974 |
diff --git a/lib/node.c b/lib/node.c
|
|
|
33d974 |
index 22d1861..a90c964 100644
|
|
|
33d974 |
--- a/lib/node.c
|
|
|
33d974 |
+++ b/lib/node.c
|
|
|
33d974 |
@@ -343,11 +343,18 @@ _hivex_get_children (hive_h *h, hive_node_h node,
|
|
|
33d974 |
*/
|
|
|
33d974 |
size_t nr_children = _hivex_get_offset_list_length (&children);
|
|
|
33d974 |
if (nr_subkeys_in_nk != nr_children) {
|
|
|
33d974 |
- SET_ERRNO (ENOTSUP,
|
|
|
33d974 |
- "nr_subkeys_in_nk = %zu "
|
|
|
33d974 |
- "is not equal to number of children read %zu",
|
|
|
33d974 |
- nr_subkeys_in_nk, nr_children);
|
|
|
33d974 |
- goto error;
|
|
|
33d974 |
+ if (!h->unsafe) {
|
|
|
33d974 |
+ SET_ERRNO (ENOTSUP,
|
|
|
33d974 |
+ "nr_subkeys_in_nk = %zu "
|
|
|
33d974 |
+ "is not equal to number of childred read %zu",
|
|
|
33d974 |
+ nr_subkeys_in_nk, nr_children);
|
|
|
33d974 |
+ goto error;
|
|
|
33d974 |
+ } else {
|
|
|
33d974 |
+ DEBUG (2,
|
|
|
33d974 |
+ "nr_subkeys_in_nk = %zu "
|
|
|
33d974 |
+ "is not equal to number of children read %zu",
|
|
|
33d974 |
+ nr_subkeys_in_nk, nr_children);
|
|
|
33d974 |
+ }
|
|
|
33d974 |
}
|
|
|
33d974 |
|
|
|
33d974 |
out:
|
|
|
33d974 |
@@ -407,8 +414,14 @@ _get_children (hive_h *h, hive_node_h blkoff,
|
|
|
33d974 |
for (i = 0; i < nr_subkeys_in_lf; ++i) {
|
|
|
33d974 |
hive_node_h subkey = le32toh (lf->keys[i].offset);
|
|
|
33d974 |
subkey += 0x1000;
|
|
|
33d974 |
- if (check_child_is_nk_block (h, subkey, flags) == -1)
|
|
|
33d974 |
- return -1;
|
|
|
33d974 |
+ if (check_child_is_nk_block (h, subkey, flags) == -1) {
|
|
|
33d974 |
+ if (h->unsafe) {
|
|
|
33d974 |
+ DEBUG (2, "subkey at 0x%zx is not an NK block, skipping", subkey);
|
|
|
33d974 |
+ continue;
|
|
|
33d974 |
+ } else {
|
|
|
33d974 |
+ return -1;
|
|
|
33d974 |
+ }
|
|
|
33d974 |
+ }
|
|
|
33d974 |
if (_hivex_add_to_offset_list (children, subkey) == -1)
|
|
|
33d974 |
return -1;
|
|
|
33d974 |
}
|
|
|
33d974 |
@@ -435,8 +448,14 @@ _get_children (hive_h *h, hive_node_h blkoff,
|
|
|
33d974 |
for (i = 0; i < nr_offsets; ++i) {
|
|
|
33d974 |
hive_node_h subkey = le32toh (ri->offset[i]);
|
|
|
33d974 |
subkey += 0x1000;
|
|
|
33d974 |
- if (check_child_is_nk_block (h, subkey, flags) == -1)
|
|
|
33d974 |
- return -1;
|
|
|
33d974 |
+ if (check_child_is_nk_block (h, subkey, flags) == -1) {
|
|
|
33d974 |
+ if (h->unsafe) {
|
|
|
33d974 |
+ DEBUG (2, "subkey at 0x%zx is not an NK block, skipping", subkey);
|
|
|
33d974 |
+ continue;
|
|
|
33d974 |
+ } else {
|
|
|
33d974 |
+ return -1;
|
|
|
33d974 |
+ }
|
|
|
33d974 |
+ }
|
|
|
33d974 |
if (_hivex_add_to_offset_list (children, subkey) == -1)
|
|
|
33d974 |
return -1;
|
|
|
33d974 |
}
|
|
|
33d974 |
@@ -458,8 +477,13 @@ _get_children (hive_h *h, hive_node_h blkoff,
|
|
|
33d974 |
hive_node_h offset = le32toh (ri->offset[i]);
|
|
|
33d974 |
offset += 0x1000;
|
|
|
33d974 |
if (!IS_VALID_BLOCK (h, offset)) {
|
|
|
33d974 |
- SET_ERRNO (EFAULT, "ri-offset is not a valid block (0x%zx)", offset);
|
|
|
33d974 |
- return -1;
|
|
|
33d974 |
+ if (h->unsafe) {
|
|
|
33d974 |
+ DEBUG (2, "ri-offset is not a valid block (0x%zx), skipping", offset);
|
|
|
33d974 |
+ continue;
|
|
|
33d974 |
+ } else {
|
|
|
33d974 |
+ SET_ERRNO (EFAULT, "ri-offset is not a valid block (0x%zx)", offset);
|
|
|
33d974 |
+ return -1;
|
|
|
33d974 |
+ }
|
|
|
33d974 |
}
|
|
|
33d974 |
|
|
|
33d974 |
if (_get_children (h, offset, children, blocks, flags) == -1)
|
|
|
33d974 |
--
|
|
|
33d974 |
1.8.3.1
|
|
|
33d974 |
|