- Timestamp:
- 12/06/09 15:09:01 (15 years ago)
- Location:
- trunk/src
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/common.c
r154 r159 160 160 int ret; 161 161 162 /* Set up conversion descriptor. */163 162 conv_desc = iconv_open("US-ASCII//TRANSLIT", "UTF-16LE"); 164 163 … … 229 228 * value, and a non-NULL (*error_msg). 230 229 */ 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; 230 static char* data_to_ascii(REGFI_DATA* data, char** error_msg) 231 { 232 char* ret_val; 241 233 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."); 256 244 return NULL; 257 245 } 258 246 *error_msg = NULL; 259 247 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) 261 259 { 262 260 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 263 269 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 265 278 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... 268 374 */ 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 else346 {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:381 375 *error_msg = (char*)malloc(65); 382 376 if(*error_msg == NULL) … … 384 378 sprintf(*error_msg, 385 379 "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 } 387 383 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 398 384 return NULL; 399 385 } -
trunk/src/reglookup-recover.c
r157 r159 111 111 char* conv_error = NULL; 112 112 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 133 114 quoted_name = quote_string(vk->valuename, key_special_chars); 134 115 if (quoted_name == NULL) … … 144 125 quoted_name[0] = '\0'; 145 126 } 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); 148 137 if(quoted_value == NULL) 149 138 { … … 469 458 return 10; 470 459 460 data.buf = NULL; 461 data.len = 0; 471 462 for(i=0; i<range_list_size(unalloc_values); i++) 472 463 { … … 571 562 } 572 563 } 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); 576 569 } 577 570 } -
trunk/src/reglookup.c
r158 r159 50 50 51 51 52 void printValue(const REGFI_VK_REC* vk, char* prefix) 53 { 52 void printValue(REGFI_ITERATOR* iter, const REGFI_VK_REC* vk, char* prefix) 53 { 54 REGFI_DATA* data; 54 55 char* quoted_value = NULL; 55 56 char* quoted_name = NULL; 56 57 char* conv_error = NULL; 57 58 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 73 60 quoted_name = quote_string(vk->valuename, key_special_chars); 74 61 if (quoted_name == NULL) … … 84 71 quoted_name[0] = '\0'; 85 72 } 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); 96 80 if(quoted_value == NULL) 97 81 { … … 103 87 "Returned error: %s\n", prefix, quoted_name, conv_error); 104 88 } 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', " 107 91 "warning returned: %s\n", prefix, quoted_name, conv_error); 92 regfi_free_data(data); 108 93 } 109 94 … … 281 266 { 282 267 if(!type_filter_enabled || (value->type == type_filter)) 283 printValue( value, prefix);268 printValue(iter, value, prefix); 284 269 regfi_free_value(value); 285 270 value = regfi_iterator_next_value(iter); … … 511 496 512 497 if(!type_filter_enabled || (value->type == type_filter)) 513 printValue( value, tmp_path_joined);498 printValue(iter, value, tmp_path_joined); 514 499 515 500 regfi_free_value(value); … … 632 617 regfi_set_message_mask(f, REGFI_MSG_INFO|REGFI_MSG_WARN|REGFI_MSG_ERROR); 633 618 634 iter = regfi_iterator_new(f); 619 /* XXX: add command line option to choose output encoding */ 620 iter = regfi_iterator_new(f, 0); 635 621 if(iter == NULL) 636 622 {
Note: See TracChangeset
for help on using the changeset viewer.