Changeset 159 for trunk/lib


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

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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;
Note: See TracChangeset for help on using the changeset viewer.