Changeset 152
- Timestamp:
- 06/02/09 16:00:38 (16 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/regfi.h
r151 r152 96 96 #define REGFI_REGF_MAGIC_SIZE 4 97 97 #define REGFI_REGF_NAME_SIZE 64 98 99 98 #define REGFI_REGF_RESERVED1_SIZE 340 100 99 #define REGFI_REGF_RESERVED2_SIZE 3528 101 102 100 #define REGFI_HBIN_MAGIC_SIZE 4 103 101 #define REGFI_CELL_MAGIC_SIZE 2 … … 127 125 128 126 /* Flags for the vk records */ 127 /* XXX: This next flag may be incorrect. According to Jeffrey Muir, 128 * this may actually indicate that the value name is stored in 129 * UTF-16LE. 130 */ 129 131 #define REGFI_VK_FLAG_NAME_PRESENT 0x0001 130 132 #define REGFI_VK_DATA_IN_OFFSET 0x80000000 131 #define REGFI_VK_MAX_DATA_LENGTH 1024*1024 132 133 134 /* NK record types */ 135 /* XXX: This is starting to look like this is a flags field. 136 * Need to decipher the meaning of each flag. 137 */ 138 #define REGFI_NK_TYPE_LINKKEY 0x0010 139 #define REGFI_NK_TYPE_NORMALKEY 0x0020 140 /* XXX: Unknown key type that shows up in Vista registries */ 141 #define REGFI_NK_TYPE_UNKNOWN1 0x1020 142 /* XXX: Unknown key types that shows up in W2K3 registries */ 143 #define REGFI_NK_TYPE_UNKNOWN2 0x4020 144 #define REGFI_NK_TYPE_UNKNOWN3 0x0000 /* XXX: This type seems to have UTF-16 names!!! */ 145 #define REGFI_NK_TYPE_ROOTKEY1 0x002c 146 /* XXX: Unknown root key type that shows up in Vista registries */ 147 #define REGFI_NK_TYPE_ROOTKEY2 0x00ac 148 149 #if 0 150 /* Initial hypothesis of NK flags: */ 151 /***********************************/ 152 #define REGFI_NK_FLAG_LINK 0x0010 153 /* The name will be in ASCII if this next bit is set, otherwise UTF-16LE */ 154 #define REGFI_NK_FLAG_ASCIINAME 0x0020 155 /* These next two combine to form the "c" on both known root key types */ 156 #define REGFI_NK_FLAG_ROOT1 0x0008 157 #define REGFI_NK_FLAG_ROOT2 0x0004 133 #define REGFI_VK_MAX_DATA_LENGTH 1024*1024 /* XXX: This is arbitrary */ 134 135 136 /* Known key flags */ 137 /*******************/ 158 138 /* These next two show up on normal-seeming keys in Vista and W2K3 registries */ 159 139 #define REGFI_NK_FLAG_UNKNOWN1 0x4000 160 140 #define REGFI_NK_FLAG_UNKNOWN2 0x1000 141 161 142 /* This next one shows up on root keys in some Vista "software" registries */ 162 143 #define REGFI_NK_FLAG_UNKNOWN3 0x0080 163 #endif 164 144 145 /* Predefined handle. Rumor has it that the valuelist count for this key is 146 * where the handle is stored. 147 * http://msdn.microsoft.com/en-us/library/ms724836(VS.85).aspx 148 */ 149 #define REGFI_NK_FLAG_PREDEF_KEY 0x0040 150 151 /* The name will be in ASCII if this next bit is set, otherwise UTF-16LE */ 152 #define REGFI_NK_FLAG_ASCIINAME 0x0020 153 154 /* Symlink key. 155 * See: http://www.codeproject.com/KB/system/regsymlink.aspx 156 */ 157 #define REGFI_NK_FLAG_LINK 0x0010 158 159 /* This key cannot be deleted */ 160 #define REGFI_NK_FLAG_NO_RM 0x0008 161 162 /* Root of a hive */ 163 #define REGFI_NK_FLAG_ROOT 0x0004 164 165 /* Mount point of another hive. NULL/(default) value indicates which hive 166 * and where in the hive it points to. 167 */ 168 #define REGFI_NK_FLAG_HIVE_LINK 0x0002 169 170 /* These keys shouldn't be stored on disk, according to: 171 * http://geekswithblogs.net/sdorman/archive/2007/12/24/volatile-registry-keys.aspx 172 */ 173 #define REGFI_NK_FLAG_VOLATILE 0x0001 174 175 /* Useful for identifying unknown flag types */ 176 #define REGFI_NK_KNOWN_FLAGS (REGFI_NK_FLAG_PREDEF_KEY\ 177 | REGFI_NK_FLAG_ASCIINAME\ 178 | REGFI_NK_FLAG_LINK\ 179 | REGFI_NK_FLAG_NO_RM\ 180 | REGFI_NK_FLAG_ROOT\ 181 | REGFI_NK_FLAG_HIVE_LINK\ 182 | REGFI_NK_FLAG_VOLATILE\ 183 | REGFI_NK_FLAG_UNKNOWN1\ 184 | REGFI_NK_FLAG_UNKNOWN2) 165 185 166 186 /* HBIN block */ … … 350 370 351 371 NTTIME mtime; 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 */372 uint32 major_version; /* Set to 1 in all known hives */ 373 uint32 minor_version; /* Set to 3 or 5 in all known hives */ 354 374 uint32 type; /* XXX: Unverified. Set to 0 in all known hives */ 355 375 uint32 format; /* XXX: Unverified. Set to 1 in all known hives */ 356 376 357 377 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?) */ 378 uint32 last_block; /* Offset to last hbin block in file */ 360 379 361 380 uint32 cluster; /* XXX: Unverified. Set to 1 in all known hives */ … … 516 535 uint32 max_size, bool strict); 517 536 518 REGFI_BUFFER regfi_parse_data(REGFI_FILE* file, 519 uint32 data_type, uint32 offset, 520 uint32 length, uint32 max_size, 521 bool data_in_offset, bool strict); 537 REGFI_BUFFER regfi_load_data(REGFI_FILE* file, 538 uint32 data_type, uint32 offset, 539 uint32 length, uint32 max_size, 540 bool data_in_offset, bool strict); 541 542 REGFI_BUFFER regfi_load_big_data(REGFI_FILE* file, 543 uint32 offset, uint32 data_length, 544 uint32 cell_length, bool strict); 522 545 523 546 REGFI_SK_REC* regfi_parse_sk(REGFI_FILE* file, uint32 offset, -
trunk/lib/regfi.c
r151 r152 966 966 if(ret_val->data_in_offset) 967 967 { 968 data = regfi_ parse_data(file, ret_val->type, ret_val->data_off,968 data = regfi_load_data(file, ret_val->type, ret_val->data_off, 969 969 ret_val->data_size, 4, 970 970 ret_val->data_in_offset, strict); … … 979 979 data_offset = ret_val->data_off+REGFI_REGF_SIZE; 980 980 data_maxsize = hbin->block_size + hbin->file_off - data_offset; 981 data = regfi_ parse_data(file, ret_val->type, data_offset,981 data = regfi_load_data(file, ret_val->type, data_offset, 982 982 ret_val->data_size, data_maxsize, 983 983 ret_val->data_in_offset, strict); … … 999 999 regfi_add_message(file, REGFI_MSG_WARN, "Could not parse data record" 1000 1000 " while parsing VK record at offset 0x%.8X.", 1001 ret_val->offset );1001 ret_val->offset, ret_val->valuename); 1002 1002 } 1003 1003 else … … 1204 1204 if(nk != NULL) 1205 1205 { 1206 if((nk->key_type == REGFI_NK_TYPE_ROOTKEY1) 1207 || (nk->key_type == REGFI_NK_TYPE_ROOTKEY2)) 1206 if(nk->key_type & REGFI_NK_FLAG_ROOT) 1208 1207 { 1209 1208 found = true; … … 1777 1776 ret_val->thaw_rm_id = winsec_parse_uuid(ret_val, file_header+0xFD8, 16); 1778 1777 ret_val->thaw_log_id = winsec_parse_uuid(ret_val, file_header+0xFE8, 16); 1779 ret_val->boot_type = IVAL(file_header, 0x 90);1780 ret_val->boot_recover = IVAL(file_header, 0x 90);1778 ret_val->boot_type = IVAL(file_header, 0xFF8); 1779 ret_val->boot_recover = IVAL(file_header, 0xFFC); 1781 1780 1782 1781 return ret_val; … … 1918 1917 ret_val->magic[1] = nk_header[0x1]; 1919 1918 ret_val->key_type = SVAL(nk_header, 0x2); 1920 if((ret_val->key_type != REGFI_NK_TYPE_NORMALKEY) 1921 && (ret_val->key_type != REGFI_NK_TYPE_ROOTKEY1) 1922 && (ret_val->key_type != REGFI_NK_TYPE_ROOTKEY2) 1923 && (ret_val->key_type != REGFI_NK_TYPE_LINKKEY) 1924 && (ret_val->key_type != REGFI_NK_TYPE_UNKNOWN1) 1925 && (ret_val->key_type != REGFI_NK_TYPE_UNKNOWN2) 1926 && (ret_val->key_type != REGFI_NK_TYPE_UNKNOWN3)) 1927 { 1928 regfi_add_message(file, REGFI_MSG_WARN, "Unknown key type (0x%.4X) while" 1919 1920 if((ret_val->key_type & ~REGFI_NK_KNOWN_FLAGS) != 0) 1921 { 1922 regfi_add_message(file, REGFI_MSG_WARN, "Unknown key flags (0x%.4X) while" 1929 1923 " parsing NK record at offset 0x%.8X.", 1930 ret_val->key_type, offset);1924 (ret_val->key_type & ~REGFI_NK_KNOWN_FLAGS), offset); 1931 1925 } 1932 1926 … … 1964 1958 ret_val->classname_length = SVAL(nk_header, 0x4A); 1965 1959 1966 1967 1960 if(ret_val->name_length + REGFI_NK_MIN_LENGTH > ret_val->cell_size) 1968 1961 { … … 2106 2099 2107 2100 2108 /******************************************************************* 2109 2101 /****************************************************************************** 2102 *******************************************************************************/ 2110 2103 REGFI_VK_REC* regfi_parse_vk(REGFI_FILE* file, uint32 offset, 2111 2104 uint32 max_size, bool strict) … … 2221 2214 2222 2215 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) 2216 /****************************************************************************** 2217 *******************************************************************************/ 2218 REGFI_BUFFER regfi_load_data(REGFI_FILE* file, 2219 uint32 data_type, uint32 offset, 2220 uint32 length, uint32 max_size, 2221 bool data_in_offset, bool strict) 2227 2222 { 2228 2223 REGFI_BUFFER ret_val; … … 2280 2275 if(cell_length - 4 < length) 2281 2276 { 2282 /* XXX: This strict condition has been triggered in multiple registries. 2283 * Not sure the cause, but the data length values are very large, 2284 * such as 53392. For now, we're truncating the size and returning 2285 * what we can, since this issue is so common. 2286 */ 2287 regfi_add_message(file, REGFI_MSG_WARN, "Data length (0x%.8X) larger than" 2288 " remaining cell length (0x%.8X)" 2289 " while parsing data record at offset 0x%.8X.", 2290 length, cell_length - 4, offset); 2291 /* 2292 if(strict) 2293 goto fail; 2277 if (file->major_version >= 1 && file->minor_version >= 5) 2278 { 2279 /* Attempt to parse a big data record */ 2280 return regfi_load_big_data(file, offset, length, cell_length, strict); 2281 } 2294 2282 else 2295 */ 2296 length = cell_length - 4; 2283 { 2284 regfi_add_message(file, REGFI_MSG_WARN, "Data length (0x%.8X) larger than" 2285 " remaining cell length (0x%.8X)" 2286 " while parsing data record at offset 0x%.8X.", 2287 length, cell_length - 4, offset); 2288 if(strict) 2289 goto fail; 2290 else 2291 length = cell_length - 4; 2292 } 2297 2293 } 2298 2294 … … 2314 2310 return ret_val; 2315 2311 2312 fail: 2313 ret_val.buf = NULL; 2314 ret_val.len = 0; 2315 return ret_val; 2316 } 2317 2318 2319 /****************************************************************************** 2320 *******************************************************************************/ 2321 REGFI_BUFFER regfi_load_big_data(REGFI_FILE* file, 2322 uint32 offset, uint32 data_length, 2323 uint32 cell_length, bool strict) 2324 { 2325 REGFI_BUFFER ret_val; 2326 uint16 num_chunks, i; 2327 uint32 indirect_offset, indirect_length, chunk_length, chunk_offset; 2328 uint32 read_length, data_left; 2329 bool unalloc; 2330 uint32* indirect_ptrs; 2331 uint8* big_data_cell = (uint8*)malloc(cell_length*sizeof(uint8)); 2332 if(big_data_cell == NULL) 2333 goto fail; 2334 2335 if(!regfi_parse_cell(file->fd, offset, big_data_cell, cell_length-4, 2336 &cell_length, &unalloc)) 2337 { 2338 regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while" 2339 " parsing big data record at offset 0x%.8X.", offset); 2340 free(big_data_cell); 2341 goto fail; 2342 } 2343 2344 if((big_data_cell[0] != 'd') || (big_data_cell[1] != 'b')) 2345 { 2346 regfi_add_message(file, REGFI_MSG_WARN, "Unknown magic number" 2347 " (0x%.2X, 0x%.2X) encountered while parsing" 2348 " big data record at offset 0x%.8X.", 2349 big_data_cell[0], big_data_cell[1], offset); 2350 free(big_data_cell); 2351 goto fail; 2352 } 2353 num_chunks = SVAL(big_data_cell, 0x2); 2354 /* XXX: Should check sanity of pointers here and in the indirect 2355 * block. At least ensure they are a multiple of 8. 2356 */ 2357 indirect_offset = IVAL(big_data_cell, 0x4) + REGFI_REGF_SIZE; 2358 free(big_data_cell); 2359 2360 indirect_ptrs = (uint32*)malloc(num_chunks*sizeof(uint32)); 2361 if(indirect_ptrs == NULL) 2362 goto fail; 2363 2364 if(!regfi_parse_cell(file->fd, indirect_offset, (uint8*)indirect_ptrs, 2365 num_chunks*sizeof(uint32), 2366 &indirect_length, &unalloc)) 2367 { 2368 regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while" 2369 " parsing big data indirect record at offset 0x%.8X.", 2370 offset); 2371 free(indirect_ptrs); 2372 goto fail; 2373 } 2374 2375 if((ret_val.buf = talloc_array(NULL, uint8_t, data_length)) == NULL) 2376 { 2377 free(indirect_ptrs); 2378 goto fail; 2379 } 2380 data_left = data_length; 2381 2382 for(i=0; (i<num_chunks) && (data_left>0); i++) 2383 { 2384 /* Fix endianness of pointer and convert to physical offset */ 2385 chunk_offset = IVAL(indirect_ptrs, i*4) + REGFI_REGF_SIZE; 2386 if(!regfi_parse_cell(file->fd, chunk_offset, NULL, 0, 2387 &chunk_length, &unalloc)) 2388 { 2389 regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while" 2390 " parsing big data chunk at offset 0x%.8X.", 2391 chunk_offset); 2392 if(strict) 2393 goto chunk_fail; 2394 else 2395 break; 2396 } 2397 2398 if(chunk_length-4 > data_left) 2399 read_length = data_left; 2400 else 2401 read_length = chunk_length-4; 2402 2403 if(regfi_read(file->fd, ret_val.buf+(data_length-data_left), 2404 &read_length) != 0) 2405 { 2406 regfi_add_message(file, REGFI_MSG_WARN, "Could not read data chunk while" 2407 " constructing big data at offset 0x%.8X.", 2408 chunk_offset); 2409 if(strict) 2410 goto chunk_fail; 2411 else 2412 break; 2413 } 2414 2415 data_left -= read_length; 2416 } 2417 2418 free(indirect_ptrs); 2419 ret_val.len = data_length-data_left; 2420 return ret_val; 2421 2422 chunk_fail: 2423 free(indirect_ptrs); 2424 talloc_free(ret_val.buf); 2316 2425 fail: 2317 2426 ret_val.buf = NULL; -
trunk/src/reglookup-recover.c
r151 r152 285 285 else 286 286 { 287 if((cur_ancestor->key_type == REGFI_NK_TYPE_ROOTKEY1) 288 || (cur_ancestor->key_type == REGFI_NK_TYPE_ROOTKEY2)) 287 if(cur_ancestor->key_type & REGFI_NK_FLAG_ROOT) 289 288 virt_offset = REGFI_OFFSET_NONE; 290 289 else … … 482 481 if(vk->data_in_offset) 483 482 { 484 data = regfi_ parse_data(f, vk->type, vk->data_off,485 486 483 data = regfi_load_data(f, vk->type, vk->data_off, 484 vk->data_size, 4, 485 vk->data_in_offset, false); 487 486 vk->data = data.buf; 488 487 vk->data_size = data.len; … … 495 494 data_offset = vk->data_off+REGFI_REGF_SIZE; 496 495 data_maxsize = hbin->block_size + hbin->file_off - data_offset; 497 data = regfi_ parse_data(f, vk->type, data_offset,498 499 496 data = regfi_load_data(f, vk->type, data_offset, 497 vk->data_size, data_maxsize, 498 vk->data_in_offset, false); 500 499 vk->data = data.buf; 501 500 vk->data_size = data.len; … … 503 502 if(vk->data != NULL) 504 503 { 504 /* XXX: The following may not make sense now in light of big data 505 * records. 506 */ 505 507 /* XXX: This strict checking prevents partial recovery of data 506 * cells. Also, see code for regfi_ parse_data and note that508 * cells. Also, see code for regfi_load_data and note that 507 509 * lengths indicated in VK records are sometimes just plain 508 510 * wrong. Need a feedback mechanism to be more fuzzy with 509 511 * data cell lengths and the ranges removed. 510 512 * 511 * The introduction of REGFI_BUFFER in regfi_ parse_data has513 * The introduction of REGFI_BUFFER in regfi_load_data has 512 514 * fixed some of this. Should review again with respect to 513 515 * the other issues mentioned above though.
Note: See TracChangeset
for help on using the changeset viewer.