int yr_arena_write_data( YR_ARENA* arena, void* data, size_t size, void** written_data) { void* output; int result; if (size > free_space(arena->current_page)) { result = yr_arena_allocate_memory(arena, size, &output); if (result != ERROR_SUCCESS) return result; } else { output = arena->current_page->address + arena->current_page->used; arena->current_page->used += size; } memcpy(output, data, size); if (written_data != NULL) *written_data = output; return ERROR_SUCCESS; }
int yr_arena_allocate_struct( YR_ARENA* arena, size_t size, void** allocated_memory, ...) { int result; va_list offsets; va_start(offsets, allocated_memory); result = yr_arena_allocate_memory(arena, size, allocated_memory); if (result == ERROR_SUCCESS) result = _yr_arena_make_relocatable(arena, *allocated_memory, offsets); va_end(offsets); memset(*allocated_memory, 0, size); return result; }
int _yr_scan_match_callback( uint8_t* match_data, int32_t match_length, int flags, void* args) { CALLBACK_ARGS* callback_args = (CALLBACK_ARGS*) args; YR_STRING* string = callback_args->string; YR_MATCH* new_match; int result = ERROR_SUCCESS; int tidx = callback_args->context->tidx; size_t match_offset = match_data - callback_args->data; // total match length is the sum of backward and forward matches. match_length += callback_args->forward_matches; if (callback_args->full_word) { if (flags & RE_FLAGS_WIDE) { if (match_offset >= 2 && *(match_data - 1) == 0 && isalnum(*(match_data - 2))) return ERROR_SUCCESS; if (match_offset + match_length + 1 < callback_args->data_size && *(match_data + match_length + 1) == 0 && isalnum(*(match_data + match_length))) return ERROR_SUCCESS; } else { if (match_offset >= 1 && isalnum(*(match_data - 1))) return ERROR_SUCCESS; if (match_offset + match_length < callback_args->data_size && isalnum(*(match_data + match_length))) return ERROR_SUCCESS; } } if (STRING_IS_CHAIN_PART(string)) { result = _yr_scan_verify_chained_string_match( string, callback_args->context, match_data, callback_args->data_base, match_offset, match_length); } else { if (string->matches[tidx].count == 0) { // If this is the first match for the string, put the string in the // list of strings whose flags needs to be cleared after the scan. FAIL_ON_ERROR(yr_arena_write_data( callback_args->context->matching_strings_arena, &string, sizeof(string), NULL)); } result = yr_arena_allocate_memory( callback_args->context->matches_arena, sizeof(YR_MATCH), (void**) &new_match); if (result == ERROR_SUCCESS) { new_match->base = callback_args->data_base; new_match->offset = match_offset; new_match->length = match_length; new_match->data = match_data; new_match->prev = NULL; new_match->next = NULL; FAIL_ON_ERROR(_yr_scan_add_match_to_list( new_match, &string->matches[tidx], STRING_IS_GREEDY_REGEXP(string))); } } return result; }
int _yr_scan_verify_chained_string_match( YR_STRING* matching_string, YR_SCAN_CONTEXT* context, uint8_t* match_data, uint64_t match_base, uint64_t match_offset, int32_t match_length) { YR_STRING* string; YR_MATCH* match; YR_MATCH* next_match; YR_MATCH* new_match; uint64_t lower_offset; uint64_t ending_offset; int32_t full_chain_length; int tidx = context->tidx; int add_match = FALSE; if (matching_string->chained_to == NULL) { add_match = TRUE; } else { if (matching_string->unconfirmed_matches[tidx].head != NULL) lower_offset = matching_string->unconfirmed_matches[tidx].head->offset; else lower_offset = match_offset; match = matching_string->chained_to->unconfirmed_matches[tidx].head; while (match != NULL) { next_match = match->next; ending_offset = match->offset + match->length; if (ending_offset + matching_string->chain_gap_max < lower_offset) { _yr_scan_remove_match_from_list( match, &matching_string->chained_to->unconfirmed_matches[tidx]); } else { if (ending_offset + matching_string->chain_gap_max >= match_offset && ending_offset + matching_string->chain_gap_min <= match_offset) { add_match = TRUE; break; } } match = next_match; } } if (add_match) { if (STRING_IS_CHAIN_TAIL(matching_string)) { match = matching_string->chained_to->unconfirmed_matches[tidx].head; while (match != NULL) { ending_offset = match->offset + match->length; if (ending_offset + matching_string->chain_gap_max >= match_offset && ending_offset + matching_string->chain_gap_min <= match_offset) { _yr_scan_update_match_chain_length( tidx, matching_string->chained_to, match, 1); } match = match->next; } full_chain_length = 0; string = matching_string; while(string->chained_to != NULL) { full_chain_length++; string = string->chained_to; } // "string" points now to the head of the strings chain match = string->unconfirmed_matches[tidx].head; while (match != NULL) { next_match = match->next; if (match->chain_length == full_chain_length) { _yr_scan_remove_match_from_list( match, &string->unconfirmed_matches[tidx]); match->length = (int32_t) \ (match_offset - match->offset + match_length); match->data = match_data - match_offset + match->offset; match->prev = NULL; match->next = NULL; FAIL_ON_ERROR(_yr_scan_add_match_to_list( match, &string->matches[tidx], FALSE)); } match = next_match; } } else { if (matching_string->matches[tidx].count == 0 && matching_string->unconfirmed_matches[tidx].count == 0) { // If this is the first match for the string, put the string in the // list of strings whose flags needs to be cleared after the scan. FAIL_ON_ERROR(yr_arena_write_data( context->matching_strings_arena, &matching_string, sizeof(matching_string), NULL)); } FAIL_ON_ERROR(yr_arena_allocate_memory( context->matches_arena, sizeof(YR_MATCH), (void**) &new_match)); new_match->base = match_base; new_match->offset = match_offset; new_match->length = match_length; new_match->data = match_data; new_match->chain_length = 0; new_match->prev = NULL; new_match->next = NULL; FAIL_ON_ERROR(_yr_scan_add_match_to_list( new_match, &matching_string->unconfirmed_matches[tidx], FALSE)); } } return ERROR_SUCCESS; }
int _yr_scan_match_callback( uint8_t* match_data, int32_t match_length, int flags, void* args) { CALLBACK_ARGS* callback_args = args; YR_STRING* string = callback_args->string; YR_MATCH* new_match; int result = ERROR_SUCCESS; int tidx = callback_args->tidx; size_t match_offset = match_data - callback_args->data; // total match length is the sum of backward and forward matches. match_length += callback_args->forward_matches; if (callback_args->full_word) { if (flags & RE_FLAGS_WIDE) { if (match_offset >= 2 && *(match_data - 1) == 0 && isalnum(*(match_data - 2))) return ERROR_SUCCESS; if (match_offset + match_length + 1 < callback_args->data_size && *(match_data + match_length + 1) == 0 && isalnum(*(match_data + match_length))) return ERROR_SUCCESS; } else { if (match_offset >= 1 && isalnum(*(match_data - 1))) return ERROR_SUCCESS; if (match_offset + match_length < callback_args->data_size && isalnum(*(match_data + match_length))) return ERROR_SUCCESS; } } if (STRING_IS_CHAIN_PART(string)) { result = _yr_scan_verify_chained_string_match( callback_args->matches_arena, string, match_data, match_offset, match_length, tidx); } else { result = yr_arena_allocate_memory( callback_args->matches_arena, sizeof(YR_MATCH), (void**) &new_match); if (result == ERROR_SUCCESS) { new_match->offset = match_offset; new_match->length = match_length; new_match->data = match_data; new_match->prev = NULL; new_match->next = NULL; FAIL_ON_ERROR(_yr_scan_add_match_to_list( new_match, &string->matches[tidx])); } } return result; }
int _yr_scan_verify_chained_string_match( YR_ARENA* matches_arena, YR_STRING* matching_string, uint8_t* match_data, size_t match_offset, int32_t match_length, int tidx) { YR_STRING* string; YR_MATCH* match; YR_MATCH* next_match; YR_MATCH* new_match; size_t lower_offset; size_t ending_offset; int32_t full_chain_length; int add_match = FALSE; if (matching_string->chained_to == NULL) { add_match = TRUE; } else { if (matching_string->unconfirmed_matches[tidx].head != NULL) lower_offset = matching_string->unconfirmed_matches[tidx].head->offset; else lower_offset = match_offset; match = matching_string->chained_to->unconfirmed_matches[tidx].head; while (match != NULL) { next_match = match->next; ending_offset = match->offset + match->length; if (ending_offset + matching_string->chain_gap_max < lower_offset) { _yr_scan_remove_match_from_list( match, &matching_string->chained_to->unconfirmed_matches[tidx]); } else { if (ending_offset + matching_string->chain_gap_max >= match_offset && ending_offset + matching_string->chain_gap_min <= match_offset) { add_match = TRUE; break; } } match = next_match; } } if (add_match) { if (STRING_IS_CHAIN_TAIL(matching_string)) { match = matching_string->chained_to->unconfirmed_matches[tidx].head; while (match != NULL) { ending_offset = match->offset + match->length; if (ending_offset + matching_string->chain_gap_max >= match_offset && ending_offset + matching_string->chain_gap_min <= match_offset) { _yr_scan_update_match_chain_length( tidx, matching_string->chained_to, match, 1); } match = match->next; } full_chain_length = 0; string = matching_string; while(string->chained_to != NULL) { full_chain_length++; string = string->chained_to; } // "string" points now to the head of the strings chain match = string->unconfirmed_matches[tidx].head; while (match != NULL) { next_match = match->next; if (match->chain_length == full_chain_length) { _yr_scan_remove_match_from_list( match, &string->unconfirmed_matches[tidx]); match->length = match_offset - match->offset + match_length; match->data = match_data - match_offset + match->offset; match->prev = NULL; match->next = NULL; FAIL_ON_ERROR(_yr_scan_add_match_to_list( match, &string->matches[tidx])); } match = next_match; } } else { FAIL_ON_ERROR(yr_arena_allocate_memory( matches_arena, sizeof(YR_MATCH), (void**) &new_match)); new_match->offset = match_offset; new_match->length = match_length; new_match->data = match_data; new_match->prev = NULL; new_match->next = NULL; FAIL_ON_ERROR(_yr_scan_add_match_to_list( new_match, &matching_string->unconfirmed_matches[tidx])); } } return ERROR_SUCCESS; }