/* 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 #include #include #include #include #include #include #include #include #include "hivex.h" #ifdef HAVE_GETTEXT #include "gettext.h" #define _(str) dgettext(PACKAGE, (str)) //#define N_(str) dgettext(PACKAGE, (str)) #else #define _(str) str //#define N_(str) str #endif /* 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 (EXIT_FAILURE); \ } \ } while (0) int main (int argc, char *argv[]) { setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEBASEDIR); textdomain (PACKAGE); 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 (EXIT_FAILURE); } } if (optind + 1 != argc) { fprintf (stderr, _("hivexml: missing name of input file\n")); exit (EXIT_FAILURE); } hive_h *h = hivex_open (argv[optind], open_flags); if (h == NULL) { perror (argv[optind]); exit (EXIT_FAILURE); } /* 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 (EXIT_FAILURE); } 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 (EXIT_FAILURE); } if (hivex_close (h) == -1) { perror (argv[optind]); exit (EXIT_FAILURE); } XML_CHECK (xmlTextWriterEndElement, (writer)); XML_CHECK (xmlTextWriterEndDocument, (writer)); xmlFreeTextWriter (writer); exit (EXIT_SUCCESS); } 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; }