Alex Nelson
2011-Oct-19 23:53 UTC
[Libguestfs] [hivex][PATCH 8/8] hivexml: Add byte run reporting functions
This patch adds value_byte_runs and node_byte_runs. Each byte run represents the offset and length of a data structure within the hive, one per node, and one or two per value depending on the length of the value data. These byte run functions also add additional data sanity checks as a hive is being parsed, mainly checking that a node address actually points to a node, and similarly for values. Signed-off-by: Alex Nelson <ajnelson at cs.ucsc.edu> --- xml/hivexml.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 95 insertions(+), 9 deletions(-) diff --git a/xml/hivexml.c b/xml/hivexml.c index 5030c24..7e5f51c 100644 --- a/xml/hivexml.c +++ b/xml/hivexml.c @@ -208,6 +208,34 @@ filetime_to_8601 (int64_t windows_ticks) return ret; } +#define BYTE_RUN_BUF_LEN 32 + +static int +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); + } + return -1; + } + /* A node has one byte run. */ + XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "byte_runs")); + XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "byte_run")); + memset (buf, 0, 1+BYTE_RUN_BUF_LEN); + snprintf (buf, 1+BYTE_RUN_BUF_LEN, "%d", node); + XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "file_offset", BAD_CAST buf)); + snprintf (buf, 1+BYTE_RUN_BUF_LEN, "%d", node_struct_length); + XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "len", BAD_CAST buf)); + XML_CHECK (xmlTextWriterEndElement, (writer)); + XML_CHECK (xmlTextWriterEndElement, (writer)); + return 0; +} + static int node_start (hive_h *h, void *writer_v, hive_node_h node, const char *name) { @@ -234,7 +262,8 @@ node_start (hive_h *h, void *writer_v, hive_node_h node, const char *name) } } - return 0; + ret = node_byte_runs (h, writer_v, node); + return ret; } static int @@ -266,11 +295,53 @@ end_value (xmlTextWriterPtr writer) } static int +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); + } + return -1; + } + hive_value_h value_data_cell_offset = hivex_value_data_cell_offset (h, value, &value_data_cell_length); + if (errno != 0) + return -1; + + XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "byte_runs")); + memset (buf, 0, 1+BYTE_RUN_BUF_LEN); + + /* Write first byte run for data structure */ + XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "byte_run")); + snprintf (buf, 1+BYTE_RUN_BUF_LEN, "%d", value); + XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "file_offset", BAD_CAST buf)); + snprintf (buf, 1+BYTE_RUN_BUF_LEN, "%d", value_data_structure_length); + XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "len", BAD_CAST buf)); + XML_CHECK (xmlTextWriterEndElement, (writer)); + + /* Write second byte run for longer values */ + if (value_data_cell_length > 4) { + XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "byte_run")); + snprintf (buf, 1+BYTE_RUN_BUF_LEN, "%d", value_data_cell_offset); + XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "file_offset", BAD_CAST buf)); + snprintf (buf, 1+BYTE_RUN_BUF_LEN, "%d", value_data_cell_length); + XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "len", BAD_CAST buf)); + XML_CHECK (xmlTextWriterEndElement, (writer)); + } + XML_CHECK (xmlTextWriterEndElement, (writer)); + return 0; +} + +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; + int ret = 0; switch (t) { case hive_t_string: type = "string"; break; @@ -296,8 +367,9 @@ value_string (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value, XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "value")); XML_CHECK (xmlTextWriterWriteString, (writer, BAD_CAST str)); XML_CHECK (xmlTextWriterEndAttribute, (writer)); + ret = value_byte_runs (h, writer_v, value); end_value (writer); - return 0; + return ret; } static int @@ -306,6 +378,7 @@ value_multiple_strings (hive_h *h, void *writer_v, hive_node_h node, const char *key, char **argv) { xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; + int ret = 0; start_value (writer, key, "string-list", NULL); size_t i; @@ -315,8 +388,9 @@ value_multiple_strings (hive_h *h, void *writer_v, hive_node_h node, XML_CHECK (xmlTextWriterEndElement, (writer)); } + ret = value_byte_runs (h, writer_v, value); end_value (writer); - return 0; + return ret; } static int @@ -327,6 +401,7 @@ value_string_invalid_utf16 (hive_h *h, void *writer_v, hive_node_h node, { xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; const char *type; + int ret = 0; switch (t) { case hive_t_string: type = "bad-string"; break; @@ -352,9 +427,10 @@ value_string_invalid_utf16 (hive_h *h, void *writer_v, hive_node_h node, XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "value")); XML_CHECK (xmlTextWriterWriteBase64, (writer, str, 0, len)); XML_CHECK (xmlTextWriterEndAttribute, (writer)); + ret = value_byte_runs (h, writer_v, value); end_value (writer); - return 0; + return ret; } static int @@ -362,10 +438,12 @@ 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; + int ret = 0; start_value (writer, key, "int32", NULL); XML_CHECK (xmlTextWriterWriteFormatAttribute, (writer, BAD_CAST "value", "%" PRIi32, v)); + ret = value_byte_runs (h, writer_v, value); end_value (writer); - return 0; + return ret; } static int @@ -373,10 +451,12 @@ 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; + int ret = 0; start_value (writer, key, "int64", NULL); XML_CHECK (xmlTextWriterWriteFormatAttribute, (writer, BAD_CAST "value", "%" PRIi64, v)); + ret = value_byte_runs (h, writer_v, value); end_value (writer); - return 0; + return ret; } static int @@ -384,12 +464,14 @@ 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; + int ret = 0; start_value (writer, key, "binary", "base64"); XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "value")); XML_CHECK (xmlTextWriterWriteBase64, (writer, v, 0, len)); XML_CHECK (xmlTextWriterEndAttribute, (writer)); + ret = value_byte_runs (h, writer_v, value); end_value (writer); - return 0; + return ret; } static int @@ -397,14 +479,16 @@ 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; + int ret = 0; start_value (writer, key, "none", "base64"); if (len > 0) { XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "value")); XML_CHECK (xmlTextWriterWriteBase64, (writer, v, 0, len)); XML_CHECK (xmlTextWriterEndAttribute, (writer)); + ret = value_byte_runs (h, writer_v, value); } end_value (writer); - return 0; + return ret; } static int @@ -413,6 +497,7 @@ value_other (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value, { xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v; const char *type; + int ret = 0; switch (t) { case hive_t_none: @@ -439,8 +524,9 @@ value_other (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value, XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "value")); XML_CHECK (xmlTextWriterWriteBase64, (writer, v, 0, len)); XML_CHECK (xmlTextWriterEndAttribute, (writer)); + ret = value_byte_runs (h, writer_v, value); } end_value (writer); - return 0; + return ret; } -- 1.7.4.4