diff options
author | Richard Jones <rjones@redhat.com> | 2009-10-26 11:03:07 +0000 |
---|---|---|
committer | Richard Jones <rjones@redhat.com> | 2009-10-29 15:58:23 +0000 |
commit | 792c5283009ed6753239a14df9a6e9c71bea35fd (patch) | |
tree | dfe3bf8136e85adedbb3c9d98ef748f4b61f2ec0 /hivex/hivexml.c | |
parent | d609130cb65fe7795b168a796426e39d64ceda97 (diff) | |
download | libguestfs-792c5283009ed6753239a14df9a6e9c71bea35fd.tar.gz libguestfs-792c5283009ed6753239a14df9a6e9c71bea35fd.tar.xz libguestfs-792c5283009ed6753239a14df9a6e9c71bea35fd.zip |
Support for Windows Registry.
In hivex/: This mini-library allows us to extract Windows
Registry binary files ("hives").
There are also two tools: hivexml converts a hive to a
self-describing XML format. hivexget can be used to extract
single subkeys from a hive.
New tool: virt-win-reg. This is a wrapper around the library
functionality allowing you to pull out data from the registries
of Windows guests.
Diffstat (limited to 'hivex/hivexml.c')
-rw-r--r-- | hivex/hivexml.c | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/hivex/hivexml.c b/hivex/hivexml.c new file mode 100644 index 00000000..af3de9e4 --- /dev/null +++ b/hivex/hivexml.c @@ -0,0 +1,330 @@ +/* hivexml - Convert Windows Registry "hive" to XML file. + * Copyright (C) 2009 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <inttypes.h> +#include <unistd.h> +#include <errno.h> + +#include <libxml/xmlwriter.h> + +#include "hivex.h" + +/* Callback functions. */ +static int node_start (hive_h *, void *, hive_node_h, const char *name); +static int node_end (hive_h *, void *, hive_node_h, const char *name); +static int value_string (hive_h *, void *, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *str); +static int value_multiple_strings (hive_h *, void *, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, char **argv); +static int value_string_invalid_utf16 (hive_h *, void *, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *str); +static int value_dword (hive_h *, void *, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, int32_t); +static int value_qword (hive_h *, void *, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, int64_t); +static int value_binary (hive_h *, void *, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *value); +static int value_none (hive_h *, void *, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *value); +static int value_other (hive_h *, void *, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *value); + +static struct hivex_visitor visitor = { + .node_start = node_start, + .node_end = node_end, + .value_string = value_string, + .value_multiple_strings = value_multiple_strings, + .value_string_invalid_utf16 = value_string_invalid_utf16, + .value_dword = value_dword, + .value_qword = value_qword, + .value_binary = value_binary, + .value_none = value_none, + .value_other = value_other +}; + +#define XML_CHECK(proc, args) \ + do { \ + if ((proc args) == -1) { \ + fprintf (stderr, "%s: failed to write XML document\n", #proc); \ + exit (1); \ + } \ + } while (0) + +int +main (int argc, char *argv[]) +{ + int c; + int open_flags = 0; + int visit_flags = 0; + + while ((c = getopt (argc, argv, "dk")) != EOF) { + switch (c) { + case 'd': + open_flags |= HIVEX_OPEN_DEBUG; + break; + case 'k': + visit_flags |= HIVEX_VISIT_SKIP_BAD; + break; + default: + fprintf (stderr, "hivexml [-dk] regfile > output.xml\n"); + exit (1); + } + } + + if (optind + 1 != argc) { + fprintf (stderr, "hivexml: missing name of input file\n"); + exit (1); + } + + hive_h *h = hivex_open (argv[optind], open_flags); + if (h == NULL) { + perror (argv[optind]); + exit (1); + } + + /* Note both this macro, and xmlTextWriterStartDocument leak memory. There + * doesn't seem to be any way to recover that memory, but it's not a + * large amount. + */ + LIBXML_TEST_VERSION; + + xmlTextWriterPtr writer; + writer = xmlNewTextWriterFilename ("/dev/stdout", 0); + if (writer == NULL) { + fprintf (stderr, "xmlNewTextWriterFilename: failed to create XML writer\n"); + exit (1); + } + + XML_CHECK (xmlTextWriterStartDocument, (writer, NULL, "utf-8", NULL)); + XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "hive")); + + if (hivex_visit (h, &visitor, sizeof visitor, writer, visit_flags) == -1) { + perror (argv[optind]); + exit (1); + } + + if (hivex_close (h) == -1) { + perror (argv[optind]); + exit (1); + } + + XML_CHECK (xmlTextWriterEndElement, (writer)); + XML_CHECK (xmlTextWriterEndDocument, (writer)); + xmlFreeTextWriter (writer); + + exit (0); +} + +static int +node_start (hive_h *h, void *writer_v, hive_node_h node, const char *name) +{ + xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; + XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "node")); + XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "name", BAD_CAST name)); + return 0; +} + +static int +node_end (hive_h *h, void *writer_v, hive_node_h node, const char *name) +{ + xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; + XML_CHECK (xmlTextWriterEndElement, (writer)); + return 0; +} + +static void +start_value (xmlTextWriterPtr writer, + const char *key, const char *type, const char *encoding) +{ + XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "value")); + XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "type", BAD_CAST type)); + if (encoding) + XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "encoding", BAD_CAST encoding)); + if (*key) + XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "key", BAD_CAST key)); + else /* default key */ + XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "default", BAD_CAST "1")); +} + +static void +end_value (xmlTextWriterPtr writer) +{ + XML_CHECK (xmlTextWriterEndElement, (writer)); +} + +static int +value_string (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value, + hive_type t, size_t len, const char *key, const char *str) +{ + xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; + const char *type; + + switch (t) { + case hive_t_string: type = "string"; break; + case hive_t_expand_string: type = "expand"; break; + case hive_t_link: type = "link"; break; + + case hive_t_none: + case hive_t_binary: + case hive_t_dword: + case hive_t_dword_be: + case hive_t_multiple_strings: + case hive_t_resource_list: + case hive_t_full_resource_description: + case hive_t_resource_requirements_list: + case hive_t_qword: + abort (); /* internal error - should not happen */ + + default: + type = "unknown"; + } + + start_value (writer, key, type, NULL); + XML_CHECK (xmlTextWriterWriteString, (writer, BAD_CAST str)); + end_value (writer); + return 0; +} + +static int +value_multiple_strings (hive_h *h, void *writer_v, hive_node_h node, + hive_value_h value, hive_type t, size_t len, + const char *key, char **argv) +{ + xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; + start_value (writer, key, "string-list", NULL); + + size_t i; + for (i = 0; argv[i] != NULL; ++i) { + XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "string")); + XML_CHECK (xmlTextWriterWriteString, (writer, BAD_CAST argv[i])); + XML_CHECK (xmlTextWriterEndElement, (writer)); + } + + end_value (writer); + return 0; +} + +static int +value_string_invalid_utf16 (hive_h *h, void *writer_v, hive_node_h node, + hive_value_h value, hive_type t, size_t len, + const char *key, + const char *str /* original data */) +{ + xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; + const char *type; + + switch (t) { + case hive_t_string: type = "bad-string"; break; + case hive_t_expand_string: type = "bad-expand"; break; + case hive_t_link: type = "bad-link"; break; + case hive_t_multiple_strings: type = "bad-string-list"; break; + + case hive_t_none: + case hive_t_binary: + case hive_t_dword: + case hive_t_dword_be: + case hive_t_resource_list: + case hive_t_full_resource_description: + case hive_t_resource_requirements_list: + case hive_t_qword: + abort (); /* internal error - should not happen */ + + default: + type = "unknown"; + } + + start_value (writer, key, type, "base64"); + XML_CHECK (xmlTextWriterWriteBase64, (writer, str, 0, len)); + end_value (writer); + + return 0; +} + +static int +value_dword (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value, + hive_type t, size_t len, const char *key, int32_t v) +{ + xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; + start_value (writer, key, "int32", NULL); + XML_CHECK (xmlTextWriterWriteFormatString, (writer, "%" PRIi32, v)); + end_value (writer); + return 0; +} + +static int +value_qword (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value, + hive_type t, size_t len, const char *key, int64_t v) +{ + xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; + start_value (writer, key, "int64", NULL); + XML_CHECK (xmlTextWriterWriteFormatString, (writer, "%" PRIi64, v)); + end_value (writer); + return 0; +} + +static int +value_binary (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value, + hive_type t, size_t len, const char *key, const char *v) +{ + xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; + start_value (writer, key, "binary", "base64"); + XML_CHECK (xmlTextWriterWriteBase64, (writer, v, 0, len)); + end_value (writer); + return 0; +} + +static int +value_none (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value, + hive_type t, size_t len, const char *key, const char *v) +{ + xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; + start_value (writer, key, "none", "base64"); + if (len > 0) XML_CHECK (xmlTextWriterWriteBase64, (writer, v, 0, len)); + end_value (writer); + return 0; +} + +static int +value_other (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value, + hive_type t, size_t len, const char *key, const char *v) +{ + xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; + const char *type; + + switch (t) { + case hive_t_none: + case hive_t_binary: + case hive_t_dword: + case hive_t_dword_be: + case hive_t_qword: + case hive_t_string: + case hive_t_expand_string: + case hive_t_link: + case hive_t_multiple_strings: + abort (); /* internal error - should not happen */ + + case hive_t_resource_list: type = "resource-list"; break; + case hive_t_full_resource_description: type = "resource-description"; break; + case hive_t_resource_requirements_list: type = "resource-requirements"; break; + + default: + type = "unknown"; + } + + start_value (writer, key, type, "base64"); + if (len > 0) XML_CHECK (xmlTextWriterWriteBase64, (writer, v, 0, len)); + end_value (writer); + + return 0; +} |