diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eed41cd --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/hivex-1.3.10.tar.gz diff --git a/.hivex.metadata b/.hivex.metadata new file mode 100644 index 0000000..b9989e3 --- /dev/null +++ b/.hivex.metadata @@ -0,0 +1 @@ +daf22b5301d4dfdf44cfff326b67c8690ef73509 SOURCES/hivex-1.3.10.tar.gz diff --git a/SOURCES/0001-Fix-Perl-directory-install-path.patch b/SOURCES/0001-Fix-Perl-directory-install-path.patch new file mode 100644 index 0000000..0ca73e8 --- /dev/null +++ b/SOURCES/0001-Fix-Perl-directory-install-path.patch @@ -0,0 +1,25 @@ +From 1c6bd6e0085204425d7c687f2566cb9b13231e6e Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 17 Feb 2017 15:58:04 +0000 +Subject: [PATCH 01/12] Fix Perl directory install path. + +--- + perl/Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/perl/Makefile.am b/perl/Makefile.am +index a0ae863..144a1bc 100644 +--- a/perl/Makefile.am ++++ b/perl/Makefile.am +@@ -43,7 +43,7 @@ $(TESTS): src_deps all + + TESTS_ENVIRONMENT = ../run + +-INSTALLDIRS = site ++INSTALLDIRS = vendor + + all: Makefile-pl src_deps + $(MAKE) -f Makefile-pl +-- +1.8.3.1 + diff --git a/SOURCES/0002-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch b/SOURCES/0002-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch new file mode 100644 index 0000000..32dd1b4 --- /dev/null +++ b/SOURCES/0002-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch @@ -0,0 +1,32 @@ +From 6a4dac0da1f318a1114363b274fcee76e73fcccf Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 22 Sep 2014 15:08:44 +0100 +Subject: [PATCH 02/12] value: Set errno = 0 on non-error path in + hivex_value_data_cell_offset (RHBZ#1145056). + +hivex_value_data_cell_offset may return 0 to indicate that the data is +inline. This is not an error return, but it was possible for errno to +have a random (non-zero) value along this path. Explicitly set errno += 0 on this path. + +Thanks: Wei Shi +(cherry picked from commit 9763f96a1374486c7d00ea5c04b8048fe69e63f3) +--- + lib/value.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/value.c b/lib/value.c +index f222b41..aa80238 100644 +--- a/lib/value.c ++++ b/lib/value.c +@@ -276,6 +276,7 @@ hivex_value_data_cell_offset (hive_h *h, hive_value_h value, size_t *len) + /* There is no other location for the value data. */ + if (len) + *len = 0; ++ errno = 0; + return 0; + } else { + if (len) +-- +1.8.3.1 + diff --git a/SOURCES/0003-hivexml-Tidy-up-error-handling-and-printing.patch b/SOURCES/0003-hivexml-Tidy-up-error-handling-and-printing.patch new file mode 100644 index 0000000..0942640 --- /dev/null +++ b/SOURCES/0003-hivexml-Tidy-up-error-handling-and-printing.patch @@ -0,0 +1,82 @@ +From 2cffe999c938a0bc67c3c6162ea4fc896af2dd22 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 22 Sep 2014 15:10:36 +0100 +Subject: [PATCH 03/12] hivexml: Tidy up error handling and printing. + +(cherry picked from commit 914d9b9a91babf0227989bc7ea00cf5e41ed7da4) +--- + xml/hivexml.c | 28 +++++++++++++--------------- + 1 file changed, 13 insertions(+), 15 deletions(-) + +diff --git a/xml/hivexml.c b/xml/hivexml.c +index a4bc7eb..b496bb6 100644 +--- a/xml/hivexml.c ++++ b/xml/hivexml.c +@@ -116,7 +116,7 @@ main (int argc, char *argv[]) + + hive_h *h = hivex_open (argv[optind], open_flags); + if (h == NULL) { +- perror (argv[optind]); ++ fprintf (stderr, "hivex_open: %s: %m\n", argv[optind]); + exit (EXIT_FAILURE); + } + +@@ -148,12 +148,12 @@ main (int argc, char *argv[]) + } + + if (hivex_visit (h, &visitor, sizeof visitor, writer, visit_flags) == -1) { +- perror (argv[optind]); ++ fprintf (stderr, "hivex_visit: %s: %m\n", argv[optind]); + exit (EXIT_FAILURE); + } + + if (hivex_close (h) == -1) { +- perror (argv[optind]); ++ fprintf (stderr, "hivex_close: %s: %m\n", argv[optind]); + exit (EXIT_FAILURE); + } + +@@ -217,12 +217,9 @@ node_byte_runs (hive_h *h, void *writer_v, hive_node_h node) + { + xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; + char buf[1+BYTE_RUN_BUF_LEN]; +- errno = 0; + size_t node_struct_length = hivex_node_struct_length (h, node); +- if (errno) { +- if (errno == EINVAL) { +- fprintf (stderr, "node_byte_runs: Invoked on what does not seem to be a node (%zu).\n", node); +- } ++ if (node_struct_length == 0) { ++ fprintf (stderr, "node_byte_runs: hivex_node_struct_length: %m\n"); + return -1; + } + /* A node has one byte run. */ +@@ -301,17 +298,18 @@ value_byte_runs (hive_h *h, void *writer_v, hive_value_h value) { + xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; + char buf[1+BYTE_RUN_BUF_LEN]; + size_t value_data_cell_length; +- errno = 0; + size_t value_data_structure_length = hivex_value_struct_length (h, value); +- if (errno != 0) { +- if (errno == EINVAL) { +- fprintf (stderr, "value_byte_runs: Invoked on what does not seem to be a value (%zu).\n", value); +- } ++ if (value_data_structure_length == 0) { ++ fprintf (stderr, "value_byte_runs: hivex_value_struct_length: %m\n"); + return -1; + } +- hive_value_h value_data_cell_offset = hivex_value_data_cell_offset (h, value, &value_data_cell_length); +- if (errno != 0) ++ errno = 0; ++ hive_value_h value_data_cell_offset = ++ hivex_value_data_cell_offset (h, value, &value_data_cell_length); ++ if (value_data_cell_offset == 0 && errno != 0) { ++ fprintf (stderr, "value_byte_runs: hivex_value_data_cell_offset: %m\n"); + return -1; ++ } + + XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "byte_runs")); + memset (buf, 0, 1+BYTE_RUN_BUF_LEN); +-- +1.8.3.1 + diff --git a/SOURCES/0004-lib-Don-t-leak-errno-from-_hivex_recode-function.patch b/SOURCES/0004-lib-Don-t-leak-errno-from-_hivex_recode-function.patch new file mode 100644 index 0000000..21a442e --- /dev/null +++ b/SOURCES/0004-lib-Don-t-leak-errno-from-_hivex_recode-function.patch @@ -0,0 +1,35 @@ +From 1d90ea86a0ac6c5863597880b33a18755aff819c Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 20 Nov 2014 21:37:19 +0000 +Subject: [PATCH 04/12] lib: Don't leak errno from _hivex_recode function. + +If iconv returns E2BIG, that's an internal indication for us, and not +an error. Don't leak the errno up to the user, as happened here: + +https://www.redhat.com/archives/libguestfs/2014-November/msg00140.html + +Thanks Nicolas Ecarnot. + +(cherry picked from commit 4b3c3cd2b3d8d34601979feeb1390fddd442ab04) +--- + lib/utf16.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/lib/utf16.c b/lib/utf16.c +index f4299f2..3b54b01 100644 +--- a/lib/utf16.c ++++ b/lib/utf16.c +@@ -59,6 +59,10 @@ _hivex_recode (const char *input_encoding, const char *input, size_t input_len, + if (r == (size_t) -1) { + if (errno == E2BIG) { + int err = errno; ++ /* Reset errno here because we don't want to accidentally ++ * return E2BIG to a library caller. ++ */ ++ errno = 0; + size_t prev = outalloc; + /* Try again with a larger output buffer. */ + free (out); +-- +1.8.3.1 + diff --git a/SOURCES/0005-handle-Refuse-to-open-files-8192-bytes-in-size.patch b/SOURCES/0005-handle-Refuse-to-open-files-8192-bytes-in-size.patch new file mode 100644 index 0000000..b9e4483 --- /dev/null +++ b/SOURCES/0005-handle-Refuse-to-open-files-8192-bytes-in-size.patch @@ -0,0 +1,36 @@ +From ebcb61e3d88d99b929b4d8ccaad837a871c102d8 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 30 Oct 2014 13:50:39 +0000 +Subject: [PATCH 05/12] handle: Refuse to open files < 8192 bytes in size. + +These cannot be valid hives, since they don't contain a full header +page and at least a single page of data (in other words they couldn't +contain a root node). + +Thanks: Mahmoud Al-Qudsi +(cherry picked from commit 357f26fa64fd1d9ccac2331fe174a8ee9c607adb) +--- + lib/handle.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/lib/handle.c b/lib/handle.c +index 62a8644..a3cbcf7 100644 +--- a/lib/handle.c ++++ b/lib/handle.c +@@ -104,6 +104,13 @@ hivex_open (const char *filename, int flags) + + h->size = statbuf.st_size; + ++ if (h->size < 0x2000) { ++ SET_ERRNO (EINVAL, ++ "%s: file is too small to be a Windows NT Registry hive file", ++ filename); ++ goto error; ++ } ++ + if (!h->writable) { + h->addr = mmap (NULL, h->size, PROT_READ, MAP_SHARED, h->fd, 0); + if (h->addr == MAP_FAILED) +-- +1.8.3.1 + diff --git a/SOURCES/0006-handle-Check-that-pages-do-not-extend-beyond-the-end.patch b/SOURCES/0006-handle-Check-that-pages-do-not-extend-beyond-the-end.patch new file mode 100644 index 0000000..8e4f674 --- /dev/null +++ b/SOURCES/0006-handle-Check-that-pages-do-not-extend-beyond-the-end.patch @@ -0,0 +1,33 @@ +From 5c718aab579d693ea3169ab4d29b5c3bc9105aa1 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 30 Oct 2014 14:02:25 +0000 +Subject: [PATCH 06/12] handle: Check that pages do not extend beyond the end + of the file. + +Thanks: Mahmoud Al-Qudsi +(cherry picked from commit 4bbdf555f88baeae0fa804a369a81a83908bd705) +--- + lib/handle.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/lib/handle.c b/lib/handle.c +index a3cbcf7..3a8f09b 100644 +--- a/lib/handle.c ++++ b/lib/handle.c +@@ -247,6 +247,13 @@ hivex_open (const char *filename, int flags) + goto error; + } + ++ if (off + page_size > h->size) { ++ SET_ERRNO (ENOTSUP, ++ "%s: page size %zu at 0x%zx extends beyond end of file, bad registry", ++ filename, page_size, off); ++ goto error; ++ } ++ + /* Read the blocks in this page. */ + size_t blkoff; + struct ntreg_hbin_block *block; +-- +1.8.3.1 + diff --git a/SOURCES/0007-generator-Fix-a-spelling-mistake-in-the-documentatio.patch b/SOURCES/0007-generator-Fix-a-spelling-mistake-in-the-documentatio.patch new file mode 100644 index 0000000..161e615 --- /dev/null +++ b/SOURCES/0007-generator-Fix-a-spelling-mistake-in-the-documentatio.patch @@ -0,0 +1,27 @@ +From 026a1a2e01795defcfe5b638347671e09fcec2b6 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 20 May 2014 10:48:40 +0100 +Subject: [PATCH 07/12] generator: Fix a spelling mistake in the documentation + (RHBZ#1099286). + +(cherry picked from commit cea8dbf029029a725768caa14ddc876f56bfd878) +--- + generator/generator.ml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/generator/generator.ml b/generator/generator.ml +index 02aaf12..64c7681 100755 +--- a/generator/generator.ml ++++ b/generator/generator.ml +@@ -242,7 +242,7 @@ default key."; + "\ + Return the length of the key (name) of a (key, value) pair as produced + by C. The length can legitimately be 0, so errno is +-the necesary mechanism to check for errors. ++the necessary mechanism to check for errors. + + In the context of Windows Registries, a zero-length name means + that this value is the default key for this node in the tree. +-- +1.8.3.1 + diff --git a/SOURCES/0008-add-HIVEX_OPEN_UNSAFE-flag.patch b/SOURCES/0008-add-HIVEX_OPEN_UNSAFE-flag.patch new file mode 100644 index 0000000..93c4e95 --- /dev/null +++ b/SOURCES/0008-add-HIVEX_OPEN_UNSAFE-flag.patch @@ -0,0 +1,70 @@ +From 691f5532ab4138093cdd8c661aba7519b0b1e2ad Mon Sep 17 00:00:00 2001 +From: Dawid Zamirski +Date: Thu, 16 Feb 2017 18:17:22 -0500 +Subject: [PATCH 08/12] add HIVEX_OPEN_UNSAFE flag. + +This flag will be used to control behavior of libhivex API functions so +that they tolerate corruption in hives by either using heuristic +recovery from unexpected situations or simply ignore bad registry +keys/values whenever possible. + +(cherry picked from commit 507f9328c67c701c32894249437551395bd8072c) +--- + generator/generator.ml | 8 ++++++++ + lib/handle.c | 1 + + lib/hivex-internal.h | 1 + + 3 files changed, 10 insertions(+) + +diff --git a/generator/generator.ml b/generator/generator.ml +index 64c7681..249a317 100755 +--- a/generator/generator.ml ++++ b/generator/generator.ml +@@ -113,6 +113,7 @@ let open_flags = [ + 1, "VERBOSE", "Verbose messages"; + 2, "DEBUG", "Debug messages"; + 4, "WRITE", "Enable writes to the hive"; ++ 8, "UNSAFE", "Enable heuristics to allow read/write of corrupted hives"; + ] + + (* The API calls. *) +@@ -145,6 +146,13 @@ Open the hive for writing. If omitted, the hive is read-only. + + See L. + ++=item HIVEX_OPEN_UNSAFE ++ ++Open the hive in unsafe mode that enables heuristics to handle corrupted hives. ++ ++This may allow to read or write registry keys/values that appear intact in an ++otherwise corrupted hive. Use at your own risk. ++ + =back"; + + "close", (RErrDispose, [AHive]), +diff --git a/lib/handle.c b/lib/handle.c +index 3a8f09b..dff2780 100644 +--- a/lib/handle.c ++++ b/lib/handle.c +@@ -83,6 +83,7 @@ hivex_open (const char *filename, int flags) + DEBUG (2, "created handle %p", h); + + h->writable = !!(flags & HIVEX_OPEN_WRITE); ++ h->unsafe = !!(flags & HIVEX_OPEN_UNSAFE); + h->filename = strdup (filename); + if (h->filename == NULL) + goto error; +diff --git a/lib/hivex-internal.h b/lib/hivex-internal.h +index bfd24c8..bbca215 100644 +--- a/lib/hivex-internal.h ++++ b/lib/hivex-internal.h +@@ -30,6 +30,7 @@ struct hive_h { + size_t size; + int msglvl; /* 1 = verbose, 2 or 3 = debug */ + int writable; ++ int unsafe; + + /* Registry file, memory mapped if read-only, or malloc'd if writing. */ + union { +-- +1.8.3.1 + diff --git a/SOURCES/0009-lib-change-how-hbin-sections-are-read.patch b/SOURCES/0009-lib-change-how-hbin-sections-are-read.patch new file mode 100644 index 0000000..e20e700 --- /dev/null +++ b/SOURCES/0009-lib-change-how-hbin-sections-are-read.patch @@ -0,0 +1,94 @@ +From f80b9b31f99ccdc06887c23dab46a37fc4f4ce74 Mon Sep 17 00:00:00 2001 +From: Dawid Zamirski +Date: Thu, 16 Feb 2017 18:17:23 -0500 +Subject: [PATCH 09/12] lib: change how hbin sections are read. + +Only when HIVEX_OPEN_UNSAFE flag is set: + +* 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. + +(cherry picked from commit 8d092a746dbd9e61ec85cf17449c201bc0719721) +--- + lib/handle.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 46 insertions(+), 5 deletions(-) + +diff --git a/lib/handle.c b/lib/handle.c +index dff2780..8c64b6d 100644 +--- a/lib/handle.c ++++ b/lib/handle.c +@@ -227,11 +227,42 @@ 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; ++ ++ if (!h->unsafe) { ++ 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->size) { ++ off += 0x1000; ++ ++ if (off >= h->endpages) ++ break; ++ ++ 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); +@@ -255,6 +286,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; +-- +1.8.3.1 + diff --git a/SOURCES/0010-lib-allow-to-walk-registry-with-corrupted-blocks.patch b/SOURCES/0010-lib-allow-to-walk-registry-with-corrupted-blocks.patch new file mode 100644 index 0000000..c135032 --- /dev/null +++ b/SOURCES/0010-lib-allow-to-walk-registry-with-corrupted-blocks.patch @@ -0,0 +1,137 @@ +From 8e187357f466c31a9e75ac4924b32bbf4823e73f Mon Sep 17 00:00:00 2001 +From: Dawid Zamirski +Date: Thu, 16 Feb 2017 18:17:24 -0500 +Subject: [PATCH 10/12] lib: allow to walk registry with corrupted blocks + +Only when HIVEX_OPEN_UNSAFE flag is set. + +There are some corrupted registry files that have invalid hbin cells +but are still readable. This patch makes the following changes: + +* hivex_open - do not abort with complete failure if we run across a + block with invalid size (unless it's the root block). Instead just + log the event, and move on. This will allow open hives that have + apparent invalid blocks but the ones of potential interest might be + perfectly accessible. +* _hivex_get_children - similiarly, if the's invalid subkey, just skip + it instead of failing so one can continue to browse other valid + subkeys. + +The above is similar to the behavior to Windows regedit where one can +load such corrupted hives with e.g. "reg load HKU\Corrupted" and +browse/change it despite some keys might be missing. + +(cherry picked from commit 5345ec8f1df304dc93a6b1e4cbb40e7c1cf6f88d) +--- + lib/handle.c | 16 ++++++++++++---- + lib/node.c | 46 +++++++++++++++++++++++++++++++++++----------- + 2 files changed, 47 insertions(+), 15 deletions(-) + +diff --git a/lib/handle.c b/lib/handle.c +index 8c64b6d..0d2b24b 100644 +--- a/lib/handle.c ++++ b/lib/handle.c +@@ -313,10 +313,18 @@ hivex_open (const char *filename, int flags) + int used; + seg_len = block_len (h, blkoff, &used); + if (seg_len <= 4 || (seg_len & 3) != 0) { +- SET_ERRNO (ENOTSUP, +- "%s: block size %" PRIu32 " at 0x%zx, bad registry", +- filename, le32toh (block->seg_len), blkoff); +- goto error; ++ if (is_root || !h->unsafe) { ++ SET_ERRNO (ENOTSUP, ++ "%s, the block at 0x%zx has invalid size %" PRIi32 ++ ", bad registry", ++ filename, blkoff, le32toh (block->seg_len)); ++ goto error; ++ } else { ++ DEBUG (2, ++ "%s: block at 0x%zx has invalid size %" PRIi32 ", skipping", ++ filename, blkoff, le32toh (block->seg_len)); ++ break; ++ } + } + + if (h->msglvl >= 2) { +diff --git a/lib/node.c b/lib/node.c +index 22d1861..a90c964 100644 +--- a/lib/node.c ++++ b/lib/node.c +@@ -343,11 +343,18 @@ _hivex_get_children (hive_h *h, hive_node_h node, + */ + size_t nr_children = _hivex_get_offset_list_length (&children); + if (nr_subkeys_in_nk != nr_children) { +- SET_ERRNO (ENOTSUP, +- "nr_subkeys_in_nk = %zu " +- "is not equal to number of children read %zu", +- nr_subkeys_in_nk, nr_children); +- goto error; ++ if (!h->unsafe) { ++ SET_ERRNO (ENOTSUP, ++ "nr_subkeys_in_nk = %zu " ++ "is not equal to number of childred read %zu", ++ nr_subkeys_in_nk, nr_children); ++ goto error; ++ } else { ++ DEBUG (2, ++ "nr_subkeys_in_nk = %zu " ++ "is not equal to number of children read %zu", ++ nr_subkeys_in_nk, nr_children); ++ } + } + + out: +@@ -407,8 +414,14 @@ _get_children (hive_h *h, hive_node_h blkoff, + for (i = 0; i < nr_subkeys_in_lf; ++i) { + hive_node_h subkey = le32toh (lf->keys[i].offset); + subkey += 0x1000; +- if (check_child_is_nk_block (h, subkey, flags) == -1) +- return -1; ++ if (check_child_is_nk_block (h, subkey, flags) == -1) { ++ if (h->unsafe) { ++ DEBUG (2, "subkey at 0x%zx is not an NK block, skipping", subkey); ++ continue; ++ } else { ++ return -1; ++ } ++ } + if (_hivex_add_to_offset_list (children, subkey) == -1) + return -1; + } +@@ -435,8 +448,14 @@ _get_children (hive_h *h, hive_node_h blkoff, + for (i = 0; i < nr_offsets; ++i) { + hive_node_h subkey = le32toh (ri->offset[i]); + subkey += 0x1000; +- if (check_child_is_nk_block (h, subkey, flags) == -1) +- return -1; ++ if (check_child_is_nk_block (h, subkey, flags) == -1) { ++ if (h->unsafe) { ++ DEBUG (2, "subkey at 0x%zx is not an NK block, skipping", subkey); ++ continue; ++ } else { ++ return -1; ++ } ++ } + if (_hivex_add_to_offset_list (children, subkey) == -1) + return -1; + } +@@ -458,8 +477,13 @@ _get_children (hive_h *h, hive_node_h blkoff, + hive_node_h offset = le32toh (ri->offset[i]); + offset += 0x1000; + if (!IS_VALID_BLOCK (h, offset)) { +- SET_ERRNO (EFAULT, "ri-offset is not a valid block (0x%zx)", offset); +- return -1; ++ if (h->unsafe) { ++ DEBUG (2, "ri-offset is not a valid block (0x%zx), skipping", offset); ++ continue; ++ } else { ++ SET_ERRNO (EFAULT, "ri-offset is not a valid block (0x%zx)", offset); ++ return -1; ++ } + } + + if (_get_children (h, offset, children, blocks, flags) == -1) +-- +1.8.3.1 + diff --git a/SOURCES/0011-hivexsh-add-u-flag-for-HIVEX_OPEN_UNSAFE.patch b/SOURCES/0011-hivexsh-add-u-flag-for-HIVEX_OPEN_UNSAFE.patch new file mode 100644 index 0000000..37fde1d --- /dev/null +++ b/SOURCES/0011-hivexsh-add-u-flag-for-HIVEX_OPEN_UNSAFE.patch @@ -0,0 +1,95 @@ +From d4f5c255832391ba6132959d1ded57ce9286e7d6 Mon Sep 17 00:00:00 2001 +From: Dawid Zamirski +Date: Thu, 16 Feb 2017 18:17:25 -0500 +Subject: [PATCH 11/12] hivexsh: add -u flag for HIVEX_OPEN_UNSAFE. + +and pass it to hivex_open. Additionally make hivex_value_value failures +non-critical in this mode when iterating through node children/values. + +(cherry picked from commit 62c53cda651f34f18a2b55e91012c0448acb70f1) +--- + sh/hivexsh.c | 26 ++++++++++++++++++++------ + 1 file changed, 20 insertions(+), 6 deletions(-) + +diff --git a/sh/hivexsh.c b/sh/hivexsh.c +index f578ccc..39ab9d0 100644 +--- a/sh/hivexsh.c ++++ b/sh/hivexsh.c +@@ -67,6 +67,7 @@ + + static int quit = 0; + static int is_tty; ++static int unsafe = 0; + static hive_h *h = NULL; + static char *prompt_string = NULL; /* Normal prompt string. */ + static char *loaded = NULL; /* Basename of loaded file, if any. */ +@@ -97,7 +98,7 @@ static int cmd_setval (char *args); + static void + usage (void) + { +- fprintf (stderr, "hivexsh [-dfw] [hivefile]\n"); ++ fprintf (stderr, "hivexsh [-dfwu] [hivefile]\n"); + exit (EXIT_FAILURE); + } + +@@ -115,7 +116,7 @@ main (int argc, char *argv[]) + + set_prompt_string (); + +- while ((c = getopt (argc, argv, "df:w")) != EOF) { ++ while ((c = getopt (argc, argv, "df:wu")) != EOF) { + switch (c) { + case 'd': + open_flags |= HIVEX_OPEN_DEBUG; +@@ -126,6 +127,10 @@ main (int argc, char *argv[]) + case 'w': + open_flags |= HIVEX_OPEN_WRITE; + break; ++ case 'u': ++ open_flags |= HIVEX_OPEN_UNSAFE; ++ unsafe = 1; ++ break; + default: + usage (); + } +@@ -771,6 +776,7 @@ cmd_lsval (char *key) + + hive_type t; + size_t len; ++ + if (hivex_value_type (h, values[i], &t, &len) == -1) + goto error; + +@@ -779,8 +785,12 @@ cmd_lsval (char *key) + case hive_t_expand_string: + case hive_t_link: { + char *str = hivex_value_string (h, values[i]); +- if (!str) +- goto error; ++ if (!str) { ++ if (unsafe) ++ continue; ++ else ++ goto error; ++ } + + if (t != hive_t_string) + printf ("str(%d):", t); +@@ -813,8 +823,12 @@ cmd_lsval (char *key) + default: { + unsigned char *data = + (unsigned char *) hivex_value_value (h, values[i], &t, &len); +- if (!data) +- goto error; ++ if (!data) { ++ if (unsafe) ++ continue; ++ else ++ goto error; ++ } + + printf ("hex(%d):", t); + size_t j; +-- +1.8.3.1 + diff --git a/SOURCES/0012-hivexregedit-allow-to-pass-HIVEX_OPEN_UNSAFE.patch b/SOURCES/0012-hivexregedit-allow-to-pass-HIVEX_OPEN_UNSAFE.patch new file mode 100644 index 0000000..53a5aff --- /dev/null +++ b/SOURCES/0012-hivexregedit-allow-to-pass-HIVEX_OPEN_UNSAFE.patch @@ -0,0 +1,168 @@ +From 362d5cd9b6527e4f9d3a3729afbe7cd90486c39d Mon Sep 17 00:00:00 2001 +From: Dawid Zamirski +Date: Thu, 16 Feb 2017 18:17:26 -0500 +Subject: [PATCH 12/12] hivexregedit: allow to pass HIVEX_OPEN_UNSAFE + +via new --unsafe flag. Also make --export catpure, log and skip over +errors when reading subkeys/values so that export in unsafe mode does +not abort at first sign of error. + +(cherry picked from commit 2610b1e089fa84d294f9925342929e3d7408c35b) +--- + perl/lib/Win/Hivex/Regedit.pm | 59 ++++++++++++++++++++++++++++++++++++++----- + regedit/hivexregedit | 20 ++++++++++++--- + 2 files changed, 70 insertions(+), 9 deletions(-) + +diff --git a/perl/lib/Win/Hivex/Regedit.pm b/perl/lib/Win/Hivex/Regedit.pm +index 8914f9e..355699e 100644 +--- a/perl/lib/Win/Hivex/Regedit.pm ++++ b/perl/lib/Win/Hivex/Regedit.pm +@@ -67,7 +67,7 @@ package Win::Hivex::Regedit; + use strict; + use warnings; + +-use Carp qw(croak confess); ++use Carp qw(croak carp confess); + use Encode qw(encode decode); + + require Exporter; +@@ -528,19 +528,51 @@ sub reg_export_node + print $fh "]\n"; + + my $unsafe_printable_strings = $params{unsafe_printable_strings}; ++ my $unsafe = $params{unsafe}; ++ ++ my @values; ++ my @safe_values; + + # Get the values. +- my @values = $h->node_values ($node); ++ if ($unsafe) { ++ my $have_vals = 0; ++ eval { ++ @values = $h->node_values ($node); ++ $have_vals = 1; ++ }; ++ ++ if (!$have_vals) { ++ carp "Failed to read node values at $path"; ++ } ++ } else { ++ @values = $h->node_values ($node); ++ } + + foreach (@values) { + use bytes; + + my $key = $h->value_key ($_); +- my ($type, $data) = $h->value_value ($_); +- $_ = { key => $key, type => $type, data => $data } ++ my ($type, $data); ++ ++ if ($unsafe) { ++ my $val_ok = 0; ++ eval { ++ ($type, $data) = $h->value_value ($_); ++ $val_ok = 1; ++ }; ++ ++ if (!$val_ok) { ++ carp "skipping unreadable value of key: $key in $path"; ++ next; ++ } ++ } else { ++ ($type, $data) = $h->value_value ($_); ++ } ++ ++ push @safe_values, { key => $key, type => $type, data => $data }; + } + +- @values = sort { $a->{key} cmp $b->{key} } @values; ++ @values = sort { $a->{key} cmp $b->{key} } @safe_values; + + # Print the values. + foreach (@values) { +@@ -573,7 +605,22 @@ sub reg_export_node + } + print $fh "\n"; + +- my @children = $h->node_children ($node); ++ my @children; ++ ++ if ($unsafe) { ++ my $have_children = 0; ++ eval { ++ @children = $h->node_children ($node); ++ $have_children = 1; ++ }; ++ ++ if (!$have_children) { ++ carp "Could not get children of $path"; ++ } ++ } else { ++ @children = $h->node_children ($node); ++ } ++ + @children = sort { $h->node_name ($a) cmp $h->node_name ($b) } @children; + reg_export_node ($h, $_, $fh, @_) foreach @children; + } +diff --git a/regedit/hivexregedit b/regedit/hivexregedit +index 0e534de..aa0ee6e 100755 +--- a/regedit/hivexregedit ++++ b/regedit/hivexregedit +@@ -252,6 +252,17 @@ into another program or stored in another hive. + + =cut + ++my $unsafe; ++ ++=item B<--unsafe> ++ ++Use heuristics to tolerate certain levels of corruption within hives. ++ ++This is unsafe but may allow to export/merge valid keys/values in an ++othewise corrupted hive. ++ ++=cut ++ + GetOptions ("help|?" => \$help, + "debug" => \$debug, + "merge|import" => \$merge, +@@ -259,6 +270,7 @@ GetOptions ("help|?" => \$help, + "prefix=s" => \$prefix, + "encoding=s" => \$encoding, + "unsafe-printable-strings" => \$unsafe_printable_strings, ++ "unsafe" => \$unsafe, + ) or pod2usage (2); + pod2usage (1) if $help; + +@@ -281,7 +293,8 @@ if ($merge) { # --merge (reg_import) + + my $hivefile = shift @ARGV; + +- my $h = Win::Hivex->open ($hivefile, write => 1, debug => $debug); ++ my $h = Win::Hivex->open ($hivefile, write => 1, debug => $debug, ++ unsafe => $unsafe); + + # Read from stdin unless other files have been specified. + unshift (@ARGV, '-') unless @ARGV; +@@ -312,13 +325,14 @@ if ($merge) { # --merge (reg_import) + my $hivefile = shift @ARGV; + my $key = shift @ARGV; + +- my $h = Win::Hivex->open ($hivefile, debug => $debug); ++ my $h = Win::Hivex->open ($hivefile, debug => $debug, unsafe => $unsafe); + + print "Windows Registry Editor Version 5.00\n\n"; + + reg_export ($h, $key, \*STDOUT, + prefix => $prefix, +- unsafe_printable_strings => $unsafe_printable_strings); ++ unsafe_printable_strings => $unsafe_printable_strings, ++ unsafe => $unsafe); + } + + =head1 SEE ALSO +-- +1.8.3.1 + diff --git a/SOURCES/generated.patch b/SOURCES/generated.patch new file mode 100644 index 0000000..b6ad060 --- /dev/null +++ b/SOURCES/generated.patch @@ -0,0 +1,272 @@ +Only in hivex-1.3.10/generator: .pod2text.data.version.2 +Only in hivex-1.3.10/generator: stamp-generator +diff -ur hivex-1.3.10.old/lib/hivex.h hivex-1.3.10/lib/hivex.h +--- hivex-1.3.10.old/lib/hivex.h 2014-01-10 10:00:53.000000000 +0000 ++++ hivex-1.3.10/lib/hivex.h 2017-02-17 16:17:58.114476857 +0000 +@@ -3,7 +3,7 @@ + * generator/generator.ml + * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + * +- * Copyright (C) 2009-2014 Red Hat Inc. ++ * Copyright (C) 2009-2017 Red Hat Inc. + * Derived from code by Petter Nordahl-Hagen under a compatible license: + * Copyright (c) 1997-2007 Petter Nordahl-Hagen. + * Derived from code by Markus Stephany under a compatible license: +@@ -111,6 +111,8 @@ + #define HIVEX_OPEN_DEBUG 2 + /* Enable writes to the hive */ + #define HIVEX_OPEN_WRITE 4 ++ /* Enable heuristics to allow read/write of corrupted hives */ ++#define HIVEX_OPEN_UNSAFE 8 + + /* Array of (key, value) pairs passed to hivex_node_set_values. */ + struct hive_set_value { +diff -ur hivex-1.3.10.old/lib/hivex.pod hivex-1.3.10/lib/hivex.pod +--- hivex-1.3.10.old/lib/hivex.pod 2014-01-10 10:00:53.000000000 +0000 ++++ hivex-1.3.10/lib/hivex.pod 2017-02-17 16:17:58.137476198 +0000 +@@ -5,7 +5,7 @@ + generator/generator.ml + ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + +- Copyright (C) 2009-2014 Red Hat Inc. ++ Copyright (C) 2009-2017 Red Hat Inc. + Derived from code by Petter Nordahl-Hagen under a compatible license: + Copyright (c) 1997-2007 Petter Nordahl-Hagen. + Derived from code by Markus Stephany under a compatible license: +@@ -200,6 +200,13 @@ + + See L. + ++=item HIVEX_OPEN_UNSAFE ++ ++Open the hive in unsafe mode that enables heuristics to handle corrupted hives. ++ ++This may allow to read or write registry keys/values that appear intact in an ++otherwise corrupted hive. Use at your own risk. ++ + =back + + Returns a new hive handle. +@@ -346,7 +353,7 @@ + + Return the length of the key (name) of a (key, value) pair as produced + by C. The length can legitimately be 0, so errno is +-the necesary mechanism to check for errors. ++the necessary mechanism to check for errors. + + In the context of Windows Registries, a zero-length name means + that this value is the default key for this node in the tree. +diff -ur hivex-1.3.10.old/lib/hivex.syms hivex-1.3.10/lib/hivex.syms +--- hivex-1.3.10.old/lib/hivex.syms 2014-01-10 10:00:53.000000000 +0000 ++++ hivex-1.3.10/lib/hivex.syms 2017-02-17 16:17:58.140476112 +0000 +@@ -3,7 +3,7 @@ + # generator/generator.ml + # ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + # +-# Copyright (C) 2009-2014 Red Hat Inc. ++# Copyright (C) 2009-2017 Red Hat Inc. + # Derived from code by Petter Nordahl-Hagen under a compatible license: + # Copyright (c) 1997-2007 Petter Nordahl-Hagen. + # Derived from code by Markus Stephany under a compatible license: +diff -ur hivex-1.3.10.old/ocaml/hivex_c.c hivex-1.3.10/ocaml/hivex_c.c +--- hivex-1.3.10.old/ocaml/hivex_c.c 2014-01-10 10:00:53.000000000 +0000 ++++ hivex-1.3.10/ocaml/hivex_c.c 2017-02-17 16:17:58.161475510 +0000 +@@ -3,7 +3,7 @@ + * generator/generator.ml + * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + * +- * Copyright (C) 2009-2014 Red Hat Inc. ++ * Copyright (C) 2009-2017 Red Hat Inc. + * Derived from code by Petter Nordahl-Hagen under a compatible license: + * Copyright (c) 1997-2007 Petter Nordahl-Hagen. + * Derived from code by Markus Stephany under a compatible license: +diff -ur hivex-1.3.10.old/ocaml/hivex.ml hivex-1.3.10/ocaml/hivex.ml +--- hivex-1.3.10.old/ocaml/hivex.ml 2014-01-10 10:00:53.000000000 +0000 ++++ hivex-1.3.10/ocaml/hivex.ml 2017-02-17 16:17:58.151475796 +0000 +@@ -3,7 +3,7 @@ + * generator/generator.ml + * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + * +- * Copyright (C) 2009-2014 Red Hat Inc. ++ * Copyright (C) 2009-2017 Red Hat Inc. + * Derived from code by Petter Nordahl-Hagen under a compatible license: + * Copyright (c) 1997-2007 Petter Nordahl-Hagen. + * Derived from code by Markus Stephany under a compatible license: +@@ -56,6 +56,7 @@ + | OPEN_VERBOSE (** Verbose messages *) + | OPEN_DEBUG (** Debug messages *) + | OPEN_WRITE (** Enable writes to the hive *) ++ | OPEN_UNSAFE (** Enable heuristics to allow read/write of corrupted hives *) + + type set_value = { + key : string; +diff -ur hivex-1.3.10.old/ocaml/hivex.mli hivex-1.3.10/ocaml/hivex.mli +--- hivex-1.3.10.old/ocaml/hivex.mli 2014-01-10 10:00:53.000000000 +0000 ++++ hivex-1.3.10/ocaml/hivex.mli 2017-02-17 16:17:58.147475911 +0000 +@@ -3,7 +3,7 @@ + * generator/generator.ml + * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + * +- * Copyright (C) 2009-2014 Red Hat Inc. ++ * Copyright (C) 2009-2017 Red Hat Inc. + * Derived from code by Petter Nordahl-Hagen under a compatible license: + * Copyright (c) 1997-2007 Petter Nordahl-Hagen. + * Derived from code by Markus Stephany under a compatible license: +@@ -63,6 +63,7 @@ + | OPEN_VERBOSE (** Verbose messages *) + | OPEN_DEBUG (** Debug messages *) + | OPEN_WRITE (** Enable writes to the hive *) ++ | OPEN_UNSAFE (** Enable heuristics to allow read/write of corrupted hives *) + (** Open flags for {!open_file} call. *) + + type set_value = { +diff -ur hivex-1.3.10.old/perl/Hivex.xs hivex-1.3.10/perl/Hivex.xs +--- hivex-1.3.10.old/perl/Hivex.xs 2014-01-13 22:20:34.000000000 +0000 ++++ hivex-1.3.10/perl/Hivex.xs 2017-02-17 16:17:58.172475194 +0000 +@@ -3,7 +3,7 @@ + * generator/generator.ml + * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + * +- * Copyright (C) 2009-2014 Red Hat Inc. ++ * Copyright (C) 2009-2017 Red Hat Inc. + * Derived from code by Petter Nordahl-Hagen under a compatible license: + * Copyright (c) 1997-2007 Petter Nordahl-Hagen. + * Derived from code by Markus Stephany under a compatible license: +diff -ur hivex-1.3.10.old/perl/lib/Win/Hivex.pm hivex-1.3.10/perl/lib/Win/Hivex.pm +--- hivex-1.3.10.old/perl/lib/Win/Hivex.pm 2014-01-10 10:00:53.000000000 +0000 ++++ hivex-1.3.10/perl/lib/Win/Hivex.pm 2017-02-17 16:17:58.166475366 +0000 +@@ -3,7 +3,7 @@ + # generator/generator.ml + # ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + # +-# Copyright (C) 2009-2014 Red Hat Inc. ++# Copyright (C) 2009-2017 Red Hat Inc. + # Derived from code by Petter Nordahl-Hagen under a compatible license: + # Copyright (c) 1997-2007 Petter Nordahl-Hagen. + # Derived from code by Markus Stephany under a compatible license: +@@ -66,7 +66,8 @@ + $h = Win::Hivex->open ($filename, + [verbose => 1,] + [debug => 1,] +- [write => 1,]) ++ [write => 1,] ++ [unsafe => 1,]) + + Open a Windows Registry binary hive file. + +@@ -94,6 +95,8 @@ + $flags += 2 if $flags{debug}; + # Enable writes to the hive + $flags += 4 if $flags{write}; ++ # Enable heuristics to allow read/write of corrupted hives ++ $flags += 8 if $flags{unsafe}; + + my $self = Win::Hivex::_open ($filename, $flags); + bless $self, $class; +@@ -212,7 +215,7 @@ + + Return the length of the key (name) of a (key, value) pair as produced + by C. The length can legitimately be 0, so errno is +-the necesary mechanism to check for errors. ++the necessary mechanism to check for errors. + + In the context of Windows Registries, a zero-length name means + that this value is the default key for this node in the tree. +@@ -388,7 +391,7 @@ + + =head1 COPYRIGHT + +-Copyright (C) 2009-2014 Red Hat Inc. ++Copyright (C) 2009-2017 Red Hat Inc. + + =head1 LICENSE + +diff -ur hivex-1.3.10.old/python/hivex.py hivex-1.3.10/python/hivex.py +--- hivex-1.3.10.old/python/hivex.py 2014-01-10 10:00:53.000000000 +0000 ++++ hivex-1.3.10/python/hivex.py 2017-02-17 16:17:58.177475051 +0000 +@@ -3,7 +3,7 @@ + # generator/generator.ml + # ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + # +-# Copyright (C) 2009-2014 Red Hat Inc. ++# Copyright (C) 2009-2017 Red Hat Inc. + # Derived from code by Petter Nordahl-Hagen under a compatible license: + # Copyright (c) 1997-2007 Petter Nordahl-Hagen. + # Derived from code by Markus Stephany under a compatible license: +@@ -39,7 +39,7 @@ + class Hivex(object): + """Instances of this class are hivex API handles.""" + +- def __init__ (self, filename, verbose = False, debug = False, write = False): ++ def __init__ (self, filename, verbose = False, debug = False, write = False, unsafe = False): + """Create a new hivex handle.""" + flags = 0 + # Verbose messages +@@ -48,6 +48,8 @@ + if debug: flags += 2 + # Enable writes to the hive + if write: flags += 4 ++ # Enable heuristics to allow read/write of corrupted hives ++ if unsafe: flags += 8 + self._o = libhivexmod.open (filename, flags) + + def __del__ (self): +diff -ur hivex-1.3.10.old/python/hivex-py.c hivex-1.3.10/python/hivex-py.c +--- hivex-1.3.10.old/python/hivex-py.c 2014-04-23 15:47:20.000000000 +0100 ++++ hivex-1.3.10/python/hivex-py.c 2017-02-17 16:17:58.186474793 +0000 +@@ -3,7 +3,7 @@ + * generator/generator.ml + * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + * +- * Copyright (C) 2009-2014 Red Hat Inc. ++ * Copyright (C) 2009-2017 Red Hat Inc. + * Derived from code by Petter Nordahl-Hagen under a compatible license: + * Copyright (c) 1997-2007 Petter Nordahl-Hagen. + * Derived from code by Markus Stephany under a compatible license: +diff -ur hivex-1.3.10.old/ruby/ext/hivex/_hivex.c hivex-1.3.10/ruby/ext/hivex/_hivex.c +--- hivex-1.3.10.old/ruby/ext/hivex/_hivex.c 2014-01-13 22:20:34.000000000 +0000 ++++ hivex-1.3.10/ruby/ext/hivex/_hivex.c 2017-02-17 16:17:59.440438835 +0000 +@@ -3,7 +3,7 @@ + * generator/generator.ml + * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + * +- * Copyright (C) 2009-2014 Red Hat Inc. ++ * Copyright (C) 2009-2017 Red Hat Inc. + * Derived from code by Petter Nordahl-Hagen under a compatible license: + * Copyright (c) 1997-2007 Petter Nordahl-Hagen. + * Derived from code by Markus Stephany under a compatible license: +@@ -121,6 +121,14 @@ + * read-only. + * + * See "WRITING TO HIVE FILES" in hivex(3). ++ * ++ * HIVEX_OPEN_UNSAFE ++ * Open the hive in unsafe mode that enables heuristics ++ * to handle corrupted hives. ++ * ++ * This may allow to read or write registry keys/values ++ * that appear intact in an otherwise corrupted hive. ++ * Use at your own risk. + * + * + * (For the C API documentation for this function, see +@@ -137,6 +145,8 @@ + flags += 2; + if (RTEST (rb_hash_lookup (flagsv, ID2SYM (rb_intern ("write"))))) + flags += 4; ++ if (RTEST (rb_hash_lookup (flagsv, ID2SYM (rb_intern ("unsafe"))))) ++ flags += 8; + + hive_h *r; + +@@ -580,8 +590,8 @@ + * + * Return the length of the key (name) of a (key, value) + * pair as produced by "h.value_key". The length can +- * legitimately be 0, so errno is the necesary mechanism to +- * check for errors. ++ * legitimately be 0, so errno is the necessary mechanism ++ * to check for errors. + * + * In the context of Windows Registries, a zero-length name + * means that this value is the default key for this node diff --git a/SPECS/hivex.spec b/SPECS/hivex.spec new file mode 100644 index 0000000..e1eacf2 --- /dev/null +++ b/SPECS/hivex.spec @@ -0,0 +1,529 @@ +# conditionalize Ocaml support +%ifarch sparc64 s390 +%bcond_with ocaml +%else +%bcond_without ocaml +%endif + +Name: hivex +Version: 1.3.10 +Release: 6.9%{?dist} +Summary: Read and write Windows Registry binary hive files + +License: LGPLv2 +URL: http://libguestfs.org/ + +Source0: http://libguestfs.org/download/hivex/%{name}-%{version}.tar.gz + +# The RHEL 7 patches are stored in the upstream git repository, +# in the branch called 'rhel-7.4', ie: +# https://github.com/libguestfs/hivex/tree/rhel-7.4 + +# Fix Perl directory install path. +Patch0001: 0001-Fix-Perl-directory-install-path.patch + +# Upstream patches to fix RHBZ#1145056. +Patch0002: 0002-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch +Patch0003: 0003-hivexml-Tidy-up-error-handling-and-printing.patch +Patch0004: 0004-lib-Don-t-leak-errno-from-_hivex_recode-function.patch + +# Upstream patches to fix RHBZ#1158992. +Patch0005: 0005-handle-Refuse-to-open-files-8192-bytes-in-size.patch +Patch0006: 0006-handle-Check-that-pages-do-not-extend-beyond-the-end.patch + +# Fix typo in documentation (RHBZ#1099286). +Patch0007: 0007-generator-Fix-a-spelling-mistake-in-the-documentatio.patch + +# Tolerate corruption in some hives (RHBZ#1423436). +Patch0008: 0008-add-HIVEX_OPEN_UNSAFE-flag.patch +Patch0009: 0009-lib-change-how-hbin-sections-are-read.patch +Patch0010: 0010-lib-allow-to-walk-registry-with-corrupted-blocks.patch +Patch0011: 0011-hivexsh-add-u-flag-for-HIVEX_OPEN_UNSAFE.patch +Patch0012: 0012-hivexregedit-allow-to-pass-HIVEX_OPEN_UNSAFE.patch + +# Patch generated code (because we can't assume we have OCaml on all +# arches). To construct this you need to do 'make prep', run the +# generator by hand, and diff before and after. +Patch9999: generated.patch + +# Use git to apply patches. +BuildRequires: git + +# Since some patches touch autotools file, we need to rerun autoreconf. +BuildRequires: autoconf, automake, libtool, gettext-devel + +BuildRequires: perl +BuildRequires: perl-Test-Simple +BuildRequires: perl-Test-Pod +BuildRequires: perl-Test-Pod-Coverage +BuildRequires: perl-ExtUtils-MakeMaker +BuildRequires: perl-IO-stringy +BuildRequires: perl-libintl +%if %{with ocaml} +BuildRequires: ocaml +BuildRequires: ocaml-findlib-devel +%endif +BuildRequires: python-devel +BuildRequires: ruby-devel +BuildRequires: rubygem-rake +BuildRequires: rubygem(minitest) +BuildRequires: readline-devel +BuildRequires: libxml2-devel + +# This library used to be part of libguestfs. It won't install alongside +# the old version of libguestfs that included this library: +Conflicts: libguestfs <= 1:1.0.84 + +# https://fedoraproject.org/wiki/Packaging:No_Bundled_Libraries#Packages_granted_exceptions +Provides: bundled(gnulib) + + +%description +Hive files are the undocumented binary files that Windows uses to +store the Windows Registry on disk. Hivex is a library that can read +and write to these files. + +'hivexsh' is a shell you can use to interactively navigate a hive +binary file. + +'hivexregedit' lets you export and merge to the textual regedit +format. + +'hivexml' can be used to convert a hive file to a more useful XML +format. + +In order to get access to the hive files themselves, you can copy them +from a Windows machine. They are usually found in +%%systemroot%%\system32\config. For virtual machines we recommend +using libguestfs or guestfish to copy out these files. libguestfs +also provides a useful high-level tool called 'virt-win-reg' (based on +hivex technology) which can be used to query specific registry keys in +an existing Windows VM. + +For OCaml bindings, see 'ocaml-hivex-devel'. + +For Perl bindings, see 'perl-hivex'. + +For Python bindings, see 'python-hivex'. + +For Ruby bindings, see 'ruby-hivex'. + + +%package devel +Summary: Development tools and libraries for %{name} +Requires: %{name} = %{version}-%{release} +Requires: pkgconfig + + +%description devel +%{name}-devel contains development tools and libraries +for %{name}. + + +%if %{with ocaml} +%package -n ocaml-%{name} +Summary: OCaml bindings for %{name} +Requires: %{name} = %{version}-%{release} + + +%description -n ocaml-%{name} +ocaml-%{name} contains OCaml bindings for %{name}. + +This is for toplevel and scripting access only. To compile OCaml +programs which use %{name} you will also need ocaml-%{name}-devel. + + +%package -n ocaml-%{name}-devel +Summary: OCaml bindings for %{name} +Requires: ocaml-%{name} = %{version}-%{release} + + +%description -n ocaml-%{name}-devel +ocaml-%{name}-devel contains development libraries +required to use the OCaml bindings for %{name}. +%endif + + +%package -n perl-%{name} +Summary: Perl bindings for %{name} +Requires: %{name} = %{version}-%{release} +Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version)) + + +%description -n perl-%{name} +perl-%{name} contains Perl bindings for %{name}. + + +%package -n python-%{name} +Summary: Python bindings for %{name} +Requires: %{name} = %{version}-%{release} + +%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} +%{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")} + +%description -n python-%{name} +python-%{name} contains Python bindings for %{name}. + + +%package -n ruby-%{name} +Summary: Ruby bindings for %{name} +Requires: %{name} = %{version}-%{release} +Requires: ruby(release) +Requires: ruby +Provides: ruby(hivex) = %{version} + +%description -n ruby-%{name} +ruby-%{name} contains Ruby bindings for %{name}. + + +%prep +%setup -q + +# Use git to apply patches. +# http://rwmj.wordpress.com/2011/08/09/nice-rpm-git-patch-management-trick/ +git init +git config user.email "libguestfs@redhat.com" +git config user.name "libguestfs" +git add . +git commit -a -q -m "%{version} baseline" +for f in %{patches}; do + if [[ ! "$f" =~ generated.patch ]]; then + git am "$f" + else + patch -p1 < "$f" + fi +done + +autoreconf -i + +%build +%configure --disable-static +make V=1 INSTALLDIRS=vendor %{?_smp_mflags} + + +%check +make check + +%if !%{with ocaml} +# Delete OCaml files, in case the user had OCaml installed and it was +# picked up by the configure script. +# XXX Add ./configure --disable-ocaml upstream. +rm -rf $RPM_BUILD_ROOT%{_libdir}/ocaml/hivex +rm -f $RPM_BUILD_ROOT%{_libdir}/ocaml/stublibs/*hivex* +%endif + + +%install +make install DESTDIR=$RPM_BUILD_ROOT INSTALLDIRS=vendor + +# Remove unwanted libtool *.la file: +rm $RPM_BUILD_ROOT%{_libdir}/libhivex.la + +# Remove unwanted Perl files: +find $RPM_BUILD_ROOT -name perllocal.pod -delete +find $RPM_BUILD_ROOT -name .packlist -delete +find $RPM_BUILD_ROOT -name '*.bs' -delete + +# Remove unwanted Python files: +rm $RPM_BUILD_ROOT%{python_sitearch}/libhivexmod.la + +%find_lang %{name} + + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + + +%files -f %{name}.lang +%doc README LICENSE +%{_bindir}/hivexget +%{_bindir}/hivexml +%{_bindir}/hivexregedit +%{_bindir}/hivexsh +%{_libdir}/libhivex.so.* +%{_mandir}/man1/hivexget.1* +%{_mandir}/man1/hivexml.1* +%{_mandir}/man1/hivexregedit.1* +%{_mandir}/man1/hivexsh.1* + + +%files devel +%doc LICENSE +%{_libdir}/libhivex.so +%{_mandir}/man3/hivex.3* +%{_includedir}/hivex.h +%{_libdir}/pkgconfig/hivex.pc + + +%if %{with ocaml} +%files -n ocaml-%{name} +%doc README +%{_libdir}/ocaml/hivex +%exclude %{_libdir}/ocaml/hivex/*.a +%exclude %{_libdir}/ocaml/hivex/*.cmxa +%exclude %{_libdir}/ocaml/hivex/*.cmx +%exclude %{_libdir}/ocaml/hivex/*.mli +%{_libdir}/ocaml/stublibs/*.so +%{_libdir}/ocaml/stublibs/*.so.owner + + +%files -n ocaml-%{name}-devel +%{_libdir}/ocaml/hivex/*.a +%{_libdir}/ocaml/hivex/*.cmxa +%{_libdir}/ocaml/hivex/*.cmx +%{_libdir}/ocaml/hivex/*.mli +%endif + + +%files -n perl-%{name} +%{perl_vendorarch}/* +%{_mandir}/man3/Win::Hivex.3pm* +%{_mandir}/man3/Win::Hivex::Regedit.3pm* + + +%files -n python-%{name} +%{python_sitearch}/*.py +%{python_sitearch}/*.pyc +%{python_sitearch}/*.pyo +%{python_sitearch}/*.so + + +%files -n ruby-%{name} +%doc ruby/doc/site/* +%{ruby_vendorlibdir}/hivex.rb +%{ruby_vendorarchdir}/_hivex.so + + +%changelog +* Tue Oct 10 2017 Richard W.M. Jones - 1.3.10-6.9 +- Enable OCaml subpackage on s390x. + resolves: rhbz#1447983 + +* Fri Sep 22 2017 Richard W.M. Jones - 1.3.10-6.8 +- Rebuild for OCaml 4.05 + resolves: rhbz#1447983 + +* Fri Feb 17 2017 Richard W.M. Jones - 1.3.10-5.8 +- Tolerate corruption in some hives + resolves: rhbz#1423436 +- Switch to using git to manage patches. + +* Mon Nov 17 2014 Richard W.M. Jones - 1.3.10-5.7 +- Fix: "Argument list too long" when using virt-v2v on Windows guest + with French copy of Citrix installed + related: rhbz#1145056 + +* Mon Nov 17 2014 Richard W.M. Jones - 1.3.10-5.6 +- Fix: typo in man page + resolves: rhbz#1099286 + +* Thu Nov 13 2014 Richard W.M. Jones - 1.3.10-5.4 +- Fix: hivex missing checks for small/truncated files + resolves: rhbz#1158992 + +* Wed Sep 24 2014 Richard W.M. Jones - 1.3.10-5.3 +- Fix: hivexml generates "Argument list too long" error. + resolves: rhbz#1145056 + +* Fri Aug 08 2014 Richard W.M. Jones - 1.3.10-5.2 +- Resolves: rhbz#1125544 + +* Mon Jul 21 2014 Richard W.M. Jones - 1.3.10-5.1 +- Rebase to hivex 1.3.10. + resolves: rhbz#1023978 + +* Fri Jan 24 2014 Daniel Mach - 1.3.8-4 +- Mass rebuild 2014-01-24 + +* Fri Dec 27 2013 Daniel Mach - 1.3.8-3 +- Mass rebuild 2013-12-27 + +* Thu Oct 31 2013 Richard W.M. Jones - 1.3.8-2 +- Drop hivex-static subpackage + resolves: rhbz#1020019 + +* Thu Jul 25 2013 Richard W.M. Jones - 1.3.8-1 +- New upstream version 1.3.8. +- Fixes handling of keys which use ri-records, for both reading and + writing (RHBZ#717583, RHBZ#987463). +- Remove upstream patch. +- Rebase dirs patch against new upstream sources. +- Rebase ruby patch against new upstream sources. +- Modernize the RPM spec file. +- Fix .gitignore. + +* Wed Jul 17 2013 Petr Pisar - 1.3.7-8 +- Perl 5.18 rebuild + +* Wed Mar 13 2013 Richard W.M. Jones - 1.3.7-7 +- Rebuild for Ruby 2.0.0. +- Change ruby(abi) to ruby(release). + +* Fri Feb 15 2013 Richard W.M. Jones - 1.3.7-6 +- Fix for latest Ruby in Rawhide. Fixes build failure identified + by mass rebuild yesterday. +- Do not ignore error from running autoreconf. + +* Thu Feb 14 2013 Fedora Release Engineering - 1.3.7-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Mon Oct 29 2012 Richard W.M. Jones - 1.3.7-2 +- Rebuild for OCaml 4.00.1. + +* Thu Oct 11 2012 Richard W.M. Jones - 1:1.3.7-1 +- New upstream version 1.3.7. + +* Thu Jul 19 2012 Fedora Release Engineering - 1.3.6-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Wed Jun 27 2012 Petr Pisar - 1.3.6-2 +- Perl 5.16 rebuild + +* Tue Jun 12 2012 Richard W.M. Jones - 1:1.3.6-1 +- New upstream version 1.3.6. +- Enable Ocaml bindings on ppc64. + +* Sat Jun 09 2012 Richard W.M. Jones - 1.3.5-9 +- Rebuild for OCaml 4.00.0. + +* Fri Jun 08 2012 Petr Pisar - 1.3.5-8 +- Perl 5.16 rebuild + +* Fri May 18 2012 Richard W.M. Jones - 1:1.3.5-7 +- "blobs" -> "files" in the description. + +* Tue May 15 2012 Richard W.M. Jones - 1:1.3.5-6 +- Bundled gnulib (RHBZ#821763). + +* Fri Mar 23 2012 Richard W.M. Jones - 1:1.3.5-5 +- Don't need to rerun the generator (thanks Dan Horák). + +* Tue Mar 13 2012 Richard W.M. Jones - 1:1.3.5-4 +- New upstream version 1.3.5. +- Remove upstream patch. +- Depend on automake etc. for the patch. + +* Thu Feb 9 2012 Richard W.M. Jones - 1.3.3-8 +- ruby(abi) 1.9.1. + +* Wed Feb 8 2012 Richard W.M. Jones - 1.3.3-7 +- Bump and rebuild for Ruby update. +- Add upstream patch to fix bindings for Ruby 1.9. +- Add non-upstream patch to pass --vendor flag to extconf.rb + +* Fri Jan 06 2012 Richard W.M. Jones - 1.3.3-3 +- Rebuild for OCaml 3.12.1. + +* Thu Dec 8 2011 Richard W.M. Jones - 1.3.3-2 +- Disable OCaml on ppc64. +- Ensure OCaml files are deleted when not packaged. + +* Tue Nov 29 2011 Richard W.M. Jones - 1.3.3-1 +- New upstream version 1.3.3. +- Rebased gnulib to work around RHBZ#756981. +- Remove patches which are now upstream. + +* Mon Oct 24 2011 Richard W.M. Jones - 1.3.2-3 +- New upstream version 1.3.2. +- Add upstream patch to fix building of hivexsh, hivexget. + +* Fri Aug 26 2011 Richard W.M. Jones - 1.3.1-2 +- New upstream version 1.3.1. +- Remove patch, now upstream. +- Don't need hack for making an unversioned Python module. + +* Mon Aug 15 2011 Richard W.M. Jones - 1.3.0-3 +- New upstream version 1.3.0. +- This version adds Ruby bindings, so there is a new subpackage 'ruby-hivex'. +- Add upstream patch to fix Ruby tests. +- Remove epoch macro in ruby-hivex dependency. + +* Fri Aug 12 2011 Richard W.M. Jones - 1.2.8-1 +- New upstream version 1.2.8. +- Remove 4 upstream patches. + +* Fri Jul 22 2011 Richard W.M. Jones - 1.2.7-9 +- Add upstream patch to fix Perl CCFLAGS for Perl 5.14 on i686. +- Enable 'make check'. + +* Thu Jul 21 2011 Richard W.M. Jones - 1.2.7-6 +- i686 package is broken, experimentally rebuild it. + +* Fri Jun 17 2011 Marcela Mašláňová - 1.2.7-5 +- Perl mass rebuild + +* Fri Jun 10 2011 Marcela Mašláňová - 1.2.7-4 +- Perl 5.14 mass rebuild + +* Tue May 17 2011 Richard W.M. Jones - 1.2.7-3 +- New upstream version 1.2.7. +- Removed patch which is now upstream. +- Add upstream patches to fix ocaml install rule. + +* Thu May 12 2011 Richard W.M. Jones - 1.2.6-2 +- New upstream version 1.2.6. +- Removed patch which is now upstream. +- Add upstream patch to fix ocaml tests. + +* Thu Apr 28 2011 Richard W.M. Jones - 1.2.5-2 +- Fix Python bindings on 32 bit arch with upstream patch. + +* Wed Apr 13 2011 Richard W.M. Jones - 1.2.5-1 +- New upstream version 1.2.5. +- This version fixes a number of important memory issues found by + valgrind and upgrading to this version is recommended for all users. +- Remove patch now upstream. + +* Wed Feb 09 2011 Fedora Release Engineering - 1.2.4-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Fri Jan 14 2011 Richard W.M. Jones - 1.2.4-6 +- Fix multilib conflicts in *.pyc and *.pyo files. +- Only install unversioned *.so file for Python bindings. + +* Wed Jan 5 2011 Richard W.M. Jones - 1.2.4-4 +- Rebuild against OCaml 3.12.0. + +* Thu Dec 16 2010 Richard W.M. Jones - 1.2.4-3 +- Backport upstream patch to fix segfault in Hivex.value_value binding. + +* Thu Dec 2 2010 Richard W.M. Jones - 1.2.4-1 +- New upstream version 1.2.4. +- This adds Python bindings (python-hivex subpackage). +- Fix Source0. + +* Fri Nov 19 2010 Dan Horák - 1.2.3-3 +- fix built with recent perl + +* Tue Sep 7 2010 Dan Horák - 1.2.3-2 +- conditionalize ocaml support + +* Fri Aug 27 2010 Richard W.M. Jones - 1.2.3-1 +- New upstream version 1.2.3. + +* Wed Aug 25 2010 Richard W.M. Jones - 1.2.2-3 +- Create a hivex-static subpackage. + +* Thu Apr 29 2010 Marcela Maslanova - 1.2.2-2 +- Mass rebuild with perl-5.12.0 + +* Wed Apr 28 2010 Richard W.M. Jones - 1.2.2-1 +- New upstream version 1.2.2. + +* Tue Mar 30 2010 Richard W.M. Jones - 1.2.1-1 +- New upstream version 1.2.1. +- Includes new tool for exporting and merging in regedit format. + +* Mon Mar 1 2010 Richard W.M. Jones - 1.2.0-2 +- New upstream version 1.2.0. +- This includes OCaml and Perl bindings, so add these as subpackages. + +* Mon Feb 22 2010 Richard W.M. Jones - 1.1.2-3 +- Missing Epoch in conflicts version fixed. + +* Mon Feb 22 2010 Richard W.M. Jones - 1.1.2-2 +- Add Conflicts libguestfs <= 1.0.84. + +* Mon Feb 22 2010 Richard W.M. Jones - 1.1.2-1 +- Initial Fedora RPM.