Changeset 159 for trunk/src


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

Location:
trunk/src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • 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.