Changeset 151 for trunk


Ignore:
Timestamp:
03/04/09 16:14:09 (15 years ago)
Author:
tim
Message:

parsed more items from regf header structure

improved feedback from regfi_parse_data

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/regfi.h

    r150 r151  
    9595#define REGFI_REGF_SIZE            0x1000 /* "regf" header block size */
    9696#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
    97102#define REGFI_HBIN_MAGIC_SIZE      4
    98103#define REGFI_CELL_MAGIC_SIZE      2
     
    337342  /********************************/
    338343  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
    339351  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
    361392} REGFI_FILE;
    362393
     
    367398 *      whole keys.
    368399 */
    369 typedef struct
     400typedef struct _regfi_iterator
    370401{
    371402  REGFI_FILE* f;
     
    377408
    378409
    379 typedef struct
     410typedef struct _regfi_iter_position
    380411{
    381412  REGFI_NK_REC* nk;
     
    385416   */
    386417} REGFI_ITER_POSITION;
     418
     419
     420typedef struct _regfi_buffer
     421{
     422  uint8* buf;
     423  uint32_t len;
     424} REGFI_BUFFER;
    387425
    388426
     
    478516                                     uint32 max_size, bool strict);
    479517
    480 uint8*                regfi_parse_data(REGFI_FILE* file,
     518REGFI_BUFFER          regfi_parse_data(REGFI_FILE* file,
    481519                                       uint32 data_type, uint32 offset,
    482520                                       uint32 length, uint32 max_size,
  • trunk/lib/regfi.c

    r150 r151  
    948948  const REGFI_HBIN* hbin;
    949949  uint32 data_offset, data_maxsize;
     950  REGFI_BUFFER data;
    950951
    951952  hbin = regfi_lookup_hbin(file, offset - REGFI_REGF_SIZE);
     
    965966    if(ret_val->data_in_offset)
    966967    {
    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;
    970973    }
    971974    else
     
    976979        data_offset = ret_val->data_off+REGFI_REGF_SIZE;
    977980        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
    981987      }
    982988      else
     
    992998    {
    993999      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.",
    9951001                        ret_val->offset);
    9961002    }
     
    17401746    regfi_add_message(ret_val, REGFI_MSG_WARN, "Magic number mismatch "
    17411747                      "(%.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],
    17431749                      ret_val->magic[2], ret_val->magic[3]);
    17441750  }
    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);
    17491753  ret_val->mtime.low = IVAL(file_header, 0xC);
    17501754  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);
    17581760  ret_val->last_block = IVAL(file_header, 0x28);
    17591761
    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);
    17611781
    17621782  return ret_val;
     
    22012221
    22022222
    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;
     2223REGFI_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;
    22092229  uint32 read_length, cell_length;
    22102230  uint8 i;
    22112231  bool unalloc;
    2212 
     2232 
    22132233  /* The data is typically stored in the offset if the size <= 4 */
    22142234  if(data_in_offset)
     
    22192239                        " while parsing data record at offset 0x%.8X.",
    22202240                        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;
    22262247
    22272248    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);
    22292250  }
    22302251  else
     
    22352256      regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while"
    22362257                        " parsing data record at offset 0x%.8X.", offset);
    2237       return NULL;
     2258      goto fail;
    22382259    }
    22392260
     
    22432264                        " while parsing data record at offset 0x%.8X.",
    22442265                        offset);
    2245       return NULL;
     2266      goto fail;
    22462267    }
    22472268
     
    22522273                        offset);
    22532274      if(strict)
    2254         return NULL;
     2275        goto fail;
    22552276      else
    22562277        cell_length = max_size;
     
    22612282      /* XXX: This strict condition has been triggered in multiple registries.
    22622283       *      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.
    22642286       */
    22652287      regfi_add_message(file, REGFI_MSG_WARN, "Data length (0x%.8X) larger than"
     
    22672289                        " while parsing data record at offset 0x%.8X.",
    22682290                        length, cell_length - 4, offset);
     2291      /*
    22692292      if(strict)
    2270         return NULL;
     2293        goto fail;
    22712294      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;
    22772302
    22782303    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)
    22802305       || read_length != length)
    22812306    {
    22822307      regfi_add_message(file, REGFI_MSG_ERROR, "Could not read data block while"
    22832308                        " 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;
    22892319  return ret_val;
    22902320}
  • trunk/src/reglookup-recover.c

    r150 r151  
    263263  uint32 virt_offset, i, stack_size, ret_val_size, ret_val_used;
    264264  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;
    273266 
    274267  /* The path_stack size limit should guarantee that we don't recurse forever. */
     
    298291          virt_offset = cur_ancestor->parent_off;
    299292       
    300         path_element = talloc(path_stack, struct name_holder);
     293        path_element = talloc(path_stack, REGFI_BUFFER);
    301294        if(path_element != NULL)
    302           path_element->quoted_name = quote_string(cur_ancestor->keyname,
     295          path_element->buf = (uint8*)quote_string(cur_ancestor->keyname,
    303296                                                   key_special_chars);
    304297         
    305         if(path_element == NULL || path_element->quoted_name == NULL
     298        if(path_element == NULL || path_element->buf == NULL
    306299           || !void_stack_push(path_stack, path_element))
    307300        {
     
    316309         * 16 bits and the max depth is 512.
    317310         */
    318         path_element->length = strlen(path_element->quoted_name);
    319         ret_val_size += path_element->length + 1;
     311        path_element->len = strlen((char*)path_element->buf);
     312        ret_val_size += path_element->len + 1;
    320313
    321314        regfi_free_key(cur_ancestor);
     
    338331    path_element = void_stack_pop(path_stack);
    339332    snprintf(ret_val+ret_val_used, ret_val_size-ret_val_used,
    340              "/%s", path_element->quoted_name);
    341     ret_val_used += path_element->length + 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);
    343336    talloc_free(path_element);
    344337  }
     
    471464  REGFI_VK_REC* vk;
    472465  const REGFI_HBIN* hbin;
     466  REGFI_BUFFER data;
    473467  uint32 i, off, data_offset, data_maxsize;
    474468
     
    488482      if(vk->data_in_offset)
    489483      {
    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;
    493489      }
    494490      else if(range_list_has_range(unalloc_cells, off, vk->data_size))
     
    499495          data_offset = vk->data_off+REGFI_REGF_SIZE;
    500496          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
    504503          if(vk->data != NULL)
    505504          {
     
    509508             *      wrong.  Need a feedback mechanism to be more fuzzy with
    510509             *      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.
    511514             */
    512515            /* A data record was recovered. Remove from unalloc_cells. */
Note: See TracChangeset for help on using the changeset viewer.