On Sun, Jun 23, 2013 at 08:52:05PM +0200, Hilko Bengen wrote:
---
lib/hivex.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 66 insertions(+), 15 deletions(-)
diff --git a/lib/hivex.c b/lib/hivex.c
index efc27f8..e3c1e05 100644
--- a/lib/hivex.c
+++ b/lib/hivex.c
@@ -208,6 +208,19 @@ struct ntreg_sk_record {
char sec_desc[1]; /* security info follows */
} __attribute__((__packed__));
+struct ntreg_db_record {
+ int32_t seg_len; /* length (always -ve because used) */
+ char id[2]; /* "db" */
+ uint16_t nr_blocks;
+ uint32_t blocklist_offset;
+ uint32_t unknown1;
+} __attribute__((__packed__));
+
+struct ntreg_db_block {
+ int32_t seg_len;
+ char data[1];
+} __attribute__((__packed__));
+
static uint32_t
header_checksum (const hive_h *h)
{
@@ -1418,22 +1431,60 @@ hivex_value_value (hive_h *h, hive_value_h value,
* instead.
*/
size_t blen = block_len (h, data_offset, NULL);
- if (len > blen - 4 /* subtract 4 for block header */) {
- if (h->msglvl >= 2)
- fprintf (stderr, "hivex_value_value: warning: declared data length "
- "is longer than the block it is in "
- "(data 0x%zx, data len %zu, block len %zu)\n",
- data_offset, len, blen);
- len = blen - 4;
-
- /* Return the smaller length to the caller too. */
- if (len_rtn)
- *len_rtn = len;
+ if (len <= blen - 4 /* subtract 4 for block header */) {
+ char *data = (char *) h->addr + data_offset + 4;
+ memcpy (ret, data, len);
+ return ret;
+ } else {
+ if (!IS_VALID_BLOCK (h, data_offset) || !BLOCK_ID_EQ (h, data_offset,
"db")) {
+ if (h->msglvl >= 2)
+ fprintf (stderr, "hivex_value_value: warning: declared data length "
+ "is longer than the amount of data found in big-data blocks
"
+ "(data 0x%zx, data len %zu)\n",
+ data_offset, len);
+ errno = EINVAL;
+ free (ret);
+ return NULL;
+ }
+ struct ntreg_db_record *db =
+ (struct ntreg_db_record *) ((char *) h->addr + data_offset);
+ size_t blocklist_offset = le32toh (db->blocklist_offset);
+ blocklist_offset += 0x1000;
+ size_t nr_blocks = le16toh (db->nr_blocks);
+ if (!IS_VALID_BLOCK (h, blocklist_offset)) {
+ if (h->msglvl >= 2)
+ fprintf (stderr, "hivex_value_value: warning: blocklist is not a "
+ "valid block "
+ "(db block 0x%zx, blocklist 0x%zx)\n",
+ data_offset, blocklist_offset);
+ errno = EINVAL;
+ free (ret);
+ return NULL;
+ }
+ struct ntreg_value_list *bl =
+ (struct ntreg_value_list *) ((char *) h->addr + blocklist_offset);
+ size_t i, off;
+ for (i=off=0; i < nr_blocks; ++i) {
+ uint32_t subblock_offset = le32toh (bl->offset[i]);
+ subblock_offset += 0x1000;
+ if (!IS_VALID_BLOCK (h, subblock_offset)) {
+ if (h->msglvl >= 2)
+ fprintf (stderr, "hivex_value_value: warning: big data block is not
"
+ "valid (db block 0x%zx, block list 0x%zx, data block
0x%zx)\n",
+ data_offset, blocklist_offset, subblock_offset);
+ }
+ int32_t seg_len = block_len(h, subblock_offset, NULL);
+ struct ntreg_db_block *subblock =
+ (struct ntreg_db_block *) ((char *) h->addr + subblock_offset);
+ int32_t sz = seg_len - 8; /* don't copy the last 4 bytes */
+ if (off + sz > len) {
+ sz = len - off;
+ }
+ memcpy (ret + off, subblock->data, sz);
+ off += sz;
+ }
+ return ret;
}
-
- char *data = (char *) h->addr + data_offset + 4;
- memcpy (ret, data, len);
- return ret;
}
static char *
--
1.8.3.1
You need to add something like this:
diff --git a/lib/hivex.c b/lib/hivex.c
index e3c1e05..9351ac5 100644
--- a/lib/hivex.c
+++ b/lib/hivex.c
@@ -1471,7 +1471,7 @@ hivex_value_value (hive_h *h, hive_value_h value,
if (h->msglvl >= 2)
fprintf (stderr, "hivex_value_value: warning: big data block is not
"
"valid (db block 0x%zx, block list 0x%zx, data block 0x%zx)\
- data_offset, blocklist_offset, subblock_offset);
+ data_offset, blocklist_offset, (size_t) subblock_offset);
}
int32_t seg_len = block_len(h, subblock_offset, NULL);
struct ntreg_db_block *subblock =
to make it compile without warnings.
With that addition, * ACK *.
Rich.
--
Richard Jones, Virtualization Group, Red Hat
http://people.redhat.com/~rjones
virt-p2v converts physical machines to virtual machines. Boot with a
live CD or over the network (PXE) and turn machines into KVM guests.
http://libguestfs.org/virt-v2v