Changeset 151
- Timestamp:
- 03/04/09 16:14:09 (16 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/regfi.h
r150 r151 95 95 #define REGFI_REGF_SIZE 0x1000 /* "regf" header block size */ 96 96 #define REGFI_REGF_MAGIC_SIZE 4 97 #define REGFI_REGF_NAME_SIZE 64 98 99 #define REGFI_REGF_RESERVED1_SIZE 340 100 #define REGFI_REGF_RESERVED2_SIZE 3528 101 97 102 #define REGFI_HBIN_MAGIC_SIZE 4 98 103 #define REGFI_CELL_MAGIC_SIZE 2 … … 337 342 /********************************/ 338 343 uint8 magic[REGFI_REGF_MAGIC_SIZE];/* "regf" */ 344 345 /* These sequence numbers should match if 346 * the hive was properly synced to disk. 347 */ 348 uint32 sequence1; 349 uint32 sequence2; 350 339 351 NTTIME mtime; 340 uint32 data_offset; /* offset to record in the first (or any?) 341 * hbin block 342 */ 343 uint32 last_block; /* offset to last hbin block in file */ 344 345 uint32 checksum; /* Stored checksum. */ 346 uint32 computed_checksum; /* Our own calculation of the checksum. 347 * (XOR of bytes 0x0000 - 0x01FB) 348 */ 349 350 /* XXX: Some of these we have some clues about (major/minor version, etc). 351 * Should verify and update names accordingly. 352 */ 353 /* unknown data structure values */ 354 uint32 unknown1; 355 uint32 unknown2; 356 uint32 unknown3; 357 uint32 unknown4; 358 uint32 unknown5; 359 uint32 unknown6; 360 uint32 unknown7; 352 uint32 major_version; /* XXX: Unverified. Set to 1 in all known hives */ 353 uint32 minor_version; /* XXX: Unverified. Set to 3 or 5 in all known hives */ 354 uint32 type; /* XXX: Unverified. Set to 0 in all known hives */ 355 uint32 format; /* XXX: Unverified. Set to 1 in all known hives */ 356 357 uint32 root_cell; /* Offset to root cell in the first (or any?) hbin block */ 358 uint32 last_block; /* Offset to last hbin block in file 359 * (or length of file minus header?) */ 360 361 uint32 cluster; /* XXX: Unverified. Set to 1 in all known hives */ 362 363 /* Matches hive's base file name. Stored in UTF-16LE */ 364 uint8 file_name[REGFI_REGF_NAME_SIZE]; 365 366 WINSEC_UUID* rm_id; /* XXX: Unverified. */ 367 WINSEC_UUID* log_id; /* XXX: Unverified. */ 368 WINSEC_UUID* tm_id; /* XXX: Unverified. */ 369 uint32 flags; /* XXX: Unverified. */ 370 uint32 guid_signature; /* XXX: Unverified. */ 371 372 uint32 checksum; /* Stored checksum from file */ 373 uint32 computed_checksum; /* Our own calculation of the checksum. 374 * (XOR of bytes 0x0000 - 0x01FB) */ 375 376 WINSEC_UUID* thaw_tm_id; /* XXX: Unverified. */ 377 WINSEC_UUID* thaw_rm_id; /* XXX: Unverified. */ 378 WINSEC_UUID* thaw_log_id; /* XXX: Unverified. */ 379 uint32 boot_type; /* XXX: Unverified. */ 380 uint32 boot_recover; /* XXX: Unverified. */ 381 382 /* This seems to include random junk. Possibly unsanitized memory left over 383 * from when header block was written. For instance, chunks of nk records 384 * can be found, though often it's all 0s. */ 385 uint8 reserved1[REGFI_REGF_RESERVED1_SIZE]; 386 387 /* This is likely reserved and unusued currently. (Should be all 0s.) 388 * Included here for easier access in looking for hidden data 389 * or doing research. */ 390 uint8 reserved2[REGFI_REGF_RESERVED2_SIZE]; 391 361 392 } REGFI_FILE; 362 393 … … 367 398 * whole keys. 368 399 */ 369 typedef struct 400 typedef struct _regfi_iterator 370 401 { 371 402 REGFI_FILE* f; … … 377 408 378 409 379 typedef struct 410 typedef struct _regfi_iter_position 380 411 { 381 412 REGFI_NK_REC* nk; … … 385 416 */ 386 417 } REGFI_ITER_POSITION; 418 419 420 typedef struct _regfi_buffer 421 { 422 uint8* buf; 423 uint32_t len; 424 } REGFI_BUFFER; 387 425 388 426 … … 478 516 uint32 max_size, bool strict); 479 517 480 uint8*regfi_parse_data(REGFI_FILE* file,518 REGFI_BUFFER regfi_parse_data(REGFI_FILE* file, 481 519 uint32 data_type, uint32 offset, 482 520 uint32 length, uint32 max_size, -
trunk/lib/regfi.c
r150 r151 948 948 const REGFI_HBIN* hbin; 949 949 uint32 data_offset, data_maxsize; 950 REGFI_BUFFER data; 950 951 951 952 hbin = regfi_lookup_hbin(file, offset - REGFI_REGF_SIZE); … … 965 966 if(ret_val->data_in_offset) 966 967 { 967 ret_val->data = regfi_parse_data(file, ret_val->type, ret_val->data_off, 968 ret_val->data_size, 4, 969 ret_val->data_in_offset, strict); 968 data = regfi_parse_data(file, ret_val->type, ret_val->data_off, 969 ret_val->data_size, 4, 970 ret_val->data_in_offset, strict); 971 ret_val->data = data.buf; 972 ret_val->data_size = data.len; 970 973 } 971 974 else … … 976 979 data_offset = ret_val->data_off+REGFI_REGF_SIZE; 977 980 data_maxsize = hbin->block_size + hbin->file_off - data_offset; 978 ret_val->data = regfi_parse_data(file, ret_val->type, data_offset, 979 ret_val->data_size, data_maxsize, 980 ret_val->data_in_offset, strict); 981 data = regfi_parse_data(file, ret_val->type, data_offset, 982 ret_val->data_size, data_maxsize, 983 ret_val->data_in_offset, strict); 984 ret_val->data = data.buf; 985 ret_val->data_size = data.len; 986 981 987 } 982 988 else … … 992 998 { 993 999 regfi_add_message(file, REGFI_MSG_WARN, "Could not parse data record" 994 " while parsing VK record at offset 0x%.8X.", 1000 " while parsing VK record at offset 0x%.8X.", 995 1001 ret_val->offset); 996 1002 } … … 1740 1746 regfi_add_message(ret_val, REGFI_MSG_WARN, "Magic number mismatch " 1741 1747 "(%.2X %.2X %.2X %.2X) while parsing hive header", 1742 ret_val->magic[0], ret_val->magic[1],1748 ret_val->magic[0], ret_val->magic[1], 1743 1749 ret_val->magic[2], ret_val->magic[3]); 1744 1750 } 1745 1746 ret_val->unknown1 = IVAL(file_header, 0x4); 1747 ret_val->unknown2 = IVAL(file_header, 0x8); 1748 1751 ret_val->sequence1 = IVAL(file_header, 0x4); 1752 ret_val->sequence2 = IVAL(file_header, 0x8); 1749 1753 ret_val->mtime.low = IVAL(file_header, 0xC); 1750 1754 ret_val->mtime.high = IVAL(file_header, 0x10); 1751 1752 ret_val->unknown3 = IVAL(file_header, 0x14); 1753 ret_val->unknown4 = IVAL(file_header, 0x18); 1754 ret_val->unknown5 = IVAL(file_header, 0x1C); 1755 ret_val->unknown6 = IVAL(file_header, 0x20); 1756 1757 ret_val->data_offset = IVAL(file_header, 0x24); 1755 ret_val->major_version = IVAL(file_header, 0x14); 1756 ret_val->minor_version = IVAL(file_header, 0x18); 1757 ret_val->type = IVAL(file_header, 0x1C); 1758 ret_val->format = IVAL(file_header, 0x20); 1759 ret_val->root_cell = IVAL(file_header, 0x24); 1758 1760 ret_val->last_block = IVAL(file_header, 0x28); 1759 1761 1760 ret_val->unknown7 = IVAL(file_header, 0x2C); 1762 ret_val->cluster = IVAL(file_header, 0x2C); 1763 1764 memcpy(ret_val->file_name, file_header+0x30, REGFI_REGF_NAME_SIZE); 1765 1766 /* XXX: Should we add a warning if these uuid parsers fail? Can they? */ 1767 ret_val->rm_id = winsec_parse_uuid(ret_val, file_header+0x70, 16); 1768 ret_val->log_id = winsec_parse_uuid(ret_val, file_header+0x80, 16); 1769 ret_val->flags = IVAL(file_header, 0x90); 1770 ret_val->tm_id = winsec_parse_uuid(ret_val, file_header+0x94, 16); 1771 ret_val->guid_signature = IVAL(file_header, 0xa4); 1772 1773 memcpy(ret_val->reserved1, file_header+0xa8, REGFI_REGF_RESERVED1_SIZE); 1774 memcpy(ret_val->reserved2, file_header+0x200, REGFI_REGF_RESERVED2_SIZE); 1775 1776 ret_val->thaw_tm_id = winsec_parse_uuid(ret_val, file_header+0xFC8, 16); 1777 ret_val->thaw_rm_id = winsec_parse_uuid(ret_val, file_header+0xFD8, 16); 1778 ret_val->thaw_log_id = winsec_parse_uuid(ret_val, file_header+0xFE8, 16); 1779 ret_val->boot_type = IVAL(file_header, 0x90); 1780 ret_val->boot_recover = IVAL(file_header, 0x90); 1761 1781 1762 1782 return ret_val; … … 2201 2221 2202 2222 2203 uint8*regfi_parse_data(REGFI_FILE* file,2204 uint32 data_type, uint32 offset,2205 uint32 length, uint32 max_size,2206 bool data_in_offset, bool strict)2207 { 2208 uint8*ret_val;2223 REGFI_BUFFER regfi_parse_data(REGFI_FILE* file, 2224 uint32 data_type, uint32 offset, 2225 uint32 length, uint32 max_size, 2226 bool data_in_offset, bool strict) 2227 { 2228 REGFI_BUFFER ret_val; 2209 2229 uint32 read_length, cell_length; 2210 2230 uint8 i; 2211 2231 bool unalloc; 2212 2232 2213 2233 /* The data is typically stored in the offset if the size <= 4 */ 2214 2234 if(data_in_offset) … … 2219 2239 " while parsing data record at offset 0x%.8X.", 2220 2240 offset); 2221 return NULL; 2222 } 2223 2224 if((ret_val = talloc_array(NULL, uint8_t, length)) == NULL) 2225 return NULL; 2241 goto fail; 2242 } 2243 2244 if((ret_val.buf = talloc_array(NULL, uint8_t, length)) == NULL) 2245 goto fail; 2246 ret_val.len = length; 2226 2247 2227 2248 for(i = 0; i < length; i++) 2228 ret_val [i] = (uint8)((offset >> i*8) & 0xFF);2249 ret_val.buf[i] = (uint8)((offset >> i*8) & 0xFF); 2229 2250 } 2230 2251 else … … 2235 2256 regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while" 2236 2257 " parsing data record at offset 0x%.8X.", offset); 2237 return NULL;2258 goto fail; 2238 2259 } 2239 2260 … … 2243 2264 " while parsing data record at offset 0x%.8X.", 2244 2265 offset); 2245 return NULL;2266 goto fail; 2246 2267 } 2247 2268 … … 2252 2273 offset); 2253 2274 if(strict) 2254 return NULL;2275 goto fail; 2255 2276 else 2256 2277 cell_length = max_size; … … 2261 2282 /* XXX: This strict condition has been triggered in multiple registries. 2262 2283 * Not sure the cause, but the data length values are very large, 2263 * such as 53392. 2284 * such as 53392. For now, we're truncating the size and returning 2285 * what we can, since this issue is so common. 2264 2286 */ 2265 2287 regfi_add_message(file, REGFI_MSG_WARN, "Data length (0x%.8X) larger than" … … 2267 2289 " while parsing data record at offset 0x%.8X.", 2268 2290 length, cell_length - 4, offset); 2291 /* 2269 2292 if(strict) 2270 return NULL;2293 goto fail; 2271 2294 else 2272 length = cell_length - 4; 2273 } 2274 2275 if((ret_val = talloc_array(NULL, uint8_t, length)) == NULL) 2276 return NULL; 2295 */ 2296 length = cell_length - 4; 2297 } 2298 2299 if((ret_val.buf = talloc_array(NULL, uint8_t, length)) == NULL) 2300 goto fail; 2301 ret_val.len = length; 2277 2302 2278 2303 read_length = length; 2279 if((regfi_read(file->fd, ret_val , &read_length) != 0)2304 if((regfi_read(file->fd, ret_val.buf, &read_length) != 0) 2280 2305 || read_length != length) 2281 2306 { 2282 2307 regfi_add_message(file, REGFI_MSG_ERROR, "Could not read data block while" 2283 2308 " parsing data record at offset 0x%.8X.", offset); 2284 talloc_free(ret_val); 2285 return NULL; 2286 } 2287 } 2288 2309 talloc_free(ret_val.buf); 2310 goto fail; 2311 } 2312 } 2313 2314 return ret_val; 2315 2316 fail: 2317 ret_val.buf = NULL; 2318 ret_val.len = 0; 2289 2319 return ret_val; 2290 2320 } -
trunk/src/reglookup-recover.c
r150 r151 263 263 uint32 virt_offset, i, stack_size, ret_val_size, ret_val_used; 264 264 uint32 max_length; 265 /* A little hack so we don't have to walk a quoted string twice. */ 266 struct name_holder 267 { 268 char* quoted_name; 269 uint32_t length; 270 }; 271 struct name_holder* path_element; 272 265 REGFI_BUFFER* path_element; 273 266 274 267 /* The path_stack size limit should guarantee that we don't recurse forever. */ … … 298 291 virt_offset = cur_ancestor->parent_off; 299 292 300 path_element = talloc(path_stack, struct name_holder);293 path_element = talloc(path_stack, REGFI_BUFFER); 301 294 if(path_element != NULL) 302 path_element-> quoted_name =quote_string(cur_ancestor->keyname,295 path_element->buf = (uint8*)quote_string(cur_ancestor->keyname, 303 296 key_special_chars); 304 297 305 if(path_element == NULL || path_element-> quoted_name== NULL298 if(path_element == NULL || path_element->buf == NULL 306 299 || !void_stack_push(path_stack, path_element)) 307 300 { … … 316 309 * 16 bits and the max depth is 512. 317 310 */ 318 path_element->len gth = strlen(path_element->quoted_name);319 ret_val_size += path_element->len gth+ 1;311 path_element->len = strlen((char*)path_element->buf); 312 ret_val_size += path_element->len + 1; 320 313 321 314 regfi_free_key(cur_ancestor); … … 338 331 path_element = void_stack_pop(path_stack); 339 332 snprintf(ret_val+ret_val_used, ret_val_size-ret_val_used, 340 "/%s", path_element-> quoted_name);341 ret_val_used += path_element->len gth+ 1;342 free(path_element-> quoted_name);333 "/%s", path_element->buf); 334 ret_val_used += path_element->len + 1; 335 free(path_element->buf); 343 336 talloc_free(path_element); 344 337 } … … 471 464 REGFI_VK_REC* vk; 472 465 const REGFI_HBIN* hbin; 466 REGFI_BUFFER data; 473 467 uint32 i, off, data_offset, data_maxsize; 474 468 … … 488 482 if(vk->data_in_offset) 489 483 { 490 vk->data = regfi_parse_data(f, vk->type, vk->data_off, 491 vk->data_size, 4, 492 vk->data_in_offset, false); 484 data = regfi_parse_data(f, vk->type, vk->data_off, 485 vk->data_size, 4, 486 vk->data_in_offset, false); 487 vk->data = data.buf; 488 vk->data_size = data.len; 493 489 } 494 490 else if(range_list_has_range(unalloc_cells, off, vk->data_size)) … … 499 495 data_offset = vk->data_off+REGFI_REGF_SIZE; 500 496 data_maxsize = hbin->block_size + hbin->file_off - data_offset; 501 vk->data = regfi_parse_data(f, vk->type, data_offset, 502 vk->data_size, data_maxsize, 503 vk->data_in_offset, false); 497 data = regfi_parse_data(f, vk->type, data_offset, 498 vk->data_size, data_maxsize, 499 vk->data_in_offset, false); 500 vk->data = data.buf; 501 vk->data_size = data.len; 502 504 503 if(vk->data != NULL) 505 504 { … … 509 508 * wrong. Need a feedback mechanism to be more fuzzy with 510 509 * data cell lengths and the ranges removed. 510 * 511 * The introduction of REGFI_BUFFER in regfi_parse_data has 512 * fixed some of this. Should review again with respect to 513 * the other issues mentioned above though. 511 514 */ 512 515 /* A data record was recovered. Remove from unalloc_cells. */
Note: See TracChangeset
for help on using the changeset viewer.