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(a)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