RPRIVATE RPVOID dnsDiffThread ( rEvent isTimeToStop, RPVOID ctx ) { UNREFERENCED_PARAMETER( ctx ); while( !rEvent_wait( isTimeToStop, 0 ) ) { if( kAcq_isAvailable() ) { rpal_debug_info( "running kernelmode acquisition dns notification" ); dnsKmDiffThread( isTimeToStop ); } else if( !rEvent_wait( isTimeToStop, 0 ) ) { rpal_debug_info( "running usermode acquisition dns notification" ); dnsUmDiffThread( isTimeToStop ); } } return NULL; }
static RPVOID moduleDiffThread ( rEvent isTimeToStop, RPVOID ctx ) { UNREFERENCED_PARAMETER( ctx ); while( !rEvent_wait( isTimeToStop, 0 ) ) { if( kAcq_isAvailable() && !g_is_kernel_failure ) { // We first attempt to get new modules through // the kernel mode acquisition driver rpal_debug_info( "running kernel acquisition module notification" ); modKernelModeDiff( isTimeToStop ); } // If the kernel mode fails, or is not available, try // to revert to user mode else if( !rEvent_wait( isTimeToStop, 0 ) ) { rpal_debug_info( "running usermode acquisition module notification" ); modUserModeDiff( isTimeToStop ); } } return NULL; }
RPRIVATE RVOID dnsUmDiffThread ( rEvent isTimeToStop ) { rSequence notif = NULL; rBlob snapCur = NULL; rBlob snapPrev = NULL; _dnsRecord rec = { 0 }; _dnsRecord* pCurRec = NULL; RU32 i = 0; LibOsPerformanceProfile perfProfile = { 0 }; #ifdef RPAL_PLATFORM_WINDOWS PDNSCACHEENTRY pDnsEntry = NULL; PDNSCACHEENTRY pPrevDnsEntry = NULL; #endif perfProfile.enforceOnceIn = 1; perfProfile.sanityCeiling = MSEC_FROM_SEC( 10 ); perfProfile.lastTimeoutValue = 100; perfProfile.targetCpuPerformance = 0; perfProfile.globalTargetCpuPerformance = GLOBAL_CPU_USAGE_TARGET; perfProfile.timeoutIncrementPerSec = 1; while( !rEvent_wait( isTimeToStop, 0 ) ) { if( kAcq_isAvailable() ) { // If kernel acquisition becomes available, try kernel again. return; } libOs_timeoutWithProfile( &perfProfile, FALSE, isTimeToStop ); if( NULL != ( snapCur = rpal_blob_create( 0, 10 * sizeof( rec ) ) ) ) { #ifdef RPAL_PLATFORM_WINDOWS if( TRUE == getCache( &pDnsEntry ) ) { while( NULL != pDnsEntry ) { rec.flags = pDnsEntry->dwFlags; rec.type = pDnsEntry->wType; if( NULL != ( rec.name = rpal_string_strdup( pDnsEntry->pszName ) ) ) { rpal_blob_add( snapCur, &rec, sizeof( rec ) ); } pPrevDnsEntry = pDnsEntry; pDnsEntry = pDnsEntry->pNext; freeCacheEntry( pPrevDnsEntry->pszName, DnsFreeFlat ); freeCacheEntry( pPrevDnsEntry, DnsFreeFlat ); } rpal_sort_array( rpal_blob_getBuffer( snapCur ), rpal_blob_getSize( snapCur ) / sizeof( rec ), sizeof( rec ), _cmpDns ); } #elif defined( RPAL_PLATFORM_MACOSX ) rpal_thread_sleep( MSEC_FROM_SEC( 2 ) ); #endif // Do a general diff of the snapshots to find new entries. if( NULL != snapPrev ) { i = 0; while( !rEvent_wait( isTimeToStop, 0 ) && NULL != ( pCurRec = rpal_blob_arrElem( snapCur, sizeof( rec ), i++ ) ) ) { if( -1 == rpal_binsearch_array( rpal_blob_getBuffer( snapPrev ), rpal_blob_getSize( snapPrev ) / sizeof( rec ), sizeof( rec ), pCurRec, (rpal_ordering_func)_cmpDns ) ) { if( NULL != ( notif = rSequence_new() ) ) { rSequence_addSTRINGN( notif, RP_TAGS_DOMAIN_NAME, pCurRec->name ); rSequence_addRU16( notif, RP_TAGS_DNS_TYPE, pCurRec->type ); rSequence_addRU32( notif, RP_TAGS_DNS_FLAGS, pCurRec->flags ); hbs_timestampEvent( notif, 0 ); hbs_publish( RP_TAGS_NOTIFICATION_DNS_REQUEST, notif ); rSequence_free( notif ); } } } } } if( NULL != snapPrev ) { _freeRecords( snapPrev ); rpal_blob_free( snapPrev ); snapPrev = NULL; } snapPrev = snapCur; snapCur = NULL; libOs_timeoutWithProfile( &perfProfile, TRUE, isTimeToStop ); } if( NULL != snapPrev ) { _freeRecords( snapPrev ); rpal_blob_free( snapPrev ); snapPrev = NULL; } }
static RPVOID modUserModeDiff ( rEvent isTimeToStop ) { rBlob previousSnapshot = NULL; rBlob newSnapshot = NULL; _moduleHistEntry curModule = { 0 }; processLibProcEntry* processes = NULL; processLibProcEntry* curProc = NULL; rList modules = NULL; rSequence module = NULL; LibOsPerformanceProfile perfProfile = { 0 }; Atom parentAtom = { 0 }; RU64 curTime = 0; perfProfile.enforceOnceIn = 1; perfProfile.lastTimeoutValue = 10; perfProfile.sanityCeiling = MSEC_FROM_SEC( 10 ); perfProfile.targetCpuPerformance = 0; perfProfile.globalTargetCpuPerformance = GLOBAL_CPU_USAGE_TARGET; perfProfile.timeoutIncrementPerSec = 1; while( rpal_memory_isValid( isTimeToStop ) && !rEvent_wait( isTimeToStop, 0 ) && ( !kAcq_isAvailable() || g_is_kernel_failure ) ) { if( NULL != ( processes = processLib_getProcessEntries( FALSE ) ) ) { if( NULL != ( newSnapshot = rpal_blob_create( 1000 * sizeof( _moduleHistEntry ), 1000 * sizeof( _moduleHistEntry ) ) ) ) { libOs_timeoutWithProfile( &perfProfile, FALSE, isTimeToStop ); curProc = processes; while( rpal_memory_isValid( isTimeToStop ) && #ifdef RPAL_PLATFORM_WINDOWS !rEvent_wait( isTimeToStop, 0 ) && #else // Module listing outside of !rEvent_wait( isTimeToStop, MSEC_FROM_SEC( 1 ) ) && #endif 0 != curProc->pid ) { if( NULL != ( modules = processLib_getProcessModules( curProc->pid ) ) ) { curTime = rpal_time_getGlobalPreciseTime(); while( rpal_memory_isValid( isTimeToStop ) && !rEvent_wait( isTimeToStop, 0 ) && rList_getSEQUENCE( modules, RP_TAGS_DLL, &module ) ) { libOs_timeoutWithProfile( &perfProfile, TRUE, isTimeToStop ); if( rSequence_getPOINTER64( module, RP_TAGS_BASE_ADDRESS, &( curModule.baseAddr ) ) && rSequence_getRU64( module, RP_TAGS_MEMORY_SIZE, &(curModule.size) ) ) { curModule.procId = curProc->pid; rpal_blob_add( newSnapshot, &curModule, sizeof( curModule ) ); if( NULL != previousSnapshot && -1 == rpal_binsearch_array( rpal_blob_getBuffer( previousSnapshot ), rpal_blob_getSize( previousSnapshot ) / sizeof( _moduleHistEntry ), sizeof( _moduleHistEntry ), &curModule, (rpal_ordering_func)_cmpModule ) ) { hbs_timestampEvent( module, curTime ); parentAtom.key.category = RP_TAGS_NOTIFICATION_NEW_PROCESS; parentAtom.key.process.pid = curProc->pid; if( atoms_query( &parentAtom, curTime ) ) { HbsSetParentAtom( module, parentAtom.id ); } rpal_memory_zero( &parentAtom, sizeof( parentAtom ) ); hbs_publish( RP_TAGS_NOTIFICATION_MODULE_LOAD, module ); } } } rList_free( modules ); } curProc++; } if( !rpal_sort_array( rpal_blob_getBuffer( newSnapshot ), rpal_blob_getSize( newSnapshot ) / sizeof( _moduleHistEntry ), sizeof( _moduleHistEntry ), (rpal_ordering_func)_cmpModule ) ) { rpal_debug_warning( "error sorting modules" ); } } rpal_memory_free( processes ); } if( NULL != previousSnapshot ) { rpal_blob_free( previousSnapshot ); } previousSnapshot = newSnapshot; newSnapshot = NULL; } if( NULL != previousSnapshot ) { rpal_blob_free( previousSnapshot ); } return NULL; }
static RVOID userModeDiff ( rEvent isTimeToStop ) { processEntry snapshot_1[ MAX_SNAPSHOT_SIZE ] = { 0 }; processEntry snapshot_2[ MAX_SNAPSHOT_SIZE ] = { 0 }; processEntry* currentSnapshot = snapshot_1; processEntry* previousSnapshot = snapshot_2; processEntry* tmpSnapshot = NULL; RBOOL isFirstSnapshots = TRUE; RU32 i = 0; RBOOL isFound = FALSE; RU32 nTmpElem = 0; RU32 nCurElem = 0; RU32 nPrevElem = 0; LibOsPerformanceProfile perfProfile = { 0 }; perfProfile.enforceOnceIn = 1; perfProfile.sanityCeiling = MSEC_FROM_SEC( 10 ); perfProfile.lastTimeoutValue = 100; perfProfile.targetCpuPerformance = 0; perfProfile.globalTargetCpuPerformance = GLOBAL_CPU_USAGE_TARGET; perfProfile.timeoutIncrementPerSec = 10; while( !rEvent_wait( isTimeToStop, 0 ) && ( !kAcq_isAvailable() || g_is_kernel_failure ) ) { libOs_timeoutWithProfile( &perfProfile, FALSE ); tmpSnapshot = currentSnapshot; currentSnapshot = previousSnapshot; previousSnapshot = tmpSnapshot; nTmpElem = nCurElem; nCurElem = nPrevElem; nPrevElem = nTmpElem; if( getSnapshot( currentSnapshot, &nCurElem ) ) { if( isFirstSnapshots ) { isFirstSnapshots = FALSE; continue; } // Diff to find new processes for( i = 0; i < nCurElem; i++ ) { isFound = FALSE; if( (RU32)( -1 ) != rpal_binsearch_array( previousSnapshot, nPrevElem, sizeof( processEntry ), &(currentSnapshot[ i ].pid), (rpal_ordering_func)rpal_order_RU32 ) ) { isFound = TRUE; } if( !isFound ) { if( !notifyOfProcess( currentSnapshot[ i ].pid, currentSnapshot[ i ].ppid, TRUE, NULL, NULL, KERNEL_ACQ_NO_USER_ID, 0 ) ) { rpal_debug_warning( "error reporting new process: %d", currentSnapshot[ i ].pid ); } } } // Diff to find terminated processes for( i = 0; i < nPrevElem; i++ ) { isFound = FALSE; if( (RU32)( -1 ) != rpal_binsearch_array( currentSnapshot, nCurElem, sizeof( processEntry ), &(previousSnapshot[ i ].pid), (rpal_ordering_func)rpal_order_RU32 ) ) { isFound = TRUE; } if( !isFound ) { if( !notifyOfProcess( previousSnapshot[ i ].pid, previousSnapshot[ i ].ppid, FALSE, NULL, NULL, KERNEL_ACQ_NO_USER_ID, 0 ) ) { rpal_debug_warning( "error reporting terminated process: %d", previousSnapshot[ i ].pid ); } } } } libOs_timeoutWithProfile( &perfProfile, TRUE ); } }