static RVOID sendStartupEvent ( ) { rSequence wrapper = NULL; rSequence startupEvent = NULL; if( NULL != ( wrapper = rSequence_new() ) ) { if( NULL != ( startupEvent = rSequence_new() ) ) { if( rSequence_addSEQUENCE( wrapper, RP_TAGS_NOTIFICATION_STARTING_UP, startupEvent ) ) { if( !rSequence_addTIMESTAMP( startupEvent, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() ) || !rQueue_add( g_hbs_state.outQueue, wrapper, 0 ) ) { rSequence_free( wrapper ); } } else { rSequence_free( wrapper ); rSequence_free( startupEvent ); } } else { rSequence_free( wrapper ); } } }
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; }
// Receives new process notifications and check if they're on our // deny list, if so, kill. RPRIVATE RVOID denyNewProcesses ( rpcm_tag notifType, rSequence event ) { RPU8 atomId = NULL; RU32 pid = 0; UNREFERENCED_PARAMETER( notifType ); // We use the lastActivity check here as a cheap way of seeing if there is // anything at all in the denied tree. if( 0 != g_lastDenyActivity && HbsGetParentAtom( event, &atomId ) && isAtomDenied( atomId ) ) { // This atom is part of a tree that needs to be denied, so we do two things: // 1- Add its atom to the list of denied atoms. if( HbsGetThisAtom( event, &atomId ) ) { addAtomToDeny( atomId ); } // 2- As this is a process, we deny by killing it. if( rSequence_getRU32( event, RP_TAGS_PROCESS_ID, &pid ) ) { if( processLib_killProcess( pid ) ) { rpal_debug_info( "denied process id " RF_U32, pid ); } else { rpal_debug_warning( "failed to deny process id " RF_U32, pid ); } } } else if( 0 != g_lastDenyActivity && g_lastDenyActivity + DENY_TREE_CLEANUP_TIMEOUT < rpal_time_getGlobal() ) { // There has not been any positive activity on any denied trees, for the sake // of performance we'll reset the denied trees. if( rMutex_lock( g_deniedMutex ) ) { g_lastDenyActivity = 0; rpal_blob_free( g_denied ); g_denied = rpal_blob_create( 0, HBS_ATOM_ID_SIZE * 10 ); rMutex_unlock( g_deniedMutex ); } } }
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 ); } } }
// Add an atom to the deny list, which is just a sortled list // on which we do binary searches. RPRIVATE RVOID addAtomToDeny ( RPU8 atomId ) { if( rMutex_lock( g_deniedMutex ) ) { rpal_blob_add( g_denied, atomId, HBS_ATOM_ID_SIZE ); rpal_sort_array( rpal_blob_getBuffer( g_denied ), rpal_blob_getSize( g_denied ) / HBS_ATOM_ID_SIZE, HBS_ATOM_ID_SIZE, (rpal_ordering_func)cmpAtoms ); g_lastDenyActivity = rpal_time_getGlobal(); rMutex_unlock( g_deniedMutex ); } }
static RVOID sendShutdownEvent ( ) { rList cloudMessages = NULL; rSequence wrapper = NULL; rSequence shutdownEvent = NULL; if( NULL != ( wrapper = rSequence_new() ) ) { if( NULL != ( shutdownEvent = rSequence_new() ) ) { if( rSequence_addSEQUENCE( wrapper, RP_TAGS_NOTIFICATION_SHUTTING_DOWN, shutdownEvent ) ) { if( rSequence_addTIMESTAMP( shutdownEvent, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() ) && rQueue_add( g_hbs_state.outQueue, wrapper, 0 ) ) { if( NULL != ( cloudMessages = beaconHome() ) ) { rList_free( cloudMessages ); } } else { rSequence_free( wrapper ); } } else { rSequence_free( wrapper ); rSequence_free( shutdownEvent ); } } else { rSequence_free( wrapper ); } } }
//============================================================================= // 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 ); } }
RPRIVATE RBOOL _init_profile_strw_strw ( _Profile* p, RPWCHAR key ) { RBOOL isSuccess = FALSE; RTIME now = 0; if( NULL != p ) { now = rpal_time_getGlobal(); p->firstSeen = now; p->lastSeen = now; p->gensSeen = 0; p->gensToStability = _PROFILE_BASE_CHANGE_TICKETS; if( NULL != ( p->key = rpal_string_strdupW( key ) ) ) { if( NULL != ( p->relations = rpal_btree_create( sizeof( RPVOID ), (rpal_btree_comp_f)_cmp_stringw, (rpal_btree_free_f)_clean_alloc ) ) ) { isSuccess = TRUE; } else { rpal_memory_free( p->key ); } } } return isSuccess; }
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 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 rList assembleRequest ( RPU8 optCrashCtx, RU32 optCrashCtxSize ) { rSequence req = NULL; RU32 moduleIndex = 0; rList msgList = NULL; rList modList = NULL; rSequence modEntry = NULL; if( NULL != ( req = rSequence_new() ) ) { // Add some basic info rSequence_addRU32( req, RP_TAGS_MEMORY_USAGE, rpal_memory_totalUsed() ); rSequence_addTIMESTAMP( req, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() ); // If we have a crash context to report if( NULL != optCrashCtx ) { if( !rSequence_addBUFFER( req, RP_TAGS_HCP_CRASH_CONTEXT, optCrashCtx, optCrashCtxSize ) ) { rpal_debug_error( "error adding crash context of size %d to hcp beacon", optCrashCtxSize ); } else { rpal_debug_info( "crash context is being bundled in hcp beacon" ); } } // List of loaded modules if( NULL != ( modList = rList_new( RP_TAGS_HCP_MODULE, RPCM_SEQUENCE ) ) ) { for( moduleIndex = 0; moduleIndex < RP_HCP_CONTEXT_MAX_MODULES; moduleIndex++ ) { if( NULL != g_hcpContext.modules[ moduleIndex ].hModule ) { if( NULL != ( modEntry = rSequence_new() ) ) { if( !rSequence_addBUFFER( modEntry, RP_TAGS_HASH, g_hcpContext.modules[ moduleIndex ].hash, sizeof( g_hcpContext.modules[ moduleIndex ].hash ) ) || !rSequence_addRU8( modEntry, RP_TAGS_HCP_MODULE_ID, g_hcpContext.modules[ moduleIndex ].id ) || !rList_addSEQUENCE( modList, modEntry ) ) { break; } // We take the opportunity to cleanup the list of modules... if( rpal_thread_wait( g_hcpContext.modules[ moduleIndex ].hThread, 0 ) ) { // This thread has exited, which is our signal that the module // has stopped executing... rEvent_free( g_hcpContext.modules[ moduleIndex ].isTimeToStop ); rpal_thread_free( g_hcpContext.modules[ moduleIndex ].hThread ); rpal_memory_zero( &(g_hcpContext.modules[ moduleIndex ]), sizeof( g_hcpContext.modules[ moduleIndex ] ) ); if( !rSequence_addRU8( modEntry, RP_TAGS_HCP_MODULE_TERMINATED, 1 ) ) { break; } } } } } if( !rSequence_addLIST( req, RP_TAGS_HCP_MODULES, modList ) ) { rList_free( modList ); } } if( NULL != ( msgList = rList_new( RP_TAGS_MESSAGE, RPCM_SEQUENCE ) ) ) { if( !rList_addSEQUENCE( msgList, req ) ) { rList_free( msgList ); rSequence_free( req ); msgList = NULL; } } else { rSequence_free( req ); } } return msgList; }
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 ); } } }