From: Alex Nelson Date: Thu, 8 Dec 2011 02:37:48 +0000 (-0800) Subject: hivex: Add offset-&-length function for long value data X-Git-Url: http://git.annexia.org/?p=hivex.git;a=commitdiff_plain;h=9d276628f3a76f02e487038440cbc3c153d7c273 hivex: Add offset-&-length function for long value data This patch adds value_data_cell_offset to the hivex ABI, to report the hive space used for long (>4 bytes) value data. Signed-off-by: Alex Nelson RWMJ: Rewrote the description of this function to make it clearer. --- diff --git a/generator/generator.ml b/generator/generator.ml index bc1ce44..b0c10eb 100755 --- a/generator/generator.ml +++ b/generator/generator.ml @@ -273,6 +273,20 @@ Return the length of the node data structure."; "\ Return the length of the value data structure."; + "value_data_cell_offset", (RLenValue, [AHive; AValue "val"]), + "return the offset and length of a value data cell", + "\ +Return the offset and length of the value's data cell. + +The data cell is a registry structure that contains the length +(a 4 byte, little endian integer) followed by the data. + +If the length of the value is less than or equal to 4 bytes +then the offset and length returned by this function is zero +as the data is inlined in the value. + +Returns 0 and sets errno on error."; + "value_value", (RLenTypeVal, [AHive; AValue "val"]), "return data length, data type and data of a value", "\ diff --git a/lib/hivex.c b/lib/hivex.c index bf1a860..df313bf 100644 --- a/lib/hivex.c +++ b/lib/hivex.c @@ -1257,6 +1257,66 @@ hivex_value_type (hive_h *h, hive_value_h value, hive_type *t, size_t *len) return 0; } +hive_value_h +hivex_value_data_cell_offset (hive_h *h, hive_value_h value, size_t *len) +{ + if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) { + errno = EINVAL; + return 0; + } + + if (h->msglvl >= 2) + fprintf (stderr, "hivex_value_data_cell_offset: value=0x%zx\n", value); + struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value); + + size_t data_len; + int is_inline; + + data_len = le32toh (vk->data_len); + is_inline = !!(data_len & 0x80000000); + data_len &= 0x7fffffff; + + if (h->msglvl >= 2) + fprintf (stderr, "hivex_value_data_cell_offset: is_inline=%d\n", is_inline); + + if (h->msglvl >= 2) + fprintf (stderr, "hivex_value_data_cell_offset: data_len=%zx\n", data_len); + + if (is_inline && data_len > 4) { + errno = ENOTSUP; + return 0; + } + + if (is_inline) { + /* There is no other location for the value data. */ + if (len) + *len = 0; + return 0; + } else { + if (len) + *len = data_len + 4; /* Include 4 header length bytes */ + } + + if (h->msglvl >= 2) + fprintf (stderr, "hivex_value_data_cell_offset: Proceeding with indirect data.\n"); + + size_t data_offset = le32toh (vk->data_offset); + data_offset += 0x1000; /* Add 0x1000 because everything's off by 4KiB */ + if (!IS_VALID_BLOCK (h, data_offset)) { + if (h->msglvl >= 2) + fprintf (stderr, "hivex_value_data_cell_offset: returning EFAULT because data " + "offset is not a valid block (0x%zx)\n", + data_offset); + errno = EFAULT; + return 0; + } + + if (h->msglvl >= 2) + fprintf (stderr, "hivex_value_data_cell_offset: data_offset=%zx\n", data_offset); + + return data_offset; +} + char * hivex_value_value (hive_h *h, hive_value_h value, hive_type *t_rtn, size_t *len_rtn)