void* scanning_thread(void* param) #endif { YR_RULES* rules = (YR_RULES*) param; char* file_path; int result; file_path = file_queue_get(); while (file_path != NULL) { result = yr_rules_scan_file( rules, file_path, callback, file_path, fast_scan, timeout); if (result != ERROR_SUCCESS) { mutex_lock(&output_mutex); fprintf(stderr, "Error scanning %s: ", file_path); print_scanning_error(result); mutex_unlock(&output_mutex); } free(file_path); file_path = file_queue_get(); } yr_finalize_thread(); return 0; }
static RVOID updateSignatures ( rpcm_tag eventType, rSequence event ) { RPU8 buffer = NULL; RU32 bufferSize = 0; YR_RULES* rules = NULL; UNREFERENCED_PARAMETER( eventType ); if( rpal_memory_isValid( event ) ) { if( rSequence_getBUFFER( event, RP_TAGS_RULES, &buffer, &bufferSize ) ) { if( NULL != ( rules = loadYaraRules( buffer, bufferSize ) ) ) { if( rMutex_lock( g_global_rules_mutex ) ) { g_global_rules = rules; rMutex_unlock( g_global_rules_mutex ); } else { yr_rules_destroy( rules ); } } } } yr_finalize_thread(); }
static RVOID doScan ( rpcm_tag eventType, rSequence event ) { RU32 pid = 0; RPWCHAR fileW = NULL; RPCHAR fileA = NULL; RPWCHAR procW = NULL; RPCHAR procA = NULL; RPU8 rulesBuffer = NULL; RU32 rulesBufferSize = 0; YR_RULES* rules = NULL; YaraMatchContext matchContext = { 0 }; processLibProcEntry* processes = NULL; processLibProcEntry* curProc = NULL; RU32 scanError = 0; rSequence processInfo = NULL; RPWCHAR tmpW = NULL; RPCHAR tmpA = NULL; UNREFERENCED_PARAMETER( eventType ); if( rpal_memory_isValid( event ) ) { rSequence_getRU32( event, RP_TAGS_PROCESS_ID, &pid ); rSequence_getSTRINGW( event, RP_TAGS_FILE_PATH, &fileW ); rSequence_getSTRINGA( event, RP_TAGS_FILE_PATH, &fileA ); rSequence_getSTRINGW( event, RP_TAGS_PROCESS, &procW ); rSequence_getSTRINGA( event, RP_TAGS_PROCESS, &procA ); if( rSequence_getBUFFER( event, RP_TAGS_RULES, &rulesBuffer, &rulesBufferSize ) ) { rules = loadYaraRules( rulesBuffer, rulesBufferSize ); } if( NULL != rules ) { if( NULL != fileW ) { fileA = rpal_string_wtoa( fileW ); } if( NULL != procW ) { procA = rpal_string_wtoa( procW ); } if( NULL != fileA ) { rpal_debug_info( "scanning file with yara" ); matchContext.fileInfo = event; // Scan this file if( ERROR_SUCCESS != ( scanError = yr_rules_scan_file( rules, fileA, SCAN_FLAGS_FAST_MODE, _yaraFileMatchCallback, &matchContext, 60 ) ) ) { rpal_debug_warning( "Yara file scan error: %d", scanError ); } } else if( NULL != procA ) { // Scan processes matching if( NULL != ( processes = processLib_getProcessEntries( TRUE ) ) ) { curProc = processes; while( 0 != curProc->pid ) { if( NULL != ( processInfo = processLib_getProcessInfo( curProc->pid, NULL ) ) ) { if( rSequence_getSTRINGW( processInfo, RP_TAGS_FILE_PATH, &tmpW ) || rSequence_getSTRINGA( processInfo, RP_TAGS_FILE_PATH, &tmpA ) ) { if( NULL != tmpW ) { tmpA = rpal_string_wtoa( tmpW ); } if( NULL != tmpA ) { if( rpal_string_match( procA, tmpA, RPAL_PLATFORM_FS_CASE_SENSITIVITY ) ) { matchContext.pid = curProc->pid; matchContext.processInfo = processInfo; scanError = _scanProcessWith( curProc->pid, &matchContext, rules, NULL ); } } if( NULL != tmpW && NULL != tmpA ) { // If both are allocated it means we got a strW and converted to A // so we must free the strA version. rpal_memory_free( tmpA ); } } rSequence_free( processInfo ); } curProc++; } rpal_memory_free( processes ); } } else if( 0 != pid ) { // Scan this process matchContext.pid = pid; scanError = _scanProcessWith( pid, &matchContext, rules, NULL ); rSequence_free( matchContext.processInfo ); } else { // Scan all processes if( NULL != ( processes = processLib_getProcessEntries( TRUE ) ) ) { curProc = processes; while( 0 != curProc->pid ) { matchContext.pid = curProc->pid; scanError = _scanProcessWith( curProc->pid, &matchContext, rules, NULL ); rSequence_free( matchContext.processInfo ); curProc++; } rpal_memory_free( processes ); } } if( NULL != fileW && NULL != fileA ) { // If both are allocated it means we got a strW and converted to A // so we must free the strA version. rpal_memory_free( fileA ); } if( NULL != procW && NULL != procA ) { // If both are allocated it means we got a strW and converted to A // so we must free the strA version. rpal_memory_free( procA ); } yr_rules_destroy( rules ); } else { rpal_debug_warning( "no rules in yara scan request" ); reportError( event, RPAL_ERROR_NOT_SUPPORTED, "yara rules do not parse" ); } } rpal_debug_info( "finished on demand yara scan" ); reportError( event, scanError, "done" ); yr_finalize_thread(); }
static RPVOID continuousFileScan ( rEvent isTimeToStop, RPVOID ctx ) { rSequence event = NULL; RU32 timeout = 0; RPWCHAR strW = NULL; RPCHAR strA = NULL; YaraMatchContext matchContext = { 0 }; RU32 scanError = 0; rBloom knownFiles = NULL; UNREFERENCED_PARAMETER( ctx ); if( NULL == ( knownFiles = rpal_bloom_create( 100000, 0.00001 ) ) ) { return NULL; } while( !rEvent_wait( isTimeToStop, timeout ) ) { if( rQueue_remove( g_async_files_to_scan, (RPVOID*)&event, NULL, MSEC_FROM_SEC( 2 ) ) ) { if( rSequence_getSTRINGW( event, RP_TAGS_FILE_PATH, &strW ) ) { strA = rpal_string_wtoa( strW ); } else { rSequence_getSTRINGA( event, RP_TAGS_FILE_PATH, &strA ); } if( NULL != strA && rpal_bloom_addIfNew( knownFiles, strA, rpal_string_strlen( strA ) ) ) { rpal_debug_info( "yara scanning %s", strA ); matchContext.fileInfo = event; if( rMutex_lock( g_global_rules_mutex ) ) { if( NULL != g_global_rules ) { rpal_debug_info( "scanning continuous file with yara" ); if( ERROR_SUCCESS != ( scanError = yr_rules_scan_file( g_global_rules, strA, SCAN_FLAGS_FAST_MODE, _yaraFileMatchCallback, &matchContext, 60 ) ) ) { rpal_debug_warning( "Yara file scan error: %d", scanError ); } } rMutex_unlock( g_global_rules_mutex ); } } if( NULL != strA && NULL != strW ) { // If both are allocated it means we got a strW and converted to A // so we must free the strA version. rpal_memory_free( strA ); } strA = NULL; strW = NULL; rSequence_free( event ); timeout = _TIMEOUT_BETWEEN_FILE_SCANS; } else { timeout = 0; } } rpal_bloom_destroy( knownFiles ); yr_finalize_thread(); return NULL; }
static RPVOID continuousMemScan ( rEvent isTimeToStop, RPVOID ctx ) { processLibProcEntry* processes = NULL; processLibProcEntry* curProc = NULL; RU32 thisProcId = 0; YaraMatchContext matchContext = { 0 }; RU32 scanError = 0; UNREFERENCED_PARAMETER( ctx ); thisProcId = processLib_getCurrentPid(); while( !rEvent_wait( isTimeToStop, 0 ) ) { // Wait until we have global rules to look for. if( rMutex_lock( g_global_rules_mutex ) ) { if( NULL == g_global_rules ) { rMutex_unlock( g_global_rules_mutex ); rEvent_wait( isTimeToStop, MSEC_FROM_SEC( 30 ) ); continue; } rMutex_unlock( g_global_rules_mutex ); } if( NULL != ( processes = processLib_getProcessEntries( TRUE ) ) ) { curProc = processes; while( 0 != curProc->pid ) { // We can't examine our own memory for the risk of tripping on the sigs themselves. if( curProc->pid == thisProcId ) continue; rpal_debug_info( "yara scanning pid %d", curProc->pid ); matchContext.pid = curProc->pid; matchContext.processInfo = NULL; matchContext.moduleInfo = NULL; scanError = _scanProcessWith( curProc->pid, &matchContext, NULL, isTimeToStop ); rSequence_free( matchContext.processInfo ); if( rEvent_wait( isTimeToStop, MSEC_FROM_SEC( 30 ) ) ) { break; } curProc++; } rpal_memory_free( processes ); } } yr_finalize_thread(); return NULL; }