Changeset 159


Ignore:
Timestamp:
12/06/09 15:09:01 (15 years ago)
Author:
tim
Message:

began rearranging data parsing. Moved charater set conversion and basic parsing logic into regfi

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Makefile

    r147 r159  
    1111
    1212CC=gcc
    13 OPTS=-std=gnu89 -pedantic -Wall -ggdb
    14 #OPTS=-std=gnu89 -pedantic -Wall
     13OPTS=-std=gnu99 -pedantic -Wall -ggdb
     14#OPTS=-std=gnu99 -pedantic -Wall
    1515INC:=-I$(PWD)/include -I/usr/local/include
    1616LIB=-L/usr/local/lib -lm
  • trunk/include/regfi.h

    r158 r159  
    4545#include <unistd.h>
    4646#include <assert.h>
     47#include <iconv.h>
    4748
    4849#include "talloc.h"
     
    250251
    251252
     253typedef struct _regfi_data
     254{
     255  uint32 type;
     256
     257  /* Length of the raw data. */
     258  uint32 size;
     259
     260  /* This is always present, representing the raw data cell contents. */
     261  uint8* raw;
     262
     263  /* Represents the length of the interpreted value. Meaning is type-specific.*/
     264  uint32 interpreted_size;
     265
     266  /* These items represent interpreted versions of the raw attribute above.
     267   * Only use the appropriate member according to the type field. 
     268   * In the event of an unknown type, use only the raw field.
     269   */
     270  union _regfi_data_interpreted
     271  {
     272    uint8* none; /* */
     273    uint8* string;
     274    uint8* expand_string;
     275    uint8* binary; /* */
     276    uint32 dword;
     277    uint32 dword_be;
     278    uint8* link;
     279    uint8** multiple_string;
     280    uint64 qword;
     281
     282    /* The following are treated as binary currently, but this may change in
     283     * the future as the formats become better understood.
     284     */
     285    uint8* resource_list;
     286    uint8* full_resource_descriptor;
     287    uint8* resource_requirements_list;
     288  } interpreted;
     289} REGFI_DATA;
     290
     291
    252292/* Value record */
    253293typedef struct
     
    256296  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
    257297
    258   uint8* data;
     298  REGFI_DATA* data;     /* XXX: deprecated */
     299
    259300  char*  valuename;
    260301  uint16 name_length;
    261302  uint32 hbin_off;      /* offset from beginning of this hbin block */
    262303 
    263   uint32 data_size;
    264   uint32 data_off;      /* offset of data cell (virtual) */
     304  uint32 data_size;     /* As reported in the VK record.  May be different than
     305                         * That obtained while parsing the data cell itself. */
     306  uint32 data_off;      /* Offset of data cell (virtual) */
    265307  uint32 type;
    266308  uint8  magic[REGFI_CELL_MAGIC_SIZE];
     
    423465  void_stack* key_positions;
    424466  REGFI_NK_REC* cur_key;
     467  const char* string_encoding;
    425468  uint32 cur_subkey;
    426469  uint32 cur_value;
     
    446489
    447490
     491
    448492/******************************************************************************/
    449493/*                         Main iterator API                                  */
     
    462506 */
    463507char*                 regfi_get_messages(REGFI_FILE* file);
     508
    464509void                  regfi_set_message_mask(REGFI_FILE* file, uint16 mask);
    465510
    466 REGFI_ITERATOR*       regfi_iterator_new(REGFI_FILE* fh);
     511
     512/* regfi_iterator_new: Creates a new iterator for the provided registry file.
     513 *
     514 * Arguments:
     515 *   file            -- The opened registry file the iterator should be
     516 *                      created for.
     517 *   output_encoding -- An integer representing the output string encoding.
     518 *                      These integers currently map to a specific set of
     519 *                      iconv(3) encodings.
     520 *                      The following values are currently accepted:
     521 *                      0 - default (currently US-ASCII//TRANSLIT)
     522 *                      1 - US-ASCII//TRANSLIT
     523 *                      2 - UTF-8//TRANSLIT
     524 *
     525 *                      XXX: This encoding only applies to specific data
     526 *                           strings currently, but should apply to key
     527 *                           names and value names in the future.
     528 *
     529 * Returns:
     530 *   A newly allocated REGFI_ITERATOR. Must be free()d with regfi_iterator_free.
     531 */
     532REGFI_ITERATOR*       regfi_iterator_new(REGFI_FILE* file,
     533                                         uint32 output_encoding);
    467534void                  regfi_iterator_free(REGFI_ITERATOR* i);
    468535bool                  regfi_iterator_down(REGFI_ITERATOR* i);
     
    487554                                                const char* value_name);
    488555
    489 REGFI_DATA*           regfi_iterator_cur_data(REGFI_ITERATOR* i);
     556REGFI_DATA*           regfi_iterator_fetch_data(REGFI_ITERATOR* i,
     557                                                const REGFI_VK_REC* value);
    490558
    491559
     
    512580                                          range_list* used_ranges,
    513581                                          bool strict);
     582bool                  regfi_interpret_data(REGFI_FILE* file,
     583                                           const char* string_encoding,
     584                                           uint32 type, REGFI_DATA* data);
     585void                  regfi_free_data(REGFI_DATA* data);
    514586
    515587/* These are cached so return values don't need to be freed. */
     
    599671REGFI_VK_REC*         regfi_copy_vk(const REGFI_VK_REC* vk);
    600672int32                 regfi_calc_maxsize(REGFI_FILE* file, uint32 offset);
     673int32                 regfi_conv_charset(const char* output_charset,
     674                                         uint8* input, char* output,
     675                                         uint32 input_len, uint32 output_max);
     676REGFI_DATA*           regfi_buffer_to_data(REGFI_BUFFER raw_data);
    601677
    602678#endif  /* _REGFI_H */
  • trunk/lib/regfi.c

    r158 r159  
    958958{
    959959  REGFI_VK_REC* ret_val = NULL;
    960   REGFI_BUFFER data;
    961960  int32 max_size;
    962961
     
    969968    return NULL;
    970969
    971   if(ret_val->data_size == 0)
    972     ret_val->data = NULL;
    973   else
    974   {
    975     data = regfi_load_data(file, ret_val->data_off, ret_val->data_size,
    976                            ret_val->data_in_offset, strict);
    977     ret_val->data = data.buf;
    978     ret_val->data_size = data.len;
    979 
    980     if(ret_val->data == NULL)
    981     {
    982       regfi_add_message(file, REGFI_MSG_WARN, "Could not parse data record"
    983                         " while parsing VK record at offset 0x%.8X.",
    984                         ret_val->offset, ret_val->valuename);
    985     }
    986     else
    987       talloc_steal(ret_val, ret_val->data);
    988   }
     970  /* XXX: convert valuename to proper encoding if necessary */
    989971
    990972  return ret_val;
     
    11891171  while(cur_offset < hbin_end)
    11901172  {
    1191     fprintf(stderr, "DEBUG: trying cell offset 0x%.8X\n", cur_offset);
    11921173    if(!regfi_parse_cell(file->fd, cur_offset, NULL, 0, &cell_length, &unalloc))
    11931174    {
     
    13831364/******************************************************************************
    13841365 *****************************************************************************/
    1385 REGFI_ITERATOR* regfi_iterator_new(REGFI_FILE* fh)
     1366REGFI_ITERATOR* regfi_iterator_new(REGFI_FILE* file, uint32 output_encoding)
    13861367{
    13871368  REGFI_NK_REC* root;
     
    13901371    return NULL;
    13911372
    1392   root = regfi_rootkey(fh);
     1373  root = regfi_rootkey(file);
    13931374  if(root == NULL)
    13941375  {
     
    14051386  talloc_steal(ret_val, ret_val->key_positions);
    14061387
    1407   ret_val->f = fh;
     1388  ret_val->f = file;
    14081389  ret_val->cur_key = root;
    14091390  ret_val->cur_subkey = 0;
    14101391  ret_val->cur_value = 0;
    1411 
     1392 
     1393  switch (output_encoding)
     1394  {
     1395  case 0:
     1396  case 1:
     1397    ret_val->string_encoding = "US-ASCII//TRANSLIT";
     1398    break;
     1399  case 2:
     1400    ret_val->string_encoding = "UTF-8//TRANSLIT";
     1401    break;
     1402  default:
     1403    talloc_free(ret_val);
     1404    return NULL;
     1405  }
     1406 
    14121407  return ret_val;
    14131408}
     
    16881683
    16891684
     1685/******************************************************************************
     1686 *****************************************************************************/
     1687REGFI_DATA* regfi_iterator_fetch_data(REGFI_ITERATOR* i,
     1688                                      const REGFI_VK_REC* value)
     1689{
     1690  REGFI_DATA* ret_val = NULL;
     1691  REGFI_BUFFER raw_data;
     1692
     1693  if(value->data_size != 0)
     1694  {
     1695    raw_data = regfi_load_data(i->f, value->data_off, value->data_size,
     1696                              value->data_in_offset, true);
     1697    if(raw_data.buf == NULL)
     1698    {
     1699      regfi_add_message(i->f, REGFI_MSG_WARN, "Could not parse data record"
     1700                        " while parsing VK record at offset 0x%.8X.",
     1701                        value->offset);
     1702    }
     1703    else
     1704    {
     1705      ret_val = regfi_buffer_to_data(raw_data);
     1706
     1707      if(ret_val == NULL)
     1708      {
     1709        regfi_add_message(i->f, REGFI_MSG_WARN, "Error occurred in converting"
     1710                          " data buffer to data structure while interpreting "
     1711                          "data for VK record at offset 0x%.8X.",
     1712                          value->offset);
     1713        talloc_free(raw_data.buf);
     1714        return NULL;
     1715      }
     1716
     1717      if(!regfi_interpret_data(i->f, i->string_encoding, value->type, ret_val))
     1718      {
     1719        regfi_add_message(i->f, REGFI_MSG_INFO, "Error occurred while"
     1720                          " interpreting data for VK record at offset 0x%.8X.",
     1721                          value->offset);
     1722      }
     1723    }
     1724  }
     1725 
     1726  return ret_val;
     1727}
     1728
     1729
     1730/******************************************************************************
     1731 *****************************************************************************/
     1732void regfi_free_data(REGFI_DATA* data)
     1733{
     1734  talloc_free(data);
     1735}
     1736
     1737
     1738/******************************************************************************
     1739 *****************************************************************************/
     1740REGFI_DATA* regfi_buffer_to_data(REGFI_BUFFER raw_data)
     1741{
     1742  REGFI_DATA* ret_val;
     1743
     1744  if(raw_data.buf == NULL)
     1745    return NULL;
     1746
     1747  ret_val = talloc(NULL, REGFI_DATA);
     1748  if(ret_val == NULL)
     1749    return NULL;
     1750 
     1751  talloc_steal(ret_val, raw_data.buf);
     1752  ret_val->raw = raw_data.buf;
     1753  ret_val->size = raw_data.len;
     1754  ret_val->interpreted_size = 0;
     1755  ret_val->interpreted.qword = 0;
     1756
     1757  return ret_val;
     1758}
     1759
     1760
     1761/******************************************************************************
     1762 *****************************************************************************/
     1763bool regfi_interpret_data(REGFI_FILE* file, const char* string_encoding,
     1764                          uint32 type, REGFI_DATA* data)
     1765{
     1766  uint8** tmp_array;
     1767  uint8* tmp_str;
     1768  int32 tmp_size;
     1769  uint32 i, j, array_size;
     1770
     1771  if(data == NULL)
     1772    return false;
     1773
     1774  switch (type)
     1775  {
     1776  case REG_SZ:
     1777  case REG_EXPAND_SZ:
     1778  /* REG_LINK is a symbolic link, stored as a unicode string. */
     1779  case REG_LINK:
     1780    tmp_str = talloc_array(NULL, uint8, data->size);
     1781    if(tmp_str == NULL)
     1782    {
     1783      data->interpreted.string = NULL;
     1784      data->interpreted_size = 0;
     1785      return false;
     1786    }
     1787     
     1788    tmp_size = regfi_conv_charset(string_encoding,
     1789                                  data->raw, (char*)tmp_str,
     1790                                  data->size, data->size);
     1791    if(tmp_size < 0)
     1792    {
     1793      regfi_add_message(file, REGFI_MSG_INFO, "Error occurred while"
     1794                        " converting data of type %d to %s.  Error message: %s",
     1795                        type, string_encoding, strerror(-tmp_size));
     1796      talloc_free(tmp_str);
     1797      data->interpreted.string = NULL;
     1798      data->interpreted_size = 0;
     1799      return false;
     1800    }
     1801
     1802    tmp_str = talloc_realloc(NULL, tmp_str, uint8, tmp_size);
     1803    data->interpreted.string = tmp_str;
     1804    data->interpreted_size = tmp_size;
     1805    talloc_steal(data, tmp_str);
     1806    break;
     1807
     1808  case REG_DWORD:
     1809    if(data->size < 4)
     1810    {
     1811      data->interpreted.dword = 0;
     1812      data->interpreted_size = 0;
     1813      return false;
     1814    }
     1815    data->interpreted.dword = IVAL(data->raw, 0);
     1816    data->interpreted_size = 4;
     1817    break;
     1818
     1819  case REG_DWORD_BE:
     1820    if(data->size < 4)
     1821    {
     1822      data->interpreted.dword_be = 0;
     1823      data->interpreted_size = 0;
     1824      return false;
     1825    }
     1826    data->interpreted.dword_be = RIVAL(data->raw, 0);
     1827    data->interpreted_size = 4;
     1828    break;
     1829
     1830  case REG_QWORD:
     1831    if(data->size < 8)
     1832    {
     1833      data->interpreted.qword = 0;
     1834      data->interpreted_size = 0;
     1835      return false;
     1836    }
     1837    data->interpreted.qword =
     1838      (uint64)IVAL(data->raw, 0) + (((uint64)IVAL(data->raw, 4))<<32);
     1839    data->interpreted_size = 8;
     1840    break;
     1841   
     1842  case REG_MULTI_SZ:
     1843    tmp_str = talloc_array(NULL, uint8, data->size);
     1844    if(tmp_str == NULL)
     1845    {
     1846      data->interpreted.multiple_string = NULL;
     1847      data->interpreted_size = 0;
     1848      return false;
     1849    }
     1850
     1851    /* Attempt to convert entire string from UTF-16LE to output encoding,
     1852     * then parse and quote fields individually.
     1853     */
     1854    tmp_size = regfi_conv_charset(string_encoding,
     1855                                  data->raw, (char*)tmp_str,
     1856                                  data->size, data->size);
     1857    if(tmp_size < 0)
     1858    {
     1859      regfi_add_message(file, REGFI_MSG_INFO, "Error occurred while"
     1860                        " converting data of type %d to %s.  Error message: %s",
     1861                        type, string_encoding, strerror(-tmp_size));
     1862      talloc_free(tmp_str);
     1863      data->interpreted.multiple_string = NULL;
     1864      data->interpreted_size = 0;
     1865      return false;
     1866    }
     1867
     1868    array_size = tmp_size+1;
     1869    tmp_array = talloc_array(NULL, uint8*, array_size);
     1870    if(tmp_array == NULL)
     1871    {
     1872      talloc_free(tmp_str);
     1873      data->interpreted.string = NULL;
     1874      data->interpreted_size = 0;
     1875      return false;
     1876    }
     1877   
     1878    tmp_array[0] = tmp_str;
     1879    for(i=0,j=1; i < tmp_size && j < array_size-1; i++)
     1880    {
     1881      if(tmp_str[i] == '\0' && (i+1 < tmp_size))
     1882        tmp_array[j++] = tmp_str+i+1;
     1883    }
     1884    tmp_array[j] = NULL;
     1885    tmp_array = talloc_realloc(NULL, tmp_array, uint8*, j+1);
     1886    data->interpreted.multiple_string = tmp_array;
     1887    /* XXX: how meaningful is this?  should we store number of strings instead? */
     1888    data->interpreted_size = tmp_size;
     1889    talloc_steal(tmp_array, tmp_str);
     1890    talloc_steal(data, tmp_array);
     1891    break;
     1892
     1893  /* XXX: Dont know how to interpret these yet, just treat as binary */
     1894  case REG_NONE:
     1895    data->interpreted.none = data->raw;
     1896    data->interpreted_size = data->size;
     1897    break;
     1898
     1899  case REG_RESOURCE_LIST:
     1900    data->interpreted.resource_list = data->raw;
     1901    data->interpreted_size = data->size;
     1902    break;
     1903
     1904  case REG_FULL_RESOURCE_DESCRIPTOR:
     1905    data->interpreted.full_resource_descriptor = data->raw;
     1906    data->interpreted_size = data->size;
     1907    break;
     1908
     1909  case REG_RESOURCE_REQUIREMENTS_LIST:
     1910    data->interpreted.resource_requirements_list = data->raw;
     1911    data->interpreted_size = data->size;
     1912    break;
     1913
     1914  case REG_BINARY:
     1915    data->interpreted.binary = data->raw;
     1916    data->interpreted_size = data->size;
     1917    break;
     1918
     1919  default:
     1920    data->interpreted.qword = 0;
     1921    data->interpreted_size = 0;
     1922    return false;
     1923  }
     1924
     1925  data->type = type;
     1926  return true;
     1927}
     1928
     1929
     1930
     1931/*******************************************************************
     1932 * Convert from UTF-16LE to specified character set.
     1933 * On error, returns a negative errno code.
     1934 *******************************************************************/
     1935int32 regfi_conv_charset(const char* output_charset,
     1936                         uint8* input, char* output,
     1937                         uint32 input_len, uint32 output_max)
     1938{
     1939  iconv_t conv_desc;
     1940  char* inbuf = (char*)input;
     1941  char* outbuf = output;
     1942  size_t in_len = (size_t)input_len;
     1943  size_t out_len = (size_t)(output_max-1);
     1944  int ret;
     1945
     1946  /* Set up conversion descriptor. */
     1947  conv_desc = iconv_open(output_charset, "UTF-16LE");
     1948
     1949  ret = iconv(conv_desc, &inbuf, &in_len, &outbuf, &out_len);
     1950  if(ret == -1)
     1951  {
     1952    iconv_close(conv_desc);
     1953    return -errno;
     1954  }
     1955  *outbuf = '\0';
     1956
     1957  iconv_close(conv_desc); 
     1958  return output_max-out_len-1;
     1959}
     1960
     1961
     1962
    16901963/*******************************************************************
    16911964 * Computes the checksum of the registry file header.
    1692  * buffer must be at least the size of an regf header (4096 bytes).
     1965 * buffer must be at least the size of a regf header (4096 bytes).
    16931966 *******************************************************************/
    16941967static uint32 regfi_compute_header_checksum(uint8* buffer)
     
    21872460 *
    21882461 ******************************************************************************/
    2189 REGFI_BUFFER regfi_load_data(REGFI_FILE* file, uint32 voffset, 
     2462REGFI_BUFFER regfi_load_data(REGFI_FILE* file, uint32 voffset,
    21902463                             uint32 length, bool data_in_offset,
    21912464                             bool strict)
     
    21962469  bool unalloc;
    21972470 
     2471  /* Microsoft's documentation indicates that "available memory" is
     2472   * the limit on value sizes.  Annoying.  We limit it to 1M which
     2473   * should rarely be exceeded, unless the file is corrupt or
     2474   * malicious. For more info, see:
     2475   *   http://msdn2.microsoft.com/en-us/library/ms724872.aspx
     2476   */
     2477  /*
     2478XXX
     2479  if(size > REGFI_VK_MAX_DATA_LENGTH)
     2480  {
     2481    *error_msg = (char*)malloc(82);
     2482    if(*error_msg == NULL)
     2483      return NULL;
     2484   
     2485    sprintf(*error_msg, "WARN: value data size %d larger than "
     2486            "%d, truncating...", size, REGFI_VK_MAX_DATA_LENGTH);
     2487    size = REGFI_VK_MAX_DATA_LENGTH;
     2488  }
     2489
     2490  */
     2491
    21982492  if(data_in_offset)
    21992493    return regfi_parse_little_data(file, voffset, length, strict);
     
    22892583  }
    22902584
    2291   if((ret_val.buf = talloc_array(NULL, uint8_t, length)) == NULL)
     2585  if((ret_val.buf = talloc_array(NULL, uint8, length)) == NULL)
    22922586    return ret_val;
    22932587  ret_val.len = length;
     
    23292623  }
    23302624
    2331   if((ret_val.buf = talloc_array(NULL, uint8_t, length)) == NULL)
     2625  if((ret_val.buf = talloc_array(NULL, uint8, length)) == NULL)
    23322626    return ret_val;
    23332627  ret_val.len = length;
  • trunk/src/common.c

    r154 r159  
    160160  int ret;
    161161
    162   /* Set up conversion descriptor. */
    163162  conv_desc = iconv_open("US-ASCII//TRANSLIT", "UTF-16LE");
    164163
     
    229228 * value, and a non-NULL (*error_msg).
    230229 */
    231 /* XXX: Part of this function's logic should be pushed into the regfi API.
    232  *      The structures should be parsed and stored with VK records and only
    233  *      escaped/encoded later in reglookup and reglookup-recover.
    234  */
    235 static char* data_to_ascii(unsigned char* datap, uint32 len, uint32 type,
    236                            char** error_msg)
    237 {
    238   char* asciip;
    239   char* ascii;
    240   char* ascii_tmp;
     230static char* data_to_ascii(REGFI_DATA* data, char** error_msg)
     231{
     232  char* ret_val;
    241233  char* cur_quoted;
    242   char* tmp_err = NULL;
    243   const char* delim;
    244   uint32 i;
    245   uint32 cur_str_len;
    246   uint32 ascii_max;
    247   uint32 str_rem, alen;
    248   int ret_err;
    249 
    250   if(datap == NULL)
    251   {
    252     *error_msg = (char*)malloc(24);
    253     if(*error_msg == NULL)
    254       return NULL;
    255     strcpy(*error_msg, "Data pointer was NULL.");
     234  char* tmp_ptr;
     235  char* delim;
     236  uint32 ret_val_left, i, tmp_len;
     237
     238  if(data == NULL || data->size == 0)
     239  {
     240    *error_msg = (char*)malloc(37);
     241    if(*error_msg == NULL)
     242      return NULL;
     243    strcpy(*error_msg, "Data pointer was NULL or size was 0.");
    256244    return NULL;
    257245  }
    258246  *error_msg = NULL;
    259247
    260   switch (type)
     248
     249  if(data->interpreted_size == 0)
     250  {
     251    *error_msg = (char*)malloc(51);
     252    if(*error_msg == NULL)
     253      return NULL;
     254    strcpy(*error_msg, "Data could not be interpreted, quoting raw buffer.");
     255    return quote_buffer(data->raw, data->size, common_special_chars);
     256  }
     257
     258  switch (data->type)
    261259  {
    262260  case REG_SZ:
     261    ret_val = quote_string((char*)data->interpreted.string, common_special_chars);
     262    if(ret_val == NULL && (*error_msg = (char*)malloc(49)) != NULL)
     263        strcpy(*error_msg, "Buffer could not be quoted due to unknown error.");
     264
     265    return ret_val;
     266    break;
     267
     268   
    263269  case REG_EXPAND_SZ:
    264     /* REG_LINK is a symbolic link, stored as a unicode string. */
     270    ret_val = quote_string((char*)data->interpreted.expand_string,
     271                           common_special_chars);
     272    if(ret_val == NULL && (*error_msg = (char*)malloc(49)) != NULL)
     273        strcpy(*error_msg, "Buffer could not be quoted due to unknown error.");
     274
     275    return ret_val;
     276    break;
     277
    265278  case REG_LINK:
    266     /* Sometimes values have binary stored in them.  If the unicode
    267      * conversion fails, just quote it raw.
     279    ret_val = quote_string((char*)data->interpreted.link, common_special_chars);
     280    if(ret_val == NULL && (*error_msg = (char*)malloc(49)) != NULL)
     281        strcpy(*error_msg, "Buffer could not be quoted due to unknown error.");
     282
     283    return ret_val;
     284    break;
     285
     286  case REG_DWORD:
     287    ret_val = malloc(sizeof(char)*(8+2+1));
     288    if(ret_val == NULL)
     289      return NULL;
     290
     291    sprintf(ret_val, "0x%.8X", data->interpreted.dword);
     292    return ret_val;
     293    break;
     294
     295  case REG_DWORD_BE:
     296    ret_val = malloc(sizeof(char)*(8+2+1));
     297    if(ret_val == NULL)
     298      return NULL;
     299
     300    sprintf(ret_val, "0x%.8X", data->interpreted.dword_be);
     301    return ret_val;
     302    break;
     303
     304  case REG_QWORD:
     305    ret_val = malloc(sizeof(char)*(16+2+1));
     306    if(ret_val == NULL)
     307      return NULL;
     308
     309    sprintf(ret_val, "0x%.16llX",
     310            (long long unsigned int)data->interpreted.qword);
     311    return ret_val;
     312    break;
     313
     314  case REG_MULTI_SZ:
     315    ret_val_left = data->interpreted_size*4+1;
     316    ret_val = malloc(ret_val_left);
     317    if(ret_val == NULL)
     318      return NULL;
     319
     320    tmp_ptr = ret_val;
     321    tmp_ptr[0] = '\0';
     322    delim = "";
     323    for(i=0; data->interpreted.multiple_string[i] != NULL; i++)
     324    {
     325      cur_quoted = quote_string((char*)data->interpreted.multiple_string[i],
     326                                subfield_special_chars);
     327      if(cur_quoted != NULL && cur_quoted[0] != '\0')
     328      {
     329        tmp_len = snprintf(tmp_ptr, ret_val_left, "%s%s",delim, cur_quoted);
     330        tmp_ptr += tmp_len;
     331        ret_val_left -= tmp_len;
     332        free(cur_quoted);
     333      }
     334      delim = "|";
     335    }
     336
     337    return ret_val;
     338    break;
     339
     340   
     341  case REG_NONE:
     342    return quote_buffer(data->interpreted.none, data->interpreted_size,
     343                        common_special_chars);
     344
     345    break;
     346
     347  case REG_RESOURCE_LIST:
     348    return quote_buffer(data->interpreted.resource_list, data->interpreted_size,
     349                        common_special_chars);
     350
     351    break;
     352
     353  case REG_FULL_RESOURCE_DESCRIPTOR:
     354    return quote_buffer(data->interpreted.full_resource_descriptor,
     355                        data->interpreted_size, common_special_chars);
     356
     357    break;
     358
     359  case REG_RESOURCE_REQUIREMENTS_LIST:
     360    return quote_buffer(data->interpreted.resource_requirements_list,
     361                        data->interpreted_size, common_special_chars);
     362
     363    break;
     364
     365  case REG_BINARY:
     366    return quote_buffer(data->interpreted.binary, data->interpreted_size,
     367                        common_special_chars);
     368
     369    break;
     370
     371  default:
     372    /* This shouldn't happen, since the regfi routines won't interpret
     373     * unknown types, but just as a safety measure against library changes...
    268374     */
    269     cur_quoted = quote_unicode(datap, len, common_special_chars, &tmp_err);
    270     if(cur_quoted == NULL)
    271     {
    272       if(tmp_err == NULL && (*error_msg = (char*)malloc(49)) != NULL)
    273         strcpy(*error_msg, "Buffer could not be quoted due to unknown error.");
    274       else if((*error_msg = (char*)malloc(42+strlen(tmp_err))) != NULL)
    275       {
    276         sprintf(*error_msg, "Buffer could not be quoted due to error: %s",
    277                 tmp_err);
    278         free(tmp_err);
    279       }
    280     }
    281     else if (tmp_err != NULL)
    282       *error_msg = tmp_err;
    283     return cur_quoted;
    284     break;
    285 
    286   case REG_DWORD:
    287     ascii_max = sizeof(char)*(8+2+1);
    288     ascii = malloc(ascii_max);
    289     if(ascii == NULL)
    290       return NULL;
    291 
    292     snprintf(ascii, ascii_max, "0x%.2X%.2X%.2X%.2X",
    293              datap[3], datap[2], datap[1], datap[0]);
    294     return ascii;
    295     break;
    296 
    297   case REG_DWORD_BE:
    298     ascii_max = sizeof(char)*(8+2+1);
    299     ascii = malloc(ascii_max);
    300     if(ascii == NULL)
    301       return NULL;
    302 
    303     snprintf(ascii, ascii_max, "0x%.2X%.2X%.2X%.2X",
    304              datap[0], datap[1], datap[2], datap[3]);
    305     return ascii;
    306     break;
    307 
    308   case REG_QWORD:
    309     ascii_max = sizeof(char)*(16+2+1);
    310     ascii = malloc(ascii_max);
    311     if(ascii == NULL)
    312       return NULL;
    313 
    314     snprintf(ascii, ascii_max, "0x%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X",
    315              datap[7], datap[6], datap[5], datap[4],
    316              datap[3], datap[2], datap[1], datap[0]);
    317     return ascii;
    318     break;
    319    
    320   case REG_MULTI_SZ:
    321     ascii_max = sizeof(char)*(len*4+1);
    322     ascii_tmp = malloc(ascii_max);
    323     if(ascii_tmp == NULL)
    324       return NULL;
    325 
    326     /* Attempt to convert entire string from UTF-16LE to ASCII,
    327      * then parse and quote fields individually.
    328      * If this fails, simply quote entire buffer as binary.
    329      */
    330     ret_err = uni_to_ascii(datap, ascii_tmp, len, ascii_max);
    331     if(ret_err < 0)
    332     {
    333       tmp_err = strerror(-ret_err);
    334       *error_msg = (char*)malloc(61+strlen(tmp_err));
    335       if(*error_msg == NULL)
    336       {
    337         free(ascii_tmp);
    338         return NULL;
    339       }
    340 
    341       sprintf(*error_msg, "MULTI_SZ unicode conversion"
    342               " failed with '%s'. Quoting as binary.", tmp_err);
    343       ascii = quote_buffer(datap, len, subfield_special_chars);
    344     }
    345     else
    346     {
    347       ascii = malloc(ascii_max);
    348       if(ascii == NULL)
    349       {
    350         free(ascii_tmp);
    351         return NULL;
    352       }
    353       asciip = ascii;
    354       asciip[0] = '\0';
    355       str_rem = ascii_max;
    356       delim = "";
    357       for(i=0; i<ret_err; i+=cur_str_len+1)
    358       {
    359         cur_str_len = strlen(ascii_tmp+i);
    360         if(ascii_tmp[i] != '\0')
    361         {
    362           cur_quoted = quote_string(ascii_tmp+i, subfield_special_chars);
    363           if(cur_quoted != NULL)
    364           {
    365             alen = snprintf(asciip, str_rem, "%s%s", delim, cur_quoted);
    366             asciip += alen;
    367             str_rem -= alen;
    368             free(cur_quoted);
    369           }
    370         }
    371         delim = "|";
    372       }
    373     }
    374 
    375     free(ascii_tmp);
    376     return ascii;
    377     break;
    378 
    379   /* XXX: Dont know what to do with these yet, just print as binary... */
    380   default:
    381375    *error_msg = (char*)malloc(65);
    382376    if(*error_msg == NULL)
     
    384378    sprintf(*error_msg,
    385379            "Unrecognized registry data type (0x%.8X); quoting as binary.",
    386             type);
     380            data->type);
     381    return quote_buffer(data->raw, data->size, common_special_chars);
     382  }
    387383   
    388   case REG_NONE:
    389   case REG_RESOURCE_LIST:
    390   case REG_FULL_RESOURCE_DESCRIPTOR:
    391   case REG_RESOURCE_REQUIREMENTS_LIST:
    392 
    393   case REG_BINARY:
    394     return quote_buffer(datap, len, common_special_chars);
    395     break;
    396   }
    397 
    398384  return NULL;
    399385}
  • trunk/src/reglookup-recover.c

    r157 r159  
    111111  char* conv_error = NULL;
    112112  const char* str_type = NULL;
    113   uint32 size = vk->data_size;
    114 
    115   /* Microsoft's documentation indicates that "available memory" is
    116    * the limit on value sizes.  Annoying.  We limit it to 1M which
    117    * should rarely be exceeded, unless the file is corrupt or
    118    * malicious. For more info, see:
    119    *   http://msdn2.microsoft.com/en-us/library/ms724872.aspx
    120    */
    121   /* XXX: Should probably do something different here for this tool.
    122    *      Also, It would be really nice if this message somehow included the
    123    *      name of the current value we're having trouble with, since
    124    *      stderr/stdout don't always sync nicely.
    125    */
    126   if(size > REGFI_VK_MAX_DATA_LENGTH)
    127   {
    128     fprintf(stderr, "WARN: value data size %d larger than "
    129             "%d, truncating...\n", size, REGFI_VK_MAX_DATA_LENGTH);
    130     size = REGFI_VK_MAX_DATA_LENGTH;
    131   }
    132  
     113
    133114  quoted_name = quote_string(vk->valuename, key_special_chars);
    134115  if (quoted_name == NULL)
     
    144125    quoted_name[0] = '\0';
    145126  }
    146 
    147   quoted_value = data_to_ascii(vk->data, size, vk->type, &conv_error);
     127  /* XXX: Add command line option to choose output encoding */
     128  if(vk->data != NULL
     129     && !regfi_interpret_data(f, "US-ASCII//TRANSLIT", vk->type, vk->data))
     130  {
     131    fprintf(stderr, "WARN: Error occurred while interpreting data for VK record"
     132            " at offset 0x%.8X.\n", vk->offset);
     133  }
     134  printMsgs(f);
     135
     136  quoted_value = data_to_ascii(vk->data, &conv_error);
    148137  if(quoted_value == NULL)
    149138  {
     
    469458    return 10;
    470459
     460  data.buf = NULL;
     461  data.len = 0;
    471462  for(i=0; i<range_list_size(unalloc_values); i++)
    472463  {
     
    571562          }
    572563        }
    573 
    574         vk->data = data.buf;
    575         vk->data_size = data.len;
     564        /* XXX: Need to come up with a different way to link these so the
     565         *      vk->data item can be removed from the structure.
     566         */
     567        vk->data = regfi_buffer_to_data(data);
     568        talloc_steal(vk, vk->data);
    576569      }
    577570    }
  • trunk/src/reglookup.c

    r158 r159  
    5050
    5151
    52 void printValue(const REGFI_VK_REC* vk, char* prefix)
    53 {
     52void printValue(REGFI_ITERATOR* iter, const REGFI_VK_REC* vk, char* prefix)
     53{
     54  REGFI_DATA* data;
    5455  char* quoted_value = NULL;
    5556  char* quoted_name = NULL;
    5657  char* conv_error = NULL;
    5758  const char* str_type = NULL;
    58   uint32 size = vk->data_size;
    59 
    60   /* Microsoft's documentation indicates that "available memory" is
    61    * the limit on value sizes.  Annoying.  We limit it to 1M which
    62    * should rarely be exceeded, unless the file is corrupt or
    63    * malicious. For more info, see:
    64    *   http://msdn2.microsoft.com/en-us/library/ms724872.aspx
    65    */
    66   if(size > REGFI_VK_MAX_DATA_LENGTH)
    67   {
    68     fprintf(stderr, "WARN: value data size %d larger than "
    69             "%d, truncating...\n", size, REGFI_VK_MAX_DATA_LENGTH);
    70     size = REGFI_VK_MAX_DATA_LENGTH;
    71   }
    72  
     59
    7360  quoted_name = quote_string(vk->valuename, key_special_chars);
    7461  if (quoted_name == NULL)
     
    8471    quoted_name[0] = '\0';
    8572  }
    86 
    87   if(vk->data == NULL)
    88   {
    89     if(print_verbose)
    90       fprintf(stderr, "INFO: While quoting value for '%s/%s', "
    91               "data pointer was NULL.\n", prefix, quoted_name);
    92   }
    93   else
    94   {
    95     quoted_value = data_to_ascii(vk->data, size, vk->type, &conv_error);
     73 
     74  data = regfi_iterator_fetch_data(iter, vk);
     75
     76  printMsgs(iter->f);
     77  if(data != NULL)
     78  {
     79    quoted_value = data_to_ascii(data, &conv_error);
    9680    if(quoted_value == NULL)
    9781    {
     
    10387                "Returned error: %s\n", prefix, quoted_name, conv_error);
    10488    }
    105     else if(conv_error != NULL && print_verbose)
    106       fprintf(stderr, "INFO: While quoting value for '%s/%s', "
     89    else if(conv_error != NULL)
     90      fprintf(stderr, "WARN: While quoting value for '%s/%s', "
    10791              "warning returned: %s\n", prefix, quoted_name, conv_error);
     92    regfi_free_data(data);
    10893  }
    10994
     
    281266  {
    282267    if(!type_filter_enabled || (value->type == type_filter))
    283       printValue(value, prefix);
     268      printValue(iter, value, prefix);
    284269    regfi_free_value(value);
    285270    value = regfi_iterator_next_value(iter);
     
    511496
    512497    if(!type_filter_enabled || (value->type == type_filter))
    513       printValue(value, tmp_path_joined);
     498      printValue(iter, value, tmp_path_joined);
    514499
    515500    regfi_free_value(value);
     
    632617    regfi_set_message_mask(f, REGFI_MSG_INFO|REGFI_MSG_WARN|REGFI_MSG_ERROR);
    633618
    634   iter = regfi_iterator_new(f);
     619  /* XXX: add command line option to choose output encoding */
     620  iter = regfi_iterator_new(f, 0);
    635621  if(iter == NULL)
    636622  {
Note: See TracChangeset for help on using the changeset viewer.