char id[2]; /* "nk" */
uint16_t flags;
char timestamp[8];
- char unknown0[4];
+ uint32_t unknown1;
uint32_t parent; /* offset of owner/parent */
uint32_t nr_subkeys; /* number of subkeys */
- uint32_t unknown1;
+ uint32_t nr_subkeys_volatile;
uint32_t subkey_lf; /* lf record containing list of subkeys */
- uint32_t unknown2;
+ uint32_t subkey_lf_volatile;
uint32_t nr_values; /* number of values */
uint32_t vallist; /* value-list record */
uint32_t sk; /* offset of sk-record */
uint32_t classname; /* offset of classname record */
- char unknown3[16];
- uint32_t unknown4;
+ uint16_t max_subkey_name_len; /* maximum length of a subkey name in bytes
+ if the subkey was reencoded as UTF-16LE */
+ uint16_t unknown2;
+ uint32_t unknown3;
+ uint32_t max_vk_name_len; /* maximum length of any vk name in bytes
+ if the name was reencoded as UTF-16LE */
+ uint32_t max_vk_data_len; /* maximum length of any vk data in bytes */
+ uint32_t unknown6;
uint16_t name_len; /* length of name */
uint16_t classname_len; /* length of classname */
char name[1]; /* name follows here */
*/
uint32_t data_len;
uint32_t data_offset; /* pointer to the data (or data if inline) */
- hive_type data_type; /* type of the data */
+ uint32_t data_type; /* type of the data */
uint16_t flags; /* bit 0 set => key name ASCII,
bit 0 clr => key name UTF-16.
Only seen ASCII here in the wild. */
} __attribute__((__packed__));
static uint32_t
-header_checksum (hive_h *h)
+header_checksum (const hive_h *h)
{
uint32_t *daddr = (uint32_t *) h->addr;
size_t i;
int used;
seg_len = block_len (h, blkoff, &used);
if (seg_len <= 4 || (seg_len & 3) != 0) {
- fprintf (stderr, "hivex: %s: block size %d at %zu, bad registry\n",
+ fprintf (stderr, "hivex: %s: block size %" PRIu32 " at 0x%zx, bad registry\n",
filename, le32toh (block->seg_len), blkoff);
errno = ENOTSUP;
goto error;
size_t i;
for (i = 0; i < nr_subkeys_in_lf; ++i) {
- hive_node_h subkey = lf->keys[i].offset;
+ hive_node_h subkey = le32toh (lf->keys[i].offset);
subkey += 0x1000;
if (!IS_VALID_BLOCK (h, subkey)) {
if (h->msglvl >= 2)
size_t j;
for (j = 0; j < le16toh (lf->nr_keys); ++j) {
- hive_node_h subkey = lf->keys[j].offset;
+ hive_node_h subkey = le32toh (lf->keys[j].offset);
subkey += 0x1000;
if (!IS_VALID_BLOCK (h, subkey)) {
if (h->msglvl >= 2)
return ret;
}
- size_t data_offset = vk->data_offset;
+ size_t data_offset = le32toh (vk->data_offset);
data_offset += 0x1000;
if (!IS_VALID_BLOCK (h, data_offset)) {
if (h->msglvl >= 2)
/* Check that the declared size isn't larger than the block its in. */
size_t blen = block_len (h, data_offset, NULL);
- if (len > blen) {
+ if (len > blen - 4 /* subtract 4 for block header */) {
if (h->msglvl >= 2)
fprintf (stderr, "hivex_value_value: returning EFAULT because data is longer than its block (data 0x%zx, data len %zu, block len %zu)\n",
data_offset, len, blen);