[Libguestfs] [hivex] [PATCH 1/2] hivex: Expose hive major and minor version

Alex Nelson ajnelson at cs.ucsc.edu
Tue Dec 13 05:59:18 UTC 2011


The major and minor version were being reported in a debug message.
This patch adds the version information to the ABI and reports with
hivexml.

Signed-off-by: Alex Nelson <ajnelson at cs.ucsc.edu>
---
 generator/generator.ml |   10 ++++++++++
 lib/hivex.c            |   32 +++++++++++++++++++++++++++-----
 xml/hivexml.c          |   24 ++++++++++++++++++++++++
 3 files changed, 61 insertions(+), 5 deletions(-)

diff --git a/generator/generator.ml b/generator/generator.ml
index 065c25d..fc7b483 100755
--- a/generator/generator.ml
+++ b/generator/generator.ml
@@ -159,6 +159,16 @@ but instead are lost.  See L<hivex(3)/WRITING TO HIVE FILES>.";
     "\
 Return root node of the hive.  All valid hives must contain a root node.";
 
+  "major_version", (RInt32, [AHive]),
+    "return the major version of the hive",
+    "\
+Return major version stored in the hive header, -1 on error.";
+
+  "minor_version", (RInt32, [AHive]),
+    "return the minor version of the hive",
+    "\
+Return minor version stored in the hive header, -1 on error.";
+
   "last_modified", (RInt64, [AHive]),
     "return the modification time from the header of the hive",
     "\
diff --git a/lib/hivex.c b/lib/hivex.c
index bf1a860..455202f 100644
--- a/lib/hivex.c
+++ b/lib/hivex.c
@@ -64,7 +64,7 @@ struct ntreg_header {
   uint32_t sequence2;
   int64_t last_modified;
   uint32_t major_ver;           /* 1 */
-  uint32_t minor_ver;           /* 3 */
+  uint32_t minor_ver;           /* Seen as 3 in XP, 5 in Vista */
   uint32_t unknown5;            /* 0 */
   uint32_t unknown6;            /* 1 */
   uint32_t offset;              /* offset of root key record - 4KB */
@@ -303,7 +303,7 @@ hivex_open (const char *filename, int flags)
   }
 
   /* Check major version. */
-  uint32_t major_ver = le32toh (h->hdr->major_ver);
+  int32_t major_ver = hivex_major_version (h);
   if (major_ver != 1) {
     fprintf (stderr,
              "hivex: %s: hive file major version %" PRIu32 " (expected 1)\n",
@@ -312,6 +312,16 @@ hivex_open (const char *filename, int flags)
     goto error;
   }
 
+  /* Check minor version; if unable to decode, terminate. */
+  int32_t minor_ver = hivex_minor_version (h);
+  if (minor_ver < 0) {
+    fprintf (stderr,
+             "hivex: %s: could not decode hive minor version\n",
+             filename);
+    errno = EINVAL;
+    goto error;
+  }
+
   h->bitmap = calloc (1 + h->size / 32, 1);
   if (h->bitmap == NULL)
     goto error;
@@ -328,11 +338,11 @@ hivex_open (const char *filename, int flags)
   h->last_modified = le64toh ((int64_t) h->hdr->last_modified);
 
   if (h->msglvl >= 2) {
-    char *name = windows_utf16_to_utf8 (h->hdr->name, 64);
+    char *name = hivex_name (h);
 
     fprintf (stderr,
              "hivex_open: header fields:\n"
-             "  file version             %" PRIu32 ".%" PRIu32 "\n"
+             "  file version             %" PRIi32 ".%" PRIi32 "\n"
              "  sequence nos             %" PRIu32 " %" PRIu32 "\n"
              "    (sequences nos should match if hive was synched at shutdown)\n"
              "  last modified            %" PRIu64 "\n"
@@ -342,7 +352,7 @@ hivex_open (const char *filename, int flags)
              "  root offset              0x%x + 0x1000\n"
              "  end of last page         0x%x + 0x1000 (total file size 0x%zx)\n"
              "  checksum                 0x%x (calculated 0x%x)\n",
-             major_ver, le32toh (h->hdr->minor_ver),
+             major_ver, minor_ver,
              le32toh (h->hdr->sequence1), le32toh (h->hdr->sequence2),
              h->last_modified,
              name ? name : "(conversion failed)",
@@ -624,6 +634,18 @@ hivex_last_modified (hive_h *h)
   return timestamp_check (h, 0, h->last_modified);
 }
 
+int32_t
+hivex_major_version (hive_h *h)
+{
+  return (h && h->hdr) ? (int32_t) le32toh (h->hdr->major_ver) : -1;
+}
+
+int32_t
+hivex_minor_version (hive_h *h)
+{
+  return (h && h->hdr) ? (int32_t) le32toh (h->hdr->minor_ver) : -1;
+}
+
 int64_t
 hivex_node_timestamp (hive_h *h, hive_node_h node)
 {
diff --git a/xml/hivexml.c b/xml/hivexml.c
index d38e9d4..3a4d9b7 100644
--- a/xml/hivexml.c
+++ b/xml/hivexml.c
@@ -136,6 +136,30 @@ main (int argc, char *argv[])
   XML_CHECK (xmlTextWriterStartDocument, (writer, NULL, "utf-8", NULL));
   XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "hive"));
 
+  /* Report the version. */
+  int32_t hive_major_version = hivex_major_version (h);
+  int32_t hive_minor_version = hivex_minor_version (h);
+  if (hive_major_version < 0) {
+    fprintf (stderr, _("hive_major_version: failed to determine major version\n"));
+    exit (EXIT_FAILURE);
+  } else if (hive_minor_version < 0) {
+    fprintf (stderr, _("hive_minor_version: failed to determine minor version\n"));
+    exit (EXIT_FAILURE);
+  } else {
+    char *hive_version_buf = (char *) calloc (8, sizeof (char));
+    if (hive_version_buf == NULL) {
+      fprintf (stderr, _("calloc: failed to allocate version buffer\n"));
+      exit (EXIT_FAILURE);
+    } else {
+      snprintf (hive_version_buf, 8, "%" PRIu32 ".%" PRIu32, hive_major_version, hive_minor_version);
+      XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "hive_version"));
+      XML_CHECK (xmlTextWriterWriteString, (writer, BAD_CAST hive_version_buf));
+      XML_CHECK (xmlTextWriterEndAttribute, (writer));
+      free (hive_version_buf);
+      hive_version_buf = NULL;
+    }
+  }
+
   int64_t hive_mtime = hivex_last_modified (h);
   if (hive_mtime >= 0) {
     char *timebuf = filetime_to_8601 (hive_mtime);
-- 
1.7.6.4






More information about the Libguestfs mailing list