Changeset 116
- Timestamp:
- 08/03/08 15:34:27 (16 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/regfi.h
r112 r116 72 72 #define REG_KEY 0x7FFFFFFF 73 73 74 #define REGF_BLOCKSIZE 0x100075 #define REGF_ALLOC_BLOCK 0x1000 /* Minimum allocation unit for hbins */76 #define REGF_MAX_DEPTH 51274 #define REGF_BLOCKSIZE 0x1000 75 #define REGF_ALLOC_BLOCK 0x1000 /* Minimum allocation unit for HBINs */ 76 #define REGF_MAX_DEPTH 512 77 77 78 78 /* header sizes for various records */ 79 80 #define REGF_MAGIC_SIZE 4 81 #define HBIN_MAGIC_SIZE 4 82 #define HBIN_HEADER_REC_SIZE 0x20 83 #define REC_HDR_SIZE 2 84 85 #define REGF_OFFSET_NONE 0xffffffff 86 #define REGFI_NK_MIN_LENGTH 0x4C 87 #define REGFI_VK_MIN_LENGTH 0x14 88 #define REGFI_SK_MIN_LENGTH 0x14 89 #define REGFI_HASH_LIST_MIN_LENGTH 0x4 79 #define REGF_MAGIC_SIZE 4 80 #define HBIN_MAGIC_SIZE 4 81 #define HBIN_HEADER_REC_SIZE 0x20 82 #define REC_HDR_SIZE 2 83 84 #define REGF_OFFSET_NONE 0xffffffff 85 #define REGFI_NK_MIN_LENGTH 0x4C 86 #define REGFI_VK_MIN_LENGTH 0x14 87 #define REGFI_SK_MIN_LENGTH 0x14 88 #define REGFI_HASH_LIST_MIN_LENGTH 0x4 89 90 /* Constants used for validation */ 91 /* Minimum time is Jan 1, 1990 00:00:00 */ 92 #define REGFI_MTIME_MIN_HIGH 0x01B41E6D 93 #define REGFI_MTIME_MIN_LOW 0x26F98000 94 /* Maximum time is Jan 1, 2290 00:00:00 95 * (We hope no one is using Windows by then...) 96 */ 97 #define REGFI_MTIME_MAX_HIGH 0x03047543 98 #define REGFI_MTIME_MAX_LOW 0xC80A4000 99 90 100 91 101 /* Flags for the vk records */ 92 93 #define VK_FLAG_NAME_PRESENT 0x0001 94 #define VK_DATA_IN_OFFSET 0x80000000 95 #define VK_MAX_DATA_LENGTH 1024*1024 96 97 /* NK record macros */ 98 99 #define NK_TYPE_LINKKEY 0x0010 100 #define NK_TYPE_NORMALKEY 0x0020 101 #define NK_TYPE_ROOTKEY 0x002c 102 /* TODO: Unknown type that shows up in Vista registries */ 103 #define NK_TYPE_UNKNOWN1 0x1020 104 105 #define HBIN_STORE_REF(x, y) { x->hbin = y; y->ref_count++ }; 106 /* if the count == 0; we can clean up */ 107 #define HBIN_REMOVE_REF(x, y){ x->hbin = NULL; y->ref_count-- }; 102 #define VK_FLAG_NAME_PRESENT 0x0001 103 #define VK_DATA_IN_OFFSET 0x80000000 104 #define VK_MAX_DATA_LENGTH 1024*1024 105 106 /* NK record types */ 107 #define NK_TYPE_LINKKEY 0x0010 108 #define NK_TYPE_NORMALKEY 0x0020 109 #define NK_TYPE_ROOTKEY 0x002c 110 /* TODO: Unknown type that shows up in Vista registries */ 111 #define NK_TYPE_UNKNOWN1 0x1020 108 112 109 113 -
trunk/lib/range_list.c
r113 r116 18 18 */ 19 19 20 #include <stdio.h>21 20 #include <math.h> 22 21 #include "../include/range_list.h" … … 29 28 30 29 #if 0 30 #include <stdio.h> 31 31 static void range_list_print(const range_list* rl) 32 32 { -
trunk/lib/regfi.c
r113 r116 442 442 443 443 /******************************************************************* 444 TODO: not currently validating against max_size445 444 *******************************************************************/ 446 445 REGF_HASH_LIST* regfi_load_hashlist(REGF_FILE* file, uint32 offset, … … 463 462 464 463 ret_val->offset = offset; 464 if(cell_length > max_size) 465 { 466 if(strict) 467 return NULL; 468 cell_length = max_size & 0xFFFFFFF8; 469 } 465 470 ret_val->cell_size = cell_length; 466 471 … … 491 496 return NULL; 492 497 } 493 /* TODO: Not sure which should be authoritative, the number from the494 * 495 * 496 * 498 /* XXX: Not sure which should be authoritative, the number from the 499 * NK record, or the number in the hash list. Go with the larger 500 * of the two to ensure all keys are found. Note the length checks 501 * on the cell later ensure that there won't be any critical errors. 497 502 */ 498 503 if(num_keys < ret_val->num_keys) … … 565 570 566 571 ret_val->offset = offset; 567 /* TODO: is there a way to be more conservative (shorter) with568 * 572 /* XXX: Is there a way to be more conservative (shorter) with 573 * cell length when cell is unallocated? 569 574 */ 570 575 ret_val->cell_size = cell_length; … … 582 587 ret_val->magic[1] = sk_header[1]; 583 588 584 /* TODO: can additional validation be added here? */589 /* XXX: Can additional validation be added here? */ 585 590 ret_val->unknown_tag = SVAL(sk_header, 0x2); 586 591 ret_val->prev_sk_off = IVAL(sk_header, 0x4); … … 595 600 } 596 601 597 /* TODO: need to get rid of this, but currently the security descriptor602 /* XXX: need to get rid of this, but currently the security descriptor 598 603 * code depends on the ps structure. 599 604 */ … … 678 683 679 684 /****************************************************************************** 680 * If !strict, the list may contain NULLs and VK records may point to NULL data.685 * If !strict, the list may contain NULLs, VK records may point to NULL. 681 686 ******************************************************************************/ 682 687 REGF_VK_REC** regfi_load_valuelist(REGF_FILE* file, uint32 offset, … … 686 691 REGF_VK_REC** ret_val; 687 692 REGF_HBIN* hbin; 688 uint32 i, vk_offset, vk_max_length ;693 uint32 i, vk_offset, vk_max_length, usable_num_values; 689 694 uint32* voffsets; 690 695 691 696 if((num_values+1) * sizeof(uint32) > max_size) 692 return NULL; 693 694 /* TODO: For now, everything strict seems to make sense on this call. 695 * Maybe remove the parameter or use it for other things. 696 */ 697 voffsets = regfi_parse_valuelist(file, offset, num_values, true); 697 { 698 if(strict) 699 return NULL; 700 usable_num_values = max_size/sizeof(uint32) - sizeof(uint32); 701 } 702 else 703 usable_num_values = num_values; 704 705 voffsets = regfi_parse_valuelist(file, offset, usable_num_values, strict); 698 706 if(voffsets == NULL) 699 707 return NULL; … … 706 714 } 707 715 708 for(i=0; i < num_values; i++)716 for(i=0; i < usable_num_values; i++) 709 717 { 710 718 hbin = regfi_lookup_hbin(file, voffsets[i]); … … 739 747 740 748 /******************************************************************* 741 * TODO: Need to add full key caching using a742 * 749 * XXX: Need to add full key caching using a 750 * custom cache structure. 743 751 *******************************************************************/ 744 752 REGF_NK_REC* regfi_load_key(REGF_FILE* file, uint32 offset, bool strict) … … 800 808 if(strict) 801 809 { 802 free(nk); 803 /* TODO: need convenient way to free nk->values deeply in all cases. */ 810 regfi_key_free(nk); 804 811 return NULL; 805 812 } … … 815 822 if(nk->subkeys == NULL) 816 823 { 817 /* TODO: temporary hack to get around 'ri' records */824 /* XXX: Temporary hack to get around 'ri' records */ 818 825 nk->num_subkeys = 0; 819 826 } … … 1031 1038 } 1032 1039 1033 /* TODO: come up with a better secret. */ 1034 ret_val->sk_recs = lru_cache_create(127, 0xDEADBEEF, true); 1040 /* This secret isn't very secret, but we don't need a good one. This 1041 * secret is just designed to prevent someone from trying to blow our 1042 * caching and make things slow. 1043 */ 1044 ret_val->sk_recs = lru_cache_create(127, 0x15DEAD05^time(NULL) 1045 ^(getpid()<<16)^(getppid()<<8), 1046 true); 1035 1047 1036 1048 ret_val->f = fh; … … 1367 1379 1368 1380 /******************************************************************* 1369 * TODO: add way to return more detailed error information.1381 * XXX: Add way to return more detailed error information. 1370 1382 *******************************************************************/ 1371 1383 REGF_FILE* regfi_parse_regf(int fd, bool strict) … … 1441 1453 * along with it's associated cells. 1442 1454 *******************************************************************/ 1443 /* TODO: Need a way to return types of errors. Also need to free 1444 * the hbin/ps when an error occurs. 1455 /* XXX: Need a way to return types of errors. 1445 1456 */ 1446 1457 REGF_HBIN* regfi_parse_hbin(REGF_FILE* file, uint32 offset, bool strict) … … 1485 1496 * the end of the file. 1486 1497 */ 1487 /* TODO: This may need to be relaxed for dealing with 1488 * partial or corrupt files. */ 1498 /* XXX: This may need to be relaxed for dealing with 1499 * partial or corrupt files. 1500 */ 1489 1501 if((offset + hbin->block_size > file->file_length) 1490 1502 || (hbin->block_size & 0xFFFFF000) != hbin->block_size) … … 1515 1527 if((nk_header[0x0] != 'n') || (nk_header[0x1] != 'k')) 1516 1528 { 1517 /* TODO: deal with subkey-lists that reference other subkey-lists. */ 1529 /* XXX: Deal with subkey-lists that reference other subkey-lists 1530 * (e.g. 'ri' records). 1531 */ 1518 1532 return NULL; 1519 1533 } … … 1549 1563 ret_val->mtime.low = IVAL(nk_header, 0x4); 1550 1564 ret_val->mtime.high = IVAL(nk_header, 0x8); 1551 1565 /* If the key is unallocated and the MTIME is earlier than Jan 1, 1990 1566 * or later than Jan 1, 2290, we consider this a bad key. This helps 1567 * weed out some false positives during deleted data recovery. 1568 */ 1569 if(unalloc 1570 && ((ret_val->mtime.high < REGFI_MTIME_MIN_HIGH 1571 && ret_val->mtime.low < REGFI_MTIME_MIN_LOW) 1572 || (ret_val->mtime.high > REGFI_MTIME_MAX_HIGH 1573 && ret_val->mtime.low > REGFI_MTIME_MAX_LOW))) 1574 return NULL; 1575 1552 1576 ret_val->unknown1 = IVAL(nk_header, 0xC); 1553 1577 ret_val->parent_off = IVAL(nk_header, 0x10); … … 1559 1583 ret_val->values_off = IVAL(nk_header, 0x28); 1560 1584 ret_val->sk_off = IVAL(nk_header, 0x2C); 1561 /* TODO: currently we do nothing with class names. Need to investigate. */1585 /* XXX: currently we do nothing with class names. Need to investigate. */ 1562 1586 ret_val->classname_off = IVAL(nk_header, 0x30); 1563 1587 … … 1758 1782 if(cell_length - 4 < length) 1759 1783 { 1760 /* TODO: This strict condition has been triggered in multiple registries.1761 * 1762 * 1784 /* XXX: This strict condition has been triggered in multiple registries. 1785 * Not sure the cause, but the data length values are very large, 1786 * such as 53392. 1763 1787 */ 1764 1788 if(strict) … … 1768 1792 } 1769 1793 1770 /* TODO: There is currently no check to ensure the data1771 * 1794 /* XXX: There is currently no check to ensure the data 1795 * cell doesn't cross HBIN boundary. 1772 1796 */ 1773 1797 … … 1816 1840 1817 1841 if((cell_len == 0) || ((cell_len & 0xFFFFFFF8) != cell_len)) 1818 /* TODO: should report an error here. */1842 /* XXX: should report an error here. */ 1819 1843 break; 1820 1844 -
trunk/src/common.c
r111 r116 29 29 const char* common_special_chars = ",\"\\"; 30 30 31 #define REGLOOKUP_VERSION " 1.0.0"31 #define REGLOOKUP_VERSION "0.9.0" 32 32 33 33 … … 357 357 /* XXX: Dont know what to do with these yet, just print as binary... */ 358 358 default: 359 /* XXX: It would be really nice if this message somehow included the 360 * name of the current value we're having trouble with, since 361 * stderr/stdout don't always sync nicely. 362 */ 359 363 fprintf(stderr, "WARNING: Unrecognized registry data type (0x%.8X); quoting as binary.\n", type); 360 364 -
trunk/src/reglookup-recover.c
r115 r116 148 148 * http://msdn2.microsoft.com/en-us/library/ms724872.aspx 149 149 */ 150 /* TODO: should probably do something different here for this tool.*/ 150 /* XXX: Should probably do something different here for this tool. 151 * Also, It would be really nice if this message somehow included the 152 * name of the current value we're having trouble with, since 153 * stderr/stdout don't always sync nicely. 154 */ 151 155 if(size > VK_MAX_DATA_LENGTH) 152 156 { … … 277 281 * Paths returned must be free()d. 278 282 */ 279 /* TODO: This is not terribly efficient, as it may reparse many keys280 * 281 * 283 /* XXX: This is not terribly efficient, as it may reparse many keys 284 * repeatedly. Should try to add caching. Also, piecing the path 285 * together is slow and redundant. 282 286 */ 283 287 char* getParentPath(REGF_FILE* f, REGF_NK_REC* nk) … … 425 429 rm_idx = range_list_find(rl, offset); 426 430 if(rm_idx < 0) 431 { 432 fprintf(stderr, "DEBUG: removeRange: rm_idx < 0; (%d)\n", rm_idx); 427 433 return false; 434 } 428 435 429 436 cur_elem = range_list_get(rl, rm_idx); 430 437 if(cur_elem == NULL) 431 438 { 432 printf("removeRange: cur_elem == NULL. rm_idx=%d\n", rm_idx);439 fprintf(stderr, "DEBUG: removeRange: cur_elem == NULL. rm_idx=%d\n", rm_idx); 433 440 return false; 434 441 } … … 438 445 if(!range_list_split_element(rl, rm_idx, offset)) 439 446 { 440 printf("removeRange: first split failed\n");447 fprintf(stderr, "DEBUG: removeRange: first split failed\n"); 441 448 return false; 442 449 } 443 450 rm_idx++; 451 cur_elem = range_list_get(rl, rm_idx); 452 if(cur_elem == NULL) 453 { 454 fprintf(stderr, 455 "DEBUG: removeRange: cur_elem == NULL after first split. rm_idx=%d\n", 456 rm_idx); 457 return false; 458 } 444 459 } 445 460 … … 448 463 if(!range_list_split_element(rl, rm_idx, offset+length)) 449 464 { 450 printf("removeRange: second split failed\n");465 fprintf(stderr, "DEBUG: removeRange: second split failed\n"); 451 466 return false; 452 467 } … … 455 470 if(!range_list_remove(rl, rm_idx)) 456 471 { 457 printf("removeRange: remove failed\n");472 fprintf(stderr, "DEBUG: removeRange: remove failed\n"); 458 473 return false; 459 474 } … … 487 502 return 20; 488 503 } 489 490 if(removeRange(unalloc_cells, key->offset, key->cell_size)) 491 { 492 /* TODO: This ugly hack is needed because unalloc_cells is changing 493 * underneath us when we find things. Need a better approach 494 * so we can parse things single-pass. 495 */ 496 i=0; 497 break; 498 } 499 else 500 return 30; 504 j+=key->cell_size-8; 501 505 } 502 506 } 507 } 508 509 for(i=0; i<range_list_size(unalloc_keys); i++) 510 { 511 cur_elem = range_list_get(unalloc_keys, i); 512 if(!removeRange(unalloc_cells, cur_elem->offset, cur_elem->length)) 513 return 30; 503 514 } 504 515 … … 743 754 REGF_NK_REC* tmp_key; 744 755 REGF_VK_REC* tmp_value; 745 uint32 argi, arge, i, j, k,ret, num_unalloc_keys;756 uint32 argi, arge, i, j, ret, num_unalloc_keys; 746 757 /* uint32 test_offset;*/ 747 758 -
trunk/src/reglookup.c
r111 r116 46 46 47 47 48 /* TODO: ahack to share some functions with reglookup-recover.c.49 * 48 /* XXX: A hack to share some functions with reglookup-recover.c. 49 * Should move these into a properly library at some point. 50 50 */ 51 51 #include "common.c"
Note: See TracChangeset
for help on using the changeset viewer.