static RBOOL notifyOfProcess ( RU32 pid, RU32 ppid, RBOOL isStarting ) { RBOOL isSuccess = FALSE; rSequence info = NULL; rSequence parentInfo = NULL; if( !isStarting || NULL == ( info = processLib_getProcessInfo( pid ) ) ) { info = rSequence_new(); } if( rpal_memory_isValid( info ) ) { rSequence_addRU32( info, RP_TAGS_PROCESS_ID, pid ); rSequence_addRU32( info, RP_TAGS_PARENT_PROCESS_ID, ppid ); rSequence_addTIMESTAMP( info, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() ); if( isStarting ) { if( NULL != ( parentInfo = processLib_getProcessInfo( ppid ) ) && !rSequence_addSEQUENCE( info, RP_TAGS_PARENT, parentInfo ) ) { rSequence_free( parentInfo ); } } if( isStarting ) { if( notifications_publish( RP_TAGS_NOTIFICATION_NEW_PROCESS, info ) ) { isSuccess = TRUE; rpal_debug_info( "new process starting: %d", pid ); } } else { if( notifications_publish( RP_TAGS_NOTIFICATION_TERMINATE_PROCESS, info ) ) { isSuccess = TRUE; rpal_debug_info( "new process terminating: %d", pid ); } } rSequence_free( info ); } return isSuccess; }
static int _yaraFileMatchCallback ( int message, void* message_data, void* user_data ) { YR_RULE* rule = (YR_RULE*)message_data; YaraMatchContext* context = (YaraMatchContext*)user_data; rSequence event = NULL; if( CALLBACK_MSG_RULE_MATCHING == message && NULL != message_data && NULL != user_data ) { if( NULL != ( event = rSequence_duplicate( context->fileInfo ) ) ) { rSequence_addSTRINGA( event, RP_TAGS_RULE_NAME, (char*)rule->identifier ); notifications_publish( RP_TAGS_NOTIFICATION_YARA_DETECTION, event ); rSequence_free( event ); } else { rpal_debug_warning( "error creating event from Yara match" ); } } return CALLBACK_CONTINUE; }
static int _yaraMemMatchCallback ( int message, void* message_data, void* user_data ) { YR_RULE* rule = (YR_RULE*)message_data; YaraMatchContext* context = (YaraMatchContext*)user_data; rSequence event = NULL; if( CALLBACK_MSG_RULE_MATCHING == message && NULL != message_data && NULL != user_data ) { if( NULL != ( event = rSequence_new() ) ) { rSequence_addRU32( event, RP_TAGS_PROCESS_ID, context->pid ); rSequence_addPOINTER64( event, RP_TAGS_BASE_ADDRESS, context->regionBase ); rSequence_addRU64( event, RP_TAGS_MEMORY_SIZE, context->regionSize ); hbs_markAsRelated( context->fileInfo, event ); if( NULL == context->processInfo ) { context->processInfo = processLib_getProcessInfo( context->pid, NULL ); } if( NULL != context->processInfo ) { rSequence_addSEQUENCE( event, RP_TAGS_PROCESS, rSequence_duplicate( context->processInfo ) ); } if( NULL != context->moduleInfo ) { rSequence_addSEQUENCE( event, RP_TAGS_DLL, rSequence_duplicate( context->moduleInfo ) ); } rSequence_addSTRINGA( event, RP_TAGS_RULE_NAME, (char*)rule->identifier ); notifications_publish( RP_TAGS_NOTIFICATION_YARA_DETECTION, event ); rSequence_free( event ); } else { rpal_debug_warning( "error creating event from Yara match" ); } } return CALLBACK_CONTINUE; }
static RVOID processCodeIdentA ( RPCHAR name, RPU8 pFileHash, RU64 codeSize, rSequence originalEvent ) { CodeIdent ident = { 0 }; rSequence notif = NULL; ident.codeSize = codeSize; if( NULL != name ) { CryptoLib_hash( name, rpal_string_strlen( name ) * sizeof( RCHAR ), ident.nameHash ); } if( NULL != pFileHash ) { rpal_memory_memcpy( ident.fileHash, pFileHash, CRYPTOLIB_HASH_SIZE ); } if( rpal_bloom_addIfNew( knownCode, &ident, sizeof( ident ) ) ) { if( NULL != ( notif = rSequence_new() ) ) { hbs_markAsRelated( originalEvent, notif ); if( rSequence_addSTRINGA( notif, RP_TAGS_FILE_NAME, name ) && rSequence_addBUFFER( notif, RP_TAGS_HASH, pFileHash, CRYPTOLIB_HASH_SIZE ) && rSequence_addRU32( notif, RP_TAGS_MEMORY_SIZE, (RU32)codeSize ) && rSequence_addTIMESTAMP( notif, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() ) ) { notifications_publish( RP_TAGS_NOTIFICATION_CODE_IDENTITY, notif ); } rSequence_free( notif ); } } }
//============================================================================= // YARA Required Shims //============================================================================= static RVOID reportError ( rSequence originalRequest, RU32 errorCode, RPCHAR errorStr ) { rSequence event = NULL; if( NULL != ( event = rSequence_new() ) ) { hbs_markAsRelated( originalRequest, event ); rSequence_addRU32( event, RP_TAGS_ERROR, errorCode ); rSequence_addSTRINGA( event, RP_TAGS_ERROR_MESSAGE, errorStr ? errorStr : "" ); rSequence_addTIMESTAMP( event, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() ); notifications_publish( RP_TAGS_NOTIFICATION_YARA_DETECTION, event ); rSequence_free( event ); } }
static RVOID processFile ( rSequence notif ) { RPCHAR fileA = NULL; RPWCHAR fileW = NULL; RPU8 fileContent = NULL; RU32 fileSize = 0; CryptoLib_Hash hash = { 0 }; if( NULL != notif ) { obsLib_resetSearchState( matcherA ); obsLib_resetSearchState( matcherW ); if( ( rSequence_getSTRINGA( notif, RP_TAGS_FILE_PATH, &fileA ) && obsLib_setTargetBuffer( matcherA, fileA, ( rpal_string_strlen( fileA ) + 1 ) * sizeof( RCHAR ) ) && obsLib_nextHit( matcherA, NULL, NULL ) ) || ( rSequence_getSTRINGW( notif, RP_TAGS_FILE_PATH, &fileW ) && obsLib_setTargetBuffer( matcherW, fileW, ( rpal_string_strlenw( fileW ) + 1 ) * sizeof( RWCHAR ) ) && obsLib_nextHit( matcherW, NULL, NULL ) ) ) { // This means it's a file of interest. if( ( NULL != fileA && ( ( DOCUMENT_MAX_SIZE >= rpal_file_getSize( fileA, TRUE ) && rpal_file_read( fileA, (RPVOID*)&fileContent, &fileSize, TRUE ) && CryptoLib_hash( fileContent, fileSize, &hash ) ) || CryptoLib_hashFileA( fileA, &hash, TRUE ) ) ) || ( NULL != fileW && ( ( DOCUMENT_MAX_SIZE >= rpal_file_getSizew( fileW, TRUE ) && rpal_file_readw( fileW, (RPVOID*)&fileContent, &fileSize, TRUE ) && CryptoLib_hash( fileContent, fileSize, &hash ) ) || CryptoLib_hashFileW( fileW, &hash, TRUE ) ) ) ) { // We acquired the hash, either by reading the entire file in memory // which we will use for caching, or if it was too big by hashing it // sequentially on disk. rSequence_unTaintRead( notif ); rSequence_addBUFFER( notif, RP_TAGS_HASH, (RPU8)&hash, sizeof( hash ) ); notifications_publish( RP_TAGS_NOTIFICATION_NEW_DOCUMENT, notif ); } if( rMutex_lock( cacheMutex ) ) { if( NULL == fileContent || !rSequence_addBUFFER( notif, RP_TAGS_FILE_CONTENT, fileContent, fileSize ) || !HbsRingBuffer_add( documentCache, notif ) ) { rSequence_free( notif ); } rMutex_unlock( cacheMutex ); } else { rSequence_free( notif ); } if( NULL != fileContent ) { rpal_memory_free( fileContent ); } } else { rSequence_free( notif ); } } }
static RVOID getDocument ( rpcm_tag notifId, rSequence notif ) { rSequence tmp = NULL; DocSearchContext ctx = { 0 }; RU32 hashSize = 0; rList foundDocs = NULL; RBOOL isAAlloced = FALSE; RBOOL isWAlloced = FALSE; UNREFERENCED_PARAMETER( notifId ); if( NULL != notif ) { if( !rSequence_getSTRINGA( notif, RP_TAGS_STRING_PATTERN, &ctx.exprA ) ) { ctx.exprA = NULL; } if( !rSequence_getSTRINGW( notif, RP_TAGS_STRING_PATTERN, &ctx.exprW ) ) { ctx.exprW = NULL; } if( NULL != ctx.exprA && NULL == ctx.exprW ) { ctx.exprW = rpal_string_atow( ctx.exprA ); isWAlloced = TRUE; } if( NULL != ctx.exprW && NULL == ctx.exprA ) { ctx.exprA = rpal_string_wtoa( ctx.exprW ); isAAlloced = TRUE; } if( !rSequence_getBUFFER( notif, RP_TAGS_HASH, (RPU8*)&ctx.pHash, &hashSize ) || sizeof( *ctx.pHash ) != hashSize ) { // Unexpected hash size, let's not gamble ctx.pHash = NULL; } } if( rMutex_lock( cacheMutex ) ) { if( NULL != ( foundDocs = rList_new( RP_TAGS_FILE_INFO, RPCM_SEQUENCE ) ) ) { while( HbsRingBuffer_find( documentCache, (HbsRingBufferCompareFunc)findDoc, &ctx, &tmp ) ) { // TODO: optimize this since if we're dealing with large files // we will be temporarily using large amounts of duplicate memory. // We just need to do some shallow free of the datastructures // somehow. if( NULL != ( tmp = rSequence_duplicate( tmp ) ) ) { if( !rList_addSEQUENCE( foundDocs, tmp ) ) { rSequence_free( tmp ); } } } if( !rSequence_addLIST( notif, RP_TAGS_FILES, foundDocs ) ) { rList_free( foundDocs ); } } rMutex_unlock( cacheMutex ); notifications_publish( RP_TAGS_NOTIFICATION_GET_DOCUMENT_REP, notif ); } if( isAAlloced ) { rpal_memory_free( ctx.exprA ); } if( isWAlloced ) { rpal_memory_free( ctx.exprW ); } }
static RVOID publishCloudNotifications ( rList notifications ) { rSequence notif = NULL; RPU8 buff = NULL; RU32 buffSize = 0; RPU8 sig = NULL; RU32 sigSize = 0; rpHCPId curId = { 0 }; rSequence cloudEvent = NULL; rSequence targetId = { 0 }; RU32 eventId = 0; rSequence localEvent = NULL; RU64 expiry = 0; rpHCPId tmpId = { 0 }; rSequence receipt = NULL; while( rList_getSEQUENCE( notifications, RP_TAGS_HBS_CLOUD_NOTIFICATION, ¬if ) ) { cloudEvent = NULL; if( rSequence_getBUFFER( notif, RP_TAGS_BINARY, &buff, &buffSize ) && rSequence_getBUFFER( notif, RP_TAGS_SIGNATURE, &sig, &sigSize ) ) { if( CryptoLib_verify( buff, buffSize, hbs_cloud_pub_key, sig ) ) { if( !rpHcpI_getId( &curId ) ) { rpal_debug_error( "error getting current id for cloud notifications." ); } else { if( !rSequence_deserialise( &cloudEvent, buff, buffSize, NULL ) ) { cloudEvent = NULL; rpal_debug_warning( "error deserializing cloud event." ); } } } else { rpal_debug_warning( "cloud event signature invalid." ); } } if( rpal_memory_isValid( cloudEvent ) ) { if( rSequence_getSEQUENCE( cloudEvent, RP_TAGS_HCP_ID, &targetId ) && rSequence_getRU32( cloudEvent, RP_TAGS_HBS_NOTIFICATION_ID, &eventId ) && rSequence_getSEQUENCE( cloudEvent, RP_TAGS_HBS_NOTIFICATION, &localEvent ) ) { rSequence_getTIMESTAMP( cloudEvent, RP_TAGS_EXPIRY, &expiry ); tmpId = rpHcpI_seqToHcpId( targetId ); curId.id.configId = 0; tmpId.id.configId = 0; if( NULL != ( receipt = rSequence_new() ) ) { if( rSequence_addSEQUENCE( receipt, RP_TAGS_HBS_CLOUD_NOTIFICATION, rSequence_duplicate( cloudEvent ) ) ) { if( !rQueue_add( g_hbs_state.outQueue, receipt, 0 ) ) { rSequence_free( receipt ); receipt = NULL; } } else { rSequence_free( receipt ); receipt = NULL; } } if( curId.raw == tmpId.raw && rpal_time_getGlobal() <= expiry ) { if( !notifications_publish( eventId, localEvent ) ) { rpal_debug_error( "error publishing event from cloud." ); } } else { rpal_debug_warning( "event expired or for wrong id." ); } } if( rpal_memory_isValid( cloudEvent ) ) { rSequence_free( cloudEvent ); cloudEvent = NULL; } } } }
static RPVOID trackerDiffThread ( rEvent isTimeToStop, RPVOID ctx ) { _volEntry* prevVolumes = NULL; RU32 nVolumes = 0; rList snapshot = NULL; rList prevSnapshot = NULL; _volEntry* newVolumes = NULL; RU32 nNewVolumes = 0; rSequence volume = NULL; rBlob serial = NULL; RU32 i = 0; LibOsPerformanceProfile perfProfile = { 0 }; UNREFERENCED_PARAMETER( ctx ); perfProfile.enforceOnceIn = 1; perfProfile.sanityCeiling = MSEC_FROM_SEC( 10 ); perfProfile.lastTimeoutValue = 10; perfProfile.targetCpuPerformance = 0; perfProfile.globalTargetCpuPerformance = GLOBAL_CPU_USAGE_TARGET; perfProfile.timeoutIncrementPerSec = 1; while( !rEvent_wait( isTimeToStop, 0 ) ) { libOs_timeoutWithProfile( &perfProfile, FALSE ); if( NULL != ( snapshot = libOs_getVolumes() ) ) { if( NULL != ( newVolumes = rpal_memory_alloc( sizeof( *newVolumes ) * rList_getNumElements( snapshot ) ) ) ) { nNewVolumes = 0; while( !rEvent_wait( isTimeToStop, 0 ) && rList_getSEQUENCE( snapshot, RP_TAGS_VOLUME, &volume ) ) { libOs_timeoutWithProfile( &perfProfile, TRUE ); if( NULL != ( serial = rpal_blob_create( 0, 0 ) ) ) { if( rSequence_serialise( volume, serial ) && CryptoLib_hash( rpal_blob_getBuffer( serial ), rpal_blob_getSize( serial ), &( newVolumes[ nNewVolumes ].hash ) ) ) { newVolumes[ nNewVolumes ].volume = volume; if( NULL != prevVolumes && ( -1 ) == rpal_binsearch_array( prevVolumes, nVolumes, sizeof( *prevVolumes ), &( newVolumes[ nNewVolumes ] ), (rpal_ordering_func)_cmpHashes ) ) { notifications_publish( RP_TAGS_NOTIFICATION_VOLUME_MOUNT, volume ); rpal_debug_info( "new volume mounted" ); } nNewVolumes++; } rpal_blob_free( serial ); } } if( !rEvent_wait( isTimeToStop, 0 ) ) { rpal_sort_array( newVolumes, nNewVolumes, sizeof( *newVolumes ), (rpal_ordering_func)_cmpHashes ); for( i = 0; i < nVolumes; i++ ) { libOs_timeoutWithProfile( &perfProfile, TRUE ); if( ( -1 ) == rpal_binsearch_array( newVolumes, nNewVolumes, sizeof( *newVolumes ), &( prevVolumes[ i ].hash ), (rpal_ordering_func)_cmpHashes ) ) { notifications_publish( RP_TAGS_NOTIFICATION_VOLUME_UNMOUNT, prevVolumes[ i ].volume ); rpal_debug_info( "volume unmounted" ); } } } } if( NULL != prevSnapshot ) { rList_free( prevSnapshot ); } prevSnapshot = snapshot; if( NULL != prevVolumes ) { rpal_memory_free( prevVolumes ); } prevVolumes = newVolumes; nVolumes = nNewVolumes; } } if( NULL != prevSnapshot ) { rList_free( prevSnapshot ); } if( NULL != prevVolumes ) { rpal_memory_free( prevVolumes ); } return NULL; }
static RPVOID lookForHiddenModulesIn ( rEvent isTimeToStop, RU32 processId ) { rList mods = NULL; rList map = NULL; rSequence region = NULL; RU8 memType = 0; RU8 memProtect = 0; RU64 memBase = 0; RU64 memSize = 0; RPU8 pMem = NULL; RBOOL isPrefetched = FALSE; RBOOL isCurrentExec = FALSE; RBOOL isHidden = FALSE; rSequence procInfo = NULL; #ifdef RPAL_PLATFORM_WINDOWS PIMAGE_DOS_HEADER pDos = NULL; PIMAGE_NT_HEADERS pNt = NULL; #endif if( NULL != ( mods = processLib_getProcessModules( processId ) ) ) { if( NULL != ( map = processLib_getProcessMemoryMap( processId ) ) ) { // Now we got all the info needed for a single process, compare while( rpal_memory_isValid( isTimeToStop ) && !rEvent_wait( isTimeToStop, 0 ) && ( isPrefetched || rList_getSEQUENCE( map, RP_TAGS_MEMORY_REGION, ®ion ) ) ) { if( isPrefetched ) { isPrefetched = FALSE; } if( rSequence_getRU8( region, RP_TAGS_MEMORY_TYPE, &memType ) && rSequence_getRU8( region, RP_TAGS_MEMORY_ACCESS, &memProtect ) && rSequence_getPOINTER64( region, RP_TAGS_BASE_ADDRESS, &memBase ) && rSequence_getRU64( region, RP_TAGS_MEMORY_SIZE, &memSize ) ) { if( PROCESSLIB_MEM_TYPE_PRIVATE == memType || PROCESSLIB_MEM_TYPE_MAPPED == memType ) { if( PROCESSLIB_MEM_ACCESS_EXECUTE == memProtect || PROCESSLIB_MEM_ACCESS_EXECUTE_READ == memProtect || PROCESSLIB_MEM_ACCESS_EXECUTE_READ_WRITE == memProtect || PROCESSLIB_MEM_ACCESS_EXECUTE_WRITE_COPY == memProtect ) { isCurrentExec = TRUE; } else { isCurrentExec = FALSE; } if( !isMemInModule( memBase, memSize, mods ) ) { // Exec memory found outside of a region marked to belong to // a module, keep looking in for module. if( ( 1024 * 1024 * 10 ) >= memSize && processLib_getProcessMemory( processId, NUMBER_TO_PTR( memBase ), memSize, (RPVOID*)&pMem ) ) { isHidden = FALSE; #ifdef RPAL_PLATFORM_WINDOWS // Let's just check for MZ and PE for now, we can get fancy later. pDos = (PIMAGE_DOS_HEADER)pMem; if( IS_WITHIN_BOUNDS( (RPU8)pMem, sizeof( IMAGE_DOS_HEADER ), pMem, memSize ) && IMAGE_DOS_SIGNATURE == pDos->e_magic ) { pNt = (PIMAGE_NT_HEADERS)( (RPU8)pDos + pDos->e_lfanew ); if( IS_WITHIN_BOUNDS( pNt, sizeof( *pNt ), pMem, memSize ) && IMAGE_NT_SIGNATURE == pNt->Signature ) { if( isCurrentExec ) { // If the current region is exec, we've got a hidden module. isHidden = TRUE; } else { // We need to check if the next section in memory is // executable and outside of known modules since the PE // headers may have been marked read-only before the .text. if( rList_getSEQUENCE( map, RP_TAGS_MEMORY_REGION, ®ion ) ) { isPrefetched = TRUE; if( ( PROCESSLIB_MEM_TYPE_PRIVATE == memType || PROCESSLIB_MEM_TYPE_MAPPED == memType ) && ( PROCESSLIB_MEM_ACCESS_EXECUTE == memProtect || PROCESSLIB_MEM_ACCESS_EXECUTE_READ == memProtect || PROCESSLIB_MEM_ACCESS_EXECUTE_READ_WRITE == memProtect || PROCESSLIB_MEM_ACCESS_EXECUTE_WRITE_COPY == memProtect ) ) { isHidden = TRUE; } } } } } #elif defined( RPAL_PLATFORM_LINUX ) || defined( RPAL_PLATFORM_MACOSX ) if( isCurrentExec && 0x7F == ( pMem )[ 0 ] && 'E' == ( pMem )[ 1 ] && 'L' == ( pMem )[ 2 ] && 'F' == ( pMem )[ 3 ] ) { isHidden = TRUE; } #endif rpal_memory_free( pMem ); if( isHidden && !rEvent_wait( isTimeToStop, 0 ) ) { rpal_debug_info( "found a hidden module in %d.", processId ); if( NULL != ( procInfo = processLib_getProcessInfo( processId ) ) ) { if( !rSequence_addSEQUENCE( region, RP_TAGS_PROCESS, procInfo ) ) { rSequence_free( procInfo ); } } rSequence_addTIMESTAMP( region, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() ); notifications_publish( RP_TAGS_NOTIFICATION_HIDDEN_MODULE_DETECTED, region ); break; } rpal_thread_sleep( 10 ); } } } } } rList_free( map ); } rList_free( mods ); } return NULL; }
static RPVOID networkDiffThread ( rEvent isTimeToStop, RPVOID ctx ) { NetLib_Tcp4Table* currentTcp4Table = NULL; NetLib_Tcp4Table* oldTcp4Table = NULL; NetLib_UdpTable* currentUdpTable = NULL; NetLib_UdpTable* oldUdpTable = NULL; RU32 i = 0; RU32 j = 0; RBOOL isFound = FALSE; rSequence notif = NULL; rSequence comp = NULL; RU32 timeout = 100; RU32 nThLoop = 0; UNREFERENCED_PARAMETER( ctx ); while( rpal_memory_isValid( isTimeToStop ) && !rEvent_wait( isTimeToStop, 0 ) ) { if( NULL != oldTcp4Table ) { rpal_memory_free( oldTcp4Table ); oldTcp4Table = NULL; } if( NULL != oldUdpTable ) { rpal_memory_free( oldUdpTable ); oldUdpTable = NULL; } // Swap the old snapshot for the (prev) new one oldTcp4Table = currentTcp4Table; oldUdpTable = currentUdpTable; currentTcp4Table = NULL; currentUdpTable = NULL; // Generate new tables currentTcp4Table = NetLib_getTcp4Table(); currentUdpTable = NetLib_getUdpTable(); // Diff TCP snapshots for new entries if( rpal_memory_isValid( currentTcp4Table ) && rpal_memory_isValid( oldTcp4Table ) ) { for( i = 0; i < currentTcp4Table->nRows; i++ ) { isFound = FALSE; if( rEvent_wait( isTimeToStop, 0 ) ) { break; } for( j = 0; j < oldTcp4Table->nRows; j++ ) { if( isTcpEqual( ¤tTcp4Table->rows[ i ], &oldTcp4Table->rows[ j ] ) ) { isFound = TRUE; break; } } if( !isFound ) { if( NULL != ( notif = rSequence_new() ) ) { if( rSequence_addRU32( notif, RP_TAGS_STATE, currentTcp4Table->rows[ i ].state ) && rSequence_addRU32( notif, RP_TAGS_PROCESS_ID, currentTcp4Table->rows[ i ].pid ) && rSequence_addTIMESTAMP( notif, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() ) ) { if( NULL != ( comp = rSequence_new() ) ) { // Add the destination components if( !rSequence_addIPV4( comp, RP_TAGS_IP_ADDRESS, currentTcp4Table->rows[ i ].destIp ) || !rSequence_addRU16( comp, RP_TAGS_PORT, rpal_ntoh16( (RU16)currentTcp4Table->rows[ i ].destPort ) ) || !rSequence_addSEQUENCE( notif, RP_TAGS_DESTINATION, comp ) ) { rSequence_free( comp ); comp = NULL; } } if( NULL != ( comp = rSequence_new() ) ) { // Add the source components if( !rSequence_addIPV4( comp, RP_TAGS_IP_ADDRESS, currentTcp4Table->rows[ i ].sourceIp ) || !rSequence_addRU16( comp, RP_TAGS_PORT, rpal_ntoh16( (RU16)currentTcp4Table->rows[ i ].sourcePort ) ) || !rSequence_addSEQUENCE( notif, RP_TAGS_SOURCE, comp ) ) { rSequence_free( comp ); comp = NULL; } } rpal_debug_info( "new tcp connection: 0x%08X = 0x%08X:0x%04X ---> 0x%08X:0x%04X -- 0x%08X.", currentTcp4Table->rows[ i ].state, currentTcp4Table->rows[ i ].sourceIp, currentTcp4Table->rows[ i ].sourcePort, currentTcp4Table->rows[ i ].destIp, currentTcp4Table->rows[ i ].destPort, currentTcp4Table->rows[ i ].pid ); notifications_publish( RP_TAGS_NOTIFICATION_NEW_TCP4_CONNECTION, notif ); } rSequence_free( notif ); } } } } else if( 0 != nThLoop ) { rpal_debug_warning( "could not get tcp connections table." ); } // Diff TCP snapshots for new entries if( NULL != currentUdpTable && NULL != oldUdpTable ) { for( i = 0; i < currentUdpTable->nRows; i++ ) { isFound = FALSE; if( rEvent_wait( isTimeToStop, 0 ) ) { break; } for( j = 0; j < oldUdpTable->nRows; j++ ) { if( isUdpEqual( ¤tUdpTable->rows[ i ], &oldUdpTable->rows[ j ] ) ) { isFound = TRUE; break; } } if( !isFound ) { if( NULL != ( notif = rSequence_new() ) ) { if( !rSequence_addIPV4( notif, RP_TAGS_IP_ADDRESS, currentUdpTable->rows[ i ].localIp ) || !rSequence_addRU16( notif, RP_TAGS_PORT, rpal_ntoh16( (RU16)currentUdpTable->rows[ i ].localPort ) ) || !rSequence_addRU32( notif, RP_TAGS_PROCESS_ID, currentUdpTable->rows[ i ].pid ) || !rSequence_addTIMESTAMP( notif, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() ) ) { notif = NULL; } else { rpal_debug_info( "new udp connection: 0x%08X:0x%04X -- 0x%08X.", currentUdpTable->rows[ i ].localIp, currentUdpTable->rows[ i ].localPort, currentUdpTable->rows[ i ].pid ); notifications_publish( RP_TAGS_NOTIFICATION_NEW_UDP4_CONNECTION, notif ); } rSequence_free( notif ); } } } } else if( 0 != nThLoop ) { rpal_debug_warning( "could not get udp connections table." ); } nThLoop++; if( 0 == nThLoop % 10 ) { timeout = libOs_getUsageProportionalTimeout( 1000 ) + 500; } rpal_thread_sleep( timeout ); } rpal_memory_free( currentTcp4Table ); rpal_memory_free( currentUdpTable ); rpal_memory_free( oldTcp4Table ); rpal_memory_free( oldUdpTable ); return NULL; }
static RPVOID dnsDiffThread ( rEvent isTimeToStop, RPVOID ctx ) { RU32 nThLoop = 0; RU32 currentTimeout = 0; rSequence notif = NULL; rBlob snapCur = NULL; rBlob snapPrev = NULL; _dnsRecord rec = { 0 }; _dnsRecord* pCurRec = NULL; _dnsRecord* pPrevRec = NULL; RU32 i = 0; RU32 j = 0; RBOOL isNew = FALSE; #ifdef RPAL_PLATFORM_WINDOWS PDNSCACHEENTRY pDnsEntry = NULL; PDNSCACHEENTRY pPrevDnsEntry = NULL; #endif UNREFERENCED_PARAMETER( ctx ); while( !rEvent_wait( isTimeToStop, currentTimeout ) ) { 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_strdupw( pDnsEntry->pszName ) ) ) { rpal_blob_add( snapCur, &rec, sizeof( rec ) ); } pPrevDnsEntry = pDnsEntry; pDnsEntry = pDnsEntry->pNext; freeCacheEntry( pPrevDnsEntry->pszName, DnsFreeFlat ); freeCacheEntry( pPrevDnsEntry, DnsFreeFlat ); } } #endif // Do a general diff of the snapshots to find new entries. if( NULL != snapPrev ) { i = 0; while( NULL != ( pCurRec = rpal_blob_arrElem( snapCur, sizeof( rec ), i++ ) ) ) { isNew = TRUE; j = 0; while( NULL != ( pPrevRec = rpal_blob_arrElem( snapPrev, sizeof( rec ), j++ ) ) ) { if( pCurRec->flags == pPrevRec->flags && pCurRec->type == pPrevRec->type && 0 == rpal_string_strcmpw( pCurRec->name, pPrevRec->name ) ) { isNew = FALSE; break; } } if( isNew && !rEvent_wait( isTimeToStop, 0 ) ) { if( NULL != ( notif = rSequence_new() ) ) { rSequence_addSTRINGW( 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 ); rSequence_addTIMESTAMP( notif, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() ); notifications_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; nThLoop++; if( 0 == nThLoop % 20 ) { currentTimeout = libOs_getUsageProportionalTimeout( MSEC_FROM_SEC( 10 ) ) + MSEC_FROM_SEC( 5 ); } rpal_thread_sleep( currentTimeout ); } if( NULL != snapPrev ) { _freeRecords( snapPrev ); rpal_blob_free( snapPrev ); snapPrev = NULL; } return NULL; }
static RBOOL notifyOfProcess ( RU32 pid, RU32 ppid, RBOOL isStarting, RNATIVESTR optFilePath, RNATIVESTR optCmdLine, RU32 optUserId, RU64 optTs ) { RBOOL isSuccess = FALSE; rSequence info = NULL; rSequence parentInfo = NULL; RU32 tmpUid = 0; RNATIVESTR cleanPath = NULL; // We prime the information with whatever was provided // to us by the kernel acquisition. If not available // we generate using the UM only way. if( 0 != rpal_string_strlenn( optFilePath ) && ( NULL != info || NULL != ( info = rSequence_new() ) ) ) { cleanPath = rpal_file_cleann( optFilePath ); rSequence_addSTRINGN( info, RP_TAGS_FILE_PATH, cleanPath ? cleanPath : optFilePath ); rpal_memory_free( cleanPath ); } if( 0 != rpal_string_strlenn( optCmdLine ) && ( NULL != info || NULL != ( info = rSequence_new() ) ) ) { rSequence_addSTRINGN( info, RP_TAGS_COMMAND_LINE, optCmdLine ); } if( NULL != info ) { info = processLib_getProcessInfo( pid, info ); } else if( !isStarting || NULL == ( info = processLib_getProcessInfo( pid, info ) ) ) { info = rSequence_new(); } if( rpal_memory_isValid( info ) ) { rSequence_addRU32( info, RP_TAGS_PROCESS_ID, pid ); rSequence_addRU32( info, RP_TAGS_PARENT_PROCESS_ID, ppid ); if( 0 != optTs ) { rSequence_addTIMESTAMP( info, RP_TAGS_TIMESTAMP, rpal_time_getGlobalFromLocal( optTs ) ); } else { rSequence_addTIMESTAMP( info, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() ); } if( isStarting ) { if( NULL != ( parentInfo = processLib_getProcessInfo( ppid, NULL ) ) && !rSequence_addSEQUENCE( info, RP_TAGS_PARENT, parentInfo ) ) { rSequence_free( parentInfo ); } } if( isStarting ) { if( KERNEL_ACQ_NO_USER_ID != optUserId && !rSequence_getRU32( info, RP_TAGS_USER_ID, &tmpUid ) ) { rSequence_addRU32( info, RP_TAGS_USER_ID, optUserId ); } if( notifications_publish( RP_TAGS_NOTIFICATION_NEW_PROCESS, info ) ) { isSuccess = TRUE; rpal_debug_info( "new process starting: %d / %d", pid, ppid ); } } else { if( notifications_publish( RP_TAGS_NOTIFICATION_TERMINATE_PROCESS, info ) ) { isSuccess = TRUE; rpal_debug_info( "new process terminating: %d / %d", pid, ppid ); } } rSequence_free( info ); } else { rpal_debug_error( "could not allocate info on new process" ); } return isSuccess; }
static RVOID processCodeIdentW ( RPWCHAR name, CryptoLib_Hash* pFileHash, RU64 codeSize, rSequence originalEvent ) { CodeIdent ident = { 0 }; rSequence notif = NULL; rSequence sig = NULL; RBOOL isSigned = FALSE; RBOOL isVerifiedLocal = FALSE; RBOOL isVerifiedGlobal = FALSE; ident.codeSize = codeSize; if( NULL != name ) { CryptoLib_hash( name, rpal_string_strlenw( name ) * sizeof( RWCHAR ), &ident.nameHash ); } if( NULL != pFileHash ) { rpal_memory_memcpy( &ident.fileHash, pFileHash, sizeof( *pFileHash ) ); } if( rMutex_lock( g_mutex ) ) { if( rpal_bloom_addIfNew( g_knownCode, &ident, sizeof( ident ) ) ) { rMutex_unlock( g_mutex ); if( NULL != ( notif = rSequence_new() ) ) { hbs_markAsRelated( originalEvent, notif ); if( ( rSequence_addSTRINGW( notif, RP_TAGS_FILE_PATH, name ) || rSequence_addSTRINGW( notif, RP_TAGS_DLL, name ) || rSequence_addSTRINGW( notif, RP_TAGS_EXECUTABLE, name ) ) && rSequence_addRU32( notif, RP_TAGS_MEMORY_SIZE, (RU32)codeSize ) && rSequence_addTIMESTAMP( notif, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() ) ) { if( NULL != pFileHash ) { rSequence_addBUFFER( notif, RP_TAGS_HASH, (RPU8)pFileHash, sizeof( *pFileHash ) ); } if( libOs_getSignature( name, &sig, ( OSLIB_SIGNCHECK_NO_NETWORK | OSLIB_SIGNCHECK_CHAIN_VERIFICATION ), &isSigned, &isVerifiedLocal, &isVerifiedGlobal ) ) { if( !rSequence_addSEQUENCE( notif, RP_TAGS_SIGNATURE, sig ) ) { rSequence_free( sig ); } } notifications_publish( RP_TAGS_NOTIFICATION_CODE_IDENTITY, notif ); } rSequence_free( notif ); } } else { rMutex_unlock( g_mutex ); } } }