void test_handles ( void ) { rList handles = NULL; rSequence handle = NULL; RU32 nHandles = 0; RU32 nNamedHandles = 0; RPWCHAR handleName = NULL; handles = processLib_getHandles( 0, FALSE, NULL ); CU_ASSERT_PTR_NOT_EQUAL_FATAL( handles, NULL ); while( rList_getSEQUENCE( handles, RP_TAGS_HANDLE_INFO, &handle ) ) { nHandles++; } CU_ASSERT_TRUE( 100 < nHandles ); rList_free( handles ); handles = processLib_getHandles( 0, TRUE, NULL ); CU_ASSERT_PTR_NOT_EQUAL_FATAL( handles, NULL ); while( rList_getSEQUENCE( handles, RP_TAGS_HANDLE_INFO, &handle ) ) { nNamedHandles++; CU_ASSERT_TRUE( rSequence_getSTRINGW( handle, RP_TAGS_HANDLE_NAME, &handleName ) ); CU_ASSERT_TRUE( 0 != rpal_string_strlenw( handleName ) ); } CU_ASSERT_TRUE( nNamedHandles < nHandles ); rList_free( handles ); }
static RBOOL _reportEvents ( StatefulMachine* machine ) { RBOOL isSuccess = FALSE; rSequence wrapper = NULL; rList events = NULL; rSequence event = NULL; RU32 i = 0; if( NULL != machine ) { if( NULL != ( wrapper = rSequence_new() ) ) { if( NULL != ( events = rList_new( RP_TAGS_EVENT, RPCM_SEQUENCE ) ) ) { for( i = 0; i < machine->history->nElements; i++ ) { event = ( (StatefulEvent*)machine->history->elements[ i ] )->data; rList_addSEQUENCE( events, rSequence_duplicate( event ) ); } if( !rSequence_addLIST( wrapper, RP_TAGS_EVENTS, events ) ) { rList_free( events ); } else { hbs_timestampEvent( wrapper, 0 ); isSuccess = hbs_publish( machine->desc->reportEventType, wrapper ); } } rSequence_free( wrapper ); } } return isSuccess; }
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 ); } } }
RPRIVATE RVOID mem_handles ( rpcm_tag eventType, rSequence event ) { RU32 pid; rList handleList; RPU8 atom = NULL; RU32 atomSize = 0; UNREFERENCED_PARAMETER( eventType ); if( rpal_memory_isValid( event ) ) { if( rSequence_getRU32( event, RP_TAGS_PROCESS_ID, &pid ) || ( rSequence_getBUFFER( event, RP_TAGS_HBS_THIS_ATOM, &atom, &atomSize ) && HBS_ATOM_ID_SIZE == atomSize && 0 != ( pid = atoms_getPid( atom ) ) ) ) { if( NULL != ( handleList = processLib_getHandles( pid, TRUE, NULL ) ) ) { if( !rSequence_addLIST( event, RP_TAGS_HANDLES, handleList ) ) { rList_free( handleList ); } } else { rSequence_addRU32( event, RP_TAGS_ERROR, rpal_error_getLast() ); } } hbs_timestampEvent( event, 0 ); hbs_publish( RP_TAGS_NOTIFICATION_MEM_HANDLES_REP, event ); } }
RPRIVATE RVOID mem_find_handle ( rpcm_tag eventType, rSequence event ) { RPNCHAR needle = NULL; rList handleList; UNREFERENCED_PARAMETER( eventType ); if( rpal_memory_isValid( event ) ) { if( rSequence_getSTRINGN( event, RP_TAGS_HANDLE_NAME, &needle ) ) { rSequence_unTaintRead( event ); if( NULL != ( handleList = processLib_getHandles( 0, TRUE, needle ) ) ) { if( !rSequence_addLIST( event, RP_TAGS_HANDLES, handleList ) ) { rList_free( handleList ); } } else { rSequence_addRU32( event, RP_TAGS_ERROR, rpal_error_getLast() ); rpal_debug_error( "failed to get handles for pid 0x%x.", 0 ); } } hbs_timestampEvent( event, 0 ); hbs_publish( RP_TAGS_NOTIFICATION_MEM_FIND_HANDLE_REP, event ); } }
static RVOID scan_for_hollowing ( rpcm_tag eventType, rSequence event ) { RU32 pid = (RU32)( -1 ); rEvent dummy = NULL; rList hollowedModules = NULL; rSequence process = NULL; LibOsPerformanceProfile perfProfile = { 0 }; Atom parentAtom = { 0 }; UNREFERENCED_PARAMETER( eventType ); if( NULL != ( dummy = rEvent_create( TRUE ) ) ) { perfProfile.targetCpuPerformance = 10; perfProfile.globalTargetCpuPerformance = GLOBAL_CPU_USAGE_TARGET_WHEN_TASKED; perfProfile.timeoutIncrementPerSec = _PROFILE_INCREMENT; perfProfile.enforceOnceIn = 7; perfProfile.lastTimeoutValue = _INITIAL_PROFILED_TIMEOUT; perfProfile.sanityCeiling = _SANITY_CEILING; if( rSequence_getRU32( event, RP_TAGS_PROCESS_ID, &pid ) ) { if( NULL != ( process = processLib_getProcessInfo( pid, NULL ) ) || ( NULL != ( process = rSequence_new() ) && rSequence_addRU32( process, RP_TAGS_PROCESS_ID, pid ) ) ) { if( NULL != ( hollowedModules = _spotCheckProcess( dummy, pid, &perfProfile ) ) ) { if( !rSequence_addLIST( process, RP_TAGS_MODULES, hollowedModules ) ) { rList_free( hollowedModules ); } else { parentAtom.key.category = RP_TAGS_NOTIFICATION_NEW_PROCESS; parentAtom.key.process.pid = pid; if( atoms_query( &parentAtom, 0 ) ) { HbsSetParentAtom( process, parentAtom.id ); } hbs_publish( RP_TAGS_NOTIFICATION_MODULE_MEM_DISK_MISMATCH, process ); } } } if( rpal_memory_isValid( process ) ) { rSequence_free( process ); } } rEvent_free( dummy ); } }
static RPVOID spotCheckNewProcesses ( rEvent isTimeToStop, RPVOID ctx ) { RU32 pid = 0; RTIME timestamp = 0; RTIME timeToWait = 0; RTIME now = 0; rSequence newProcess = NULL; rList hollowedModules = NULL; LibOsPerformanceProfile perfProfile = { 0 }; UNREFERENCED_PARAMETER( ctx ); perfProfile.sanityCeiling = _SANITY_CEILING; perfProfile.lastTimeoutValue = _INITIAL_PROFILED_TIMEOUT; perfProfile.targetCpuPerformance = 0; perfProfile.globalTargetCpuPerformance = GLOBAL_CPU_USAGE_TARGET; perfProfile.enforceOnceIn = 7; perfProfile.timeoutIncrementPerSec = _PROFILE_INCREMENT; while( !rEvent_wait( isTimeToStop, 0 ) ) { if( rQueue_remove( g_newProcessNotifications, &newProcess, NULL, MSEC_FROM_SEC( 5 ) ) ) { if( rSequence_getRU32( newProcess, RP_TAGS_PROCESS_ID, &pid ) && rSequence_getTIMESTAMP( newProcess, RP_TAGS_TIMESTAMP, ×tamp ) ) { timeToWait = timestamp + _CHECK_SEC_AFTER_PROCESS_CREATION; now = rpal_time_getGlobalPreciseTime(); if( now < timeToWait ) { timeToWait = timeToWait - now; if( _CHECK_SEC_AFTER_PROCESS_CREATION < timeToWait ) { // Sanity check timeToWait = _CHECK_SEC_AFTER_PROCESS_CREATION; } rpal_thread_sleep( (RU32)timeToWait ); } if( NULL != ( hollowedModules = _spotCheckProcess( isTimeToStop, pid, &perfProfile ) ) ) { if( !rSequence_addLIST( newProcess, RP_TAGS_MODULES, hollowedModules ) ) { rList_free( hollowedModules ); } else { hbs_publish( RP_TAGS_NOTIFICATION_MODULE_MEM_DISK_MISMATCH, newProcess ); } } } rSequence_free( newProcess ); } } return NULL; }
static RPVOID spotCheckProcessConstantly ( rEvent isTimeToStop, RPVOID ctx ) { rSequence originalRequest = (rSequence)ctx; processLibProcEntry* procs = NULL; processLibProcEntry* proc = NULL; rList hollowedModules = NULL; rSequence processInfo = NULL; LibOsPerformanceProfile perfProfile = { 0 }; Atom parentAtom = { 0 }; perfProfile.targetCpuPerformance = 0; perfProfile.globalTargetCpuPerformance = GLOBAL_CPU_USAGE_TARGET; perfProfile.timeoutIncrementPerSec = _PROFILE_INCREMENT; perfProfile.enforceOnceIn = 1; perfProfile.lastTimeoutValue = _INITIAL_PROFILED_TIMEOUT; perfProfile.sanityCeiling = _SANITY_CEILING; while( rpal_memory_isValid( isTimeToStop ) && !rEvent_wait( isTimeToStop, 0 ) ) { libOs_timeoutWithProfile( &perfProfile, FALSE, isTimeToStop ); if( NULL != ( procs = processLib_getProcessEntries( TRUE ) ) ) { proc = procs; while( 0 != proc->pid && rpal_memory_isValid( isTimeToStop ) && !rEvent_wait( isTimeToStop, 0 ) ) { libOs_timeoutWithProfile( &perfProfile, TRUE, isTimeToStop ); if( NULL != ( hollowedModules = _spotCheckProcess( isTimeToStop, proc->pid, &perfProfile ) ) ) { if( NULL != ( processInfo = processLib_getProcessInfo( proc->pid, NULL ) ) || ( NULL != ( processInfo = rSequence_new() ) && rSequence_addRU32( processInfo, RP_TAGS_PROCESS_ID, proc->pid ) ) ) { if( !rSequence_addLIST( processInfo, RP_TAGS_MODULES, hollowedModules ) ) { rList_free( hollowedModules ); } else { parentAtom.key.category = RP_TAGS_NOTIFICATION_NEW_PROCESS; parentAtom.key.process.pid = proc->pid; if( atoms_query( &parentAtom, 0 ) ) { HbsSetParentAtom( processInfo, parentAtom.id ); } hbs_markAsRelated( originalRequest, processInfo ); hbs_publish( RP_TAGS_NOTIFICATION_MODULE_MEM_DISK_MISMATCH, processInfo ); } rSequence_free( processInfo ); } else { rList_free( hollowedModules ); } } proc++; } rpal_memory_free( procs ); } } return NULL; }
static rList _spotCheckProcess ( rEvent isTimeToStop, RU32 pid, LibOsPerformanceProfile* perfProfile ) { rList hollowedModules = NULL; rList modules = NULL; rSequence module = NULL; RPNCHAR modulePath = NULL; RU32 fileSize = 0; RU64 moduleBase = 0; RU64 moduleSize = 0; HObs diskSample = NULL; rSequence hollowedModule = NULL; RU32 lastScratchIndex = 0; RU32 nSamplesFound = 0; RU32 nSamplesTotal = 0; RU32 tmpSamplesFound = 0; RU32 tmpSamplesSize = 0; RTIME runTime = 0; rpal_debug_info( "spot checking process %d", pid ); if( NULL != ( modules = processLib_getProcessModules( pid ) ) ) { while( !rEvent_wait( isTimeToStop, 0 ) && rList_getSEQUENCE( modules, RP_TAGS_DLL, &module ) ) { libOs_timeoutWithProfile( perfProfile, FALSE, isTimeToStop ); runTime = rpal_time_getLocal(); modulePath = NULL; lastScratchIndex = 0; if( ( rSequence_getSTRINGN( module, RP_TAGS_FILE_PATH, &modulePath ) ) && rSequence_getPOINTER64( module, RP_TAGS_BASE_ADDRESS, &moduleBase ) && rSequence_getRU64( module, RP_TAGS_MEMORY_SIZE, &moduleSize ) ) { if( 0 != ( fileSize = rpal_file_getSize( modulePath, TRUE ) ) ) { nSamplesFound = 0; nSamplesTotal = 0; tmpSamplesFound = (RU32)( -1 ); while( !rEvent_wait( isTimeToStop, 0 ) && NULL != ( diskSample = _getModuleDiskStringSample( modulePath, &lastScratchIndex, isTimeToStop, perfProfile ) ) ) { libOs_timeoutWithProfile( perfProfile, TRUE, isTimeToStop ); tmpSamplesSize = obsLib_getNumPatterns( diskSample ); if( 0 != tmpSamplesSize ) { tmpSamplesFound = _checkMemoryForStringSample( diskSample, pid, NUMBER_TO_PTR( moduleBase ), moduleSize, isTimeToStop, perfProfile ); obsLib_free( diskSample ); if( (RU32)( -1 ) == tmpSamplesFound ) { break; } nSamplesFound += tmpSamplesFound; nSamplesTotal += tmpSamplesSize; if( _MIN_DISK_SAMPLE_SIZE <= nSamplesTotal && ( _MIN_SAMPLE_MATCH_PERCENT < ( (RFLOAT)nSamplesFound / nSamplesTotal ) * 100 ) && _MIN_DISK_BIN_COVERAGE_PERCENT <= (RFLOAT)( ( lastScratchIndex * _SCRATCH_SIZE ) / fileSize ) * 100 ) { break; } } else { obsLib_free( diskSample ); } } } else { rpal_debug_info( "could not get file information, not checking" ); } rpal_debug_info( "process hollowing check found a match in %d ( %d / %d ) from %d passes in %d sec", pid, nSamplesFound, nSamplesTotal, lastScratchIndex, rpal_time_getLocal() - runTime ); if( !rEvent_wait( isTimeToStop, 0 ) && (RU32)(-1) != tmpSamplesFound && _MIN_DISK_SAMPLE_SIZE <= nSamplesTotal && ( ( (RFLOAT)nSamplesFound / nSamplesTotal ) * 100 ) < _MIN_SAMPLE_MATCH_PERCENT ) { rpal_debug_info( "sign of process hollowing found in process %d", pid ); if( NULL != ( hollowedModule = rSequence_duplicate( module ) ) ) { if( !rList_addSEQUENCE( hollowedModules, hollowedModule ) ) { rSequence_free( hollowedModule ); } } } } else { rpal_debug_info( "module missing characteristic" ); } } rList_free( modules ); } else { rpal_debug_info( "failed to get process modules, might be dead" ); } return hollowedModules; }
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; }
RPRIVATE rSequence _findStringsInProcess ( RU32 pid, rList searchStrings, RU32 minLength, RU32 maxLength ) { rSequence info = NULL; rList memMapList = NULL; rSequence region = NULL; RU64 memBase = 0; RU64 memSize = 0; RPU8 pRegion = NULL; rList stringsFound = NULL; if( NULL != searchStrings ) { if( NULL != ( info = rSequence_new() ) ) { rSequence_addRU32( info, RP_TAGS_PROCESS_ID, pid ); if( NULL != ( memMapList = processLib_getProcessMemoryMap( pid ) ) && ( NULL != ( stringsFound = rList_new( RP_TAGS_STRINGSW, RPCM_SEQUENCE ) ) ) ) { while( rList_getSEQUENCE( memMapList, RP_TAGS_MEMORY_REGION, ®ion ) ) { if( rSequence_getPOINTER64( region, RP_TAGS_BASE_ADDRESS, &memBase ) && rSequence_getRU64( region, RP_TAGS_MEMORY_SIZE, &memSize ) ) { if( processLib_getProcessMemory( pid, (RPVOID)rpal_ULongToPtr( memBase ), memSize, (RPVOID*)&pRegion, TRUE ) ) { // now search for strings inside this region _searchForStrings( stringsFound, searchStrings, pRegion, memSize, memBase, minLength, maxLength); rpal_memory_free( pRegion ); } } } if( !rSequence_addLIST( info, RP_TAGS_STRINGS_FOUND, stringsFound ) ) { rList_free( stringsFound ); } } else { rSequence_addRU32( info, RP_TAGS_ERROR, rpal_error_getLast() ); } if( NULL != memMapList ) { rList_free( memMapList ); } } } return info; }
//============================================================================= // Entry Point //============================================================================= RU32 RPAL_THREAD_FUNC RpHcpI_mainThread ( rEvent isTimeToStop ) { RU32 ret = 0; RU64 nextBeaconTime = 0; rList cloudMessages = NULL; rSequence msg = NULL; rList newConfigurations = NULL; rList newNotifications = NULL; RPU8 newConfigurationHash = NULL; RU32 newHashSize = 0; rSequence staticConfig = NULL; RU8* tmpBuffer = NULL; RU32 tmpSize = 0; FORCE_LINK_THAT( HCP_IFACE ); CryptoLib_init(); getPrivileges(); // This is the event for the collectors, it is different than the // hbs proper event so that we can restart the collectors without // signaling hbs as a whole. if( NULL == ( g_hbs_state.isTimeToStop = rEvent_create( TRUE ) ) ) { return (RU32)-1; } // By default, no collectors are running rEvent_set( g_hbs_state.isTimeToStop ); // We attempt to load some initial config from the serialized // rSequence that can be patched in this binary. if( NULL != ( staticConfig = getStaticConfig() ) ) { if( rSequence_getBUFFER( staticConfig, RP_TAGS_HBS_ROOT_PUBLIC_KEY, &tmpBuffer, &tmpSize ) ) { hbs_cloud_pub_key = rpal_memory_duplicate( tmpBuffer, tmpSize ); if( NULL == hbs_cloud_pub_key ) { hbs_cloud_pub_key = hbs_cloud_default_pub_key; } rpal_debug_info( "loading hbs root public key from static config" ); } if( rSequence_getRU32( staticConfig, RP_TAGS_MAX_QUEUE_SIZE, &g_hbs_state.maxQueueNum ) ) { rpal_debug_info( "loading max queue size from static config" ); } else { g_hbs_state.maxQueueNum = HBS_EXFIL_QUEUE_MAX_NUM; } if( rSequence_getRU32( staticConfig, RP_TAGS_MAX_SIZE, &g_hbs_state.maxQueueSize ) ) { rpal_debug_info( "loading max queue num from static config" ); } else { g_hbs_state.maxQueueSize = HBS_EXFIL_QUEUE_MAX_SIZE; } rSequence_free( staticConfig ); } else { hbs_cloud_pub_key = hbs_cloud_default_pub_key; g_hbs_state.maxQueueNum = HBS_EXFIL_QUEUE_MAX_NUM; g_hbs_state.maxQueueSize = HBS_EXFIL_QUEUE_MAX_SIZE; } if( !rQueue_create( &g_hbs_state.outQueue, freeExfilEvent, g_hbs_state.maxQueueNum ) ) { rEvent_free( g_hbs_state.isTimeToStop ); return (RU32)-1; } // We simply enqueue a message to let the cloud know we're starting sendStartupEvent(); while( !rEvent_wait( isTimeToStop, (RU32)nextBeaconTime ) ) { nextBeaconTime = MSEC_FROM_SEC( HBS_DEFAULT_BEACON_TIMEOUT + ( rpal_rand() % HBS_DEFAULT_BEACON_TIMEOUT_FUZZ ) ); if( NULL != ( cloudMessages = beaconHome() ) ) { while( rList_getSEQUENCE( cloudMessages, RP_TAGS_MESSAGE, &msg ) ) { // Cloud message indicating next requested beacon time, as a Seconds delta if( rSequence_getTIMEDELTA( msg, RP_TAGS_TIMEDELTA, &nextBeaconTime ) ) { nextBeaconTime = MSEC_FROM_SEC( nextBeaconTime ); rpal_debug_info( "received set_next_beacon" ); } if( NULL == newConfigurations && rSequence_getLIST( msg, RP_TAGS_HBS_CONFIGURATIONS, &newConfigurations ) ) { rpal_debug_info( "received a new profile" ); if( rSequence_getBUFFER( msg, RP_TAGS_HASH, &newConfigurationHash, &newHashSize ) && newHashSize == CRYPTOLIB_HASH_SIZE ) { newConfigurations = rList_duplicate( newConfigurations ); rpal_memory_memcpy( &( g_hbs_state.currentConfigHash ), newConfigurationHash, CRYPTOLIB_HASH_SIZE ); g_hbs_state.isProfilePresent = TRUE; } else { newConfigurations = NULL; rpal_debug_error( "profile hash received is invalid" ); } } if( NULL == newNotifications && rSequence_getLIST( msg, RP_TAGS_HBS_CLOUD_NOTIFICATIONS, &newNotifications ) ) { rpal_debug_info( "received cloud events" ); newNotifications = rList_duplicate( newNotifications ); } } rList_free( cloudMessages ); } // If this is the initial boot and we have no profile yet, we'll load a dummy // blank profile and use our defaults. if( NULL == newConfigurations && !g_hbs_state.isProfilePresent && !rEvent_wait( isTimeToStop, 0 ) ) { newConfigurations = rList_new( RP_TAGS_HCP_MODULES, RPCM_SEQUENCE ); rpal_debug_info( "setting empty profile" ); } if( NULL != newConfigurations ) { // We try to be as responsive as possible when asked to quit // so if we happen to have received the signal during a beacon // we will action the quit instead of the config change. if( !rEvent_wait( isTimeToStop, 0 ) ) { rpal_debug_info( "begining sensor update on new profile" ); shutdownCollectors(); updateCollectorConfigs( newConfigurations ); rList_free( newConfigurations ); newConfigurations = NULL; startCollectors(); } else { rList_free( newConfigurations ); } newConfigurations = NULL; } if( NULL != newNotifications ) { if( !rEvent_wait( isTimeToStop, 0 ) ) { publishCloudNotifications( newNotifications ); } rList_free( newNotifications ); newNotifications = NULL; } } // We issue one last beacon indicating we are stopping sendShutdownEvent(); // Shutdown everything shutdownCollectors(); // Cleanup the last few resources rEvent_free( g_hbs_state.isTimeToStop ); rQueue_free( g_hbs_state.outQueue ); CryptoLib_deinit(); if( hbs_cloud_default_pub_key != hbs_cloud_pub_key && NULL != hbs_cloud_pub_key ) { rpal_memory_free( hbs_cloud_pub_key ); hbs_cloud_pub_key = NULL; } return ret; }
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 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; }
RPRIVATE RVOID mem_find_string ( rpcm_tag eventType, rSequence event ) { RU32 pid = 0; RU32 currentPid = 0; rList searchStrings = NULL; rList processes = NULL; rSequence process = NULL; processLibProcEntry* pids = NULL; RU32 nCurrent = 0; RU32 minLength = 5; RU32 maxLength = 128; RPU8 atom = NULL; RU32 atomSize = 0; UNREFERENCED_PARAMETER( eventType ); if( rpal_memory_isValid( event ) ) { if( ( rSequence_getRU32( event, RP_TAGS_PROCESS_ID, &pid ) || ( rSequence_getBUFFER( event, RP_TAGS_HBS_THIS_ATOM, &atom, &atomSize ) && HBS_ATOM_ID_SIZE == atomSize && 0 != ( pid = atoms_getPid( atom ) ) ) ) && rSequence_getLIST( event, RP_TAGS_STRINGSW, &searchStrings ) ) { currentPid = processLib_getCurrentPid(); if( NULL != ( processes = rList_new( RP_TAGS_PROCESS, RPCM_SEQUENCE ) ) ) { if( 0 != pid ) { if( NULL != ( process = _findStringsInProcess( pid, searchStrings, minLength, maxLength ) ) ) { if( !rList_addSEQUENCE( processes, process ) ) { rSequence_free( process ); } } } else { if( NULL != ( pids = processLib_getProcessEntries( TRUE ) ) ) { while( 0 != pids[ nCurrent ].pid ) { if( currentPid != pids[ nCurrent ].pid ) { if( NULL != ( process = _findStringsInProcess( pids[ nCurrent ].pid, searchStrings, minLength, maxLength ) ) ) { if( !rList_addSEQUENCE( processes, process ) ) { rSequence_free( process ); } } } nCurrent++; } rpal_memory_free( pids ); } } if( !rSequence_addLIST( event, RP_TAGS_PROCESSES, processes ) ) { rList_free( processes ); } } } hbs_timestampEvent( event, 0 ); hbs_publish( RP_TAGS_NOTIFICATION_MEM_FIND_STRING_REP, event ); } }
RPRIVATE RVOID mem_strings ( rpcm_tag eventType, rSequence event ) { RU32 pid = 0; rList memMapList = NULL; rSequence region = NULL; RU64 memBase = 0; RU64 memSize = 0; RPU8 pRegion = NULL; rList stringsAList = NULL; rList stringsWList = NULL; RU32 minLength = 5; RU32 maxLength = 128; RPU8 atom = NULL; RU32 atomSize = 0; UNREFERENCED_PARAMETER( eventType ); if( rpal_memory_isValid( event ) ) { if( rSequence_getRU32( event, RP_TAGS_PROCESS_ID, &pid ) || ( rSequence_getBUFFER( event, RP_TAGS_HBS_THIS_ATOM, &atom, &atomSize ) && HBS_ATOM_ID_SIZE == atomSize && 0 != ( pid = atoms_getPid( atom ) ) ) ) { if( NULL != ( memMapList = processLib_getProcessMemoryMap( pid ) ) && ( NULL != ( stringsAList = rList_new( RP_TAGS_STRINGSA, RPCM_STRINGA ) ) ) && ( NULL != ( stringsWList = rList_new( RP_TAGS_STRINGSW, RPCM_STRINGW ) ) ) ) { while( rList_getSEQUENCE( memMapList, RP_TAGS_MEMORY_REGION, ®ion ) ) { if( rSequence_getPOINTER64( region, RP_TAGS_BASE_ADDRESS, &memBase ) && rSequence_getRU64( region, RP_TAGS_MEMORY_SIZE, &memSize ) ) { if( processLib_getProcessMemory( pid, (RPVOID)rpal_ULongToPtr( memBase ), memSize, (RPVOID*)&pRegion, TRUE ) ) { // now search for strings inside this region _getStringsList( stringsAList, stringsWList, pRegion, memSize, minLength, maxLength ); rpal_memory_free( pRegion ); } } } if( !rSequence_addLIST( event, RP_TAGS_STRINGSA, stringsAList ) ) { rList_free( stringsAList ); } if( !rSequence_addLIST( event, RP_TAGS_STRINGSW, stringsWList ) ) { rList_free( stringsWList ); } } else { rSequence_addRU32( event, RP_TAGS_ERROR, rpal_error_getLast() ); } if( NULL != memMapList ) { rList_free( memMapList ); } } hbs_timestampEvent( event, 0 ); hbs_publish( RP_TAGS_NOTIFICATION_MEM_STRINGS_REP, event ); } }
static rList beaconHome ( ) { rList response = NULL; rList exfil = NULL; rSequence msg = NULL; RU32 nExfilMsg = 0; rSequence tmpMessage = NULL; if( NULL != ( exfil = rList_new( RP_TAGS_MESSAGE, RPCM_SEQUENCE ) ) ) { if( NULL != ( msg = rSequence_new() ) ) { if( rSequence_addBUFFER( msg, RP_TAGS_HASH, g_hbs_state.currentConfigHash, CRYPTOLIB_HASH_SIZE ) ) { if( !rList_addSEQUENCE( exfil, msg ) ) { rSequence_free( msg ); msg = NULL; } tmpMessage = msg; } else { rSequence_free( msg ); msg = NULL; } } while( rQueue_remove( g_hbs_state.outQueue, &msg, NULL, 0 ) ) { nExfilMsg++; if( !rList_addSEQUENCE( exfil, msg ) ) { rSequence_free( msg ); } } rpal_debug_info( "%d messages ready for exfil.", nExfilMsg ); if( rpHcpI_beaconHome( exfil, &response ) ) { rpal_debug_info( "%d messages received from cloud.", rList_getNumElements( response ) ); } else if( g_hbs_state.maxQueueSize > rList_getEstimateSize( exfil ) ) { rpal_debug_info( "beacon failed, re-adding %d messages.", rList_getNumElements( exfil ) ); // We will attempt to re-add the existing messages back in the queue since this failed rList_resetIterator( exfil ); while( rList_getSEQUENCE( exfil, RP_TAGS_MESSAGE, &msg ) ) { // Ignore message we generate temporarily for the beacon if( tmpMessage == msg ) { rSequence_free( msg ); continue; } if( !rQueue_add( g_hbs_state.outQueue, msg, 0 ) ) { rSequence_free( msg ); } } rList_shallowFree( exfil ); exfil = NULL; } else { rpal_debug_warning( "beacon failed but discarded exfil because of its size." ); } if( NULL != exfil ) { rList_free( exfil ); } } return response; }
static RU32 _scanProcessWith ( RU32 pid, YaraMatchContext* matchContext, YR_RULES* rules, rEvent isTimeToStop ) { RU32 scanError = (RU32)(-1); rList modules = NULL; rSequence module = NULL; _MemRange* memRanges = NULL; RU32 i = 0; rList memoryMap = NULL; rSequence memoryRegion = NULL; RU8 memAccess = 0; RU64 mem = 0; RU64 memSize = 0; RPU8 buffer = NULL; // First pass is to scan known modules if( NULL != ( modules = processLib_getProcessModules( pid ) ) ) { rpal_debug_info( "scanning process %d module memory with yara", pid ); // We also generate an optimized list of module ranges for later if( NULL != ( memRanges = rpal_memory_alloc( sizeof( _MemRange ) * rList_getNumElements( modules ) ) ) ) { while( ( NULL == isTimeToStop || !rEvent_wait( isTimeToStop, MSEC_FROM_SEC( 5 ) ) ) && rList_getSEQUENCE( modules, RP_TAGS_DLL, &module ) ) { if( rSequence_getPOINTER64( module, RP_TAGS_BASE_ADDRESS, &mem ) && rSequence_getRU64( module, RP_TAGS_MEMORY_SIZE, &memSize ) ) { memRanges[ i ].base = mem; memRanges[ i ].size = memSize; i++; matchContext->regionBase = mem; matchContext->regionSize = memSize; matchContext->moduleInfo = module; if( processLib_getProcessMemory( pid, (RPVOID)NUMBER_TO_PTR( mem ), memSize, (RPVOID*)&buffer, TRUE ) ) { rpal_debug_info( "yara scanning module region of size 0x%lx", memSize ); if( NULL != rules || rMutex_lock( g_global_rules_mutex ) ) { if( ERROR_SUCCESS != ( scanError = yr_rules_scan_mem( NULL == rules ? g_global_rules : rules, buffer, (size_t)memSize, SCAN_FLAGS_FAST_MODE | SCAN_FLAGS_PROCESS_MEMORY, _yaraMemMatchCallback, matchContext, 60 ) ) ) { rpal_debug_warning( "Yara module scan error: %d 0x%lx 0x%lx: %d", pid, mem, memSize, scanError ); } if( NULL == rules ) { rMutex_unlock( g_global_rules_mutex ); } } rpal_memory_free( buffer ); rpal_debug_info( "finished region" ); } } } } rList_free( modules ); } // Optimize the memory ranges if( rpal_memory_isValid( memRanges ) && !rpal_sort_array( memRanges, i, sizeof( _MemRange ), (rpal_ordering_func)rpal_order_RU64 ) ) { rpal_memory_free( memRanges ); memRanges = NULL; } // Second pass is to go through executable non-module areas if( NULL != ( memoryMap = processLib_getProcessMemoryMap( pid ) ) ) { rpal_debug_info( "scanning process %d non-module memory with yara", pid ); while( ( NULL == isTimeToStop || !rEvent_wait(isTimeToStop, MSEC_FROM_SEC( 5 ) ) ) && rList_getSEQUENCE( memoryMap, RP_TAGS_MEMORY_REGION, &memoryRegion ) ) { if( rSequence_getPOINTER64( memoryRegion, RP_TAGS_BASE_ADDRESS, &mem ) && rSequence_getRU64( memoryRegion, RP_TAGS_MEMORY_SIZE, &memSize ) && rSequence_getRU8( memoryRegion, RP_TAGS_MEMORY_ACCESS, &memAccess ) && ( PROCESSLIB_MEM_ACCESS_EXECUTE == memAccess || PROCESSLIB_MEM_ACCESS_EXECUTE_READ == memAccess || PROCESSLIB_MEM_ACCESS_EXECUTE_READ_WRITE == memAccess || PROCESSLIB_MEM_ACCESS_EXECUTE_WRITE_COPY == memAccess ) ) { // If it's in a known module, skip if( (RU32)( -1 ) != rpal_binsearch_array_closest( memRanges, i, sizeof( _MemRange ), &mem, (rpal_ordering_func)rpal_order_RU64, TRUE ) ) { continue; } matchContext->regionBase = mem; matchContext->regionSize = memSize; matchContext->moduleInfo = NULL; if( processLib_getProcessMemory( pid, (RPVOID)NUMBER_TO_PTR(mem), memSize, (RPVOID*)&buffer, TRUE ) ) { rpal_debug_info( "yara scanning memory region of size 0x%lx", memSize ); if( NULL != rules || rMutex_lock( g_global_rules_mutex ) ) { if( ERROR_SUCCESS != ( scanError = yr_rules_scan_mem( NULL == rules ? g_global_rules : rules, buffer, (size_t)memSize, SCAN_FLAGS_FAST_MODE | SCAN_FLAGS_PROCESS_MEMORY, _yaraMemMatchCallback, matchContext, 60 ) ) ) { rpal_debug_warning( "Yara memory scan error: %d 0x%lx 0x%lx: %d", pid, mem, memSize, scanError ); } if( NULL == rules ) { rMutex_unlock( g_global_rules_mutex ); } } rpal_memory_free( buffer ); } } } rList_free( memoryMap ); } if( rpal_memory_isValid( memRanges ) ) { rpal_memory_free( memRanges ); } return scanError; }
//============================================================================= // PROFILERS //============================================================================= RPRIVATE RBOOL profile_processes ( ) { RBOOL isSuccess = FALSE; processLibProcEntry* processes = NULL; processLibProcEntry* process = NULL; rSequence processInfo = NULL; RPWCHAR processName = NULL; rList modules = NULL; rSequence module = NULL; RPWCHAR moduleName = NULL; _Profile profile = { 0 }; RBOOL isProfileReady = FALSE; RBOOL isChanged = FALSE; if( NULL != ( processes = processLib_getProcessEntries( FALSE ) ) ) { process = processes; while( 0 != process->pid ) { if( NULL != ( processInfo = processLib_getProcessInfo( process->pid, NULL ) ) ) { if( rSequence_getSTRINGW( processInfo, RP_TAGS_FILE_PATH, &processName ) ) { isProfileReady = FALSE; if( rpal_btree_search( g_profiles_process_module, &processName, &profile, FALSE ) ) { isProfileReady = TRUE; } else { if( _init_profile_strw_strw( g_profiles_process_module, processName ) ) { if( rpal_btree_add( g_profiles_process_module, &profile, FALSE ) ) { isProfileReady = TRUE; } else { _clean_profile( &profile ); } } } if( isProfileReady ) { if( NULL != ( modules = processLib_getProcessModules( process->pid ) ) ) { while( rList_getSEQUENCE( modules, RP_TAGS_DLL, &module ) ) { if( rSequence_getSTRINGW( module, RP_TAGS_FILE_PATH, &moduleName ) ) { if( !rpal_btree_search( profile.relations, &moduleName, NULL, FALSE ) && rpal_btree_add( profile.relations, &moduleName, FALSE ) ) { isChanged = TRUE; if( _isProfileStable( &profile ) ) { rpal_debug_info( "Stable profile change!" ); } } } } rList_free( modules ); } if( _recordGeneration( &profile, isChanged ) ) { rpal_btree_update( g_profiles_process_module, &profile, &profile, FALSE ); } } } rSequence_free( processInfo ); } process++; } rpal_memory_free( processes ); } return isSuccess; }
RPRIVATE RVOID mem_map ( rpcm_tag eventType, rSequence event ) { RU32 pid; rList memMapList = NULL; rList modulesList = NULL; rSequence modEntry = NULL; rSequence memEntry = NULL; RPNCHAR tmpModName = NULL; RPNCHAR tmpModPath = NULL; RU64 memStart = 0; RU64 memSize = 0; RU64 modStart = 0; RU64 modSize = 0; RPU8 atom = NULL; RU32 atomSize = 0; UNREFERENCED_PARAMETER( eventType ); if( rpal_memory_isValid( event ) ) { if( rSequence_getRU32( event, RP_TAGS_PROCESS_ID, &pid ) || ( rSequence_getBUFFER( event, RP_TAGS_HBS_THIS_ATOM, &atom, &atomSize ) && HBS_ATOM_ID_SIZE == atomSize && 0 != ( pid = atoms_getPid( atom ) ) ) ) { if( NULL != ( memMapList = processLib_getProcessMemoryMap( pid ) ) ) { // Try to enhance the raw map if( NULL != ( modulesList = processLib_getProcessModules( pid ) ) ) { // Looking for memory pages within the known module rList_resetIterator( memMapList ); while( rList_getSEQUENCE( memMapList, RP_TAGS_MEMORY_REGION, &memEntry ) ) { if( rSequence_getPOINTER64( memEntry, RP_TAGS_BASE_ADDRESS, &memStart ) && rSequence_getRU64( memEntry, RP_TAGS_MEMORY_SIZE, &memSize ) ) { tmpModName = NULL; tmpModPath = NULL; rList_resetIterator( modulesList ); while( rList_getSEQUENCE( modulesList, RP_TAGS_DLL, &modEntry ) ) { if( rSequence_getPOINTER64( modEntry, RP_TAGS_BASE_ADDRESS, &modStart ) && rSequence_getRU64( modEntry, RP_TAGS_MEMORY_SIZE, &modSize ) ) { if( memStart >= modStart && memStart <= ( modStart + modSize ) ) { // Match, we get just the basic info rSequence_getSTRINGN( modEntry, RP_TAGS_MODULE_NAME, &tmpModName ); rSequence_getSTRINGN( modEntry, RP_TAGS_FILE_PATH, &tmpModPath ); break; } } else { break; } } // I can assert that the strings read from the memEntry WILL NOT be used // hereon since doing so would be dangerous as I am about to modify // the memEntry sequence after the read and therefore those pointers // may not be good anymore after this point. rSequence_unTaintRead( memEntry ); if( NULL != tmpModName ) { rSequence_addSTRINGN( memEntry, RP_TAGS_MODULE_NAME, tmpModName ); } if( NULL != tmpModPath ) { rSequence_addSTRINGN( memEntry, RP_TAGS_FILE_PATH, tmpModPath ); } } } rList_resetIterator( memMapList ); rList_free( modulesList ); } if( !rSequence_addLIST( event, RP_TAGS_MEMORY_MAP, memMapList ) ) { rList_free( memMapList ); } } else { rSequence_addRU32( event, RP_TAGS_ERROR, rpal_error_getLast() ); } } } hbs_timestampEvent( event, 0 ); hbs_publish( RP_TAGS_NOTIFICATION_MEM_MAP_REP, event ); }
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 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 osTrackerDiffThread ( rEvent isTimeToStop, RPVOID ctx ) { CryptoLib_Hash* prevServices = NULL; RU32 prevNServices = 0; CryptoLib_Hash* prevDrivers = NULL; RU32 prevNDrivers = 0; CryptoLib_Hash* prevAutoruns = NULL; RU32 prevNAutoruns = 0; rList snapshot = NULL; UNREFERENCED_PARAMETER( ctx ); while( !rEvent_wait( isTimeToStop, g_diff_timeout ) ) { rpal_debug_info( "looking for changes in os snapshots" ); if( NULL != ( snapshot = libOs_getServices( TRUE ) ) ) { _processSnapshot( snapshot, &prevServices, &prevNServices, RP_TAGS_SVC, RP_TAGS_NOTIFICATION_SERVICE_CHANGE ); rList_free( snapshot ); } if( rEvent_wait( isTimeToStop, MSEC_FROM_SEC( 5 ) ) ) { break; } if( NULL != ( snapshot = libOs_getDrivers( TRUE ) ) ) { _processSnapshot( snapshot, &prevDrivers, &prevNDrivers, RP_TAGS_SVC, RP_TAGS_NOTIFICATION_DRIVER_CHANGE ); rList_free( snapshot ); } if( rEvent_wait( isTimeToStop, MSEC_FROM_SEC( 5 ) ) ) { break; } if( NULL != ( snapshot = libOs_getAutoruns( TRUE ) ) ) { _processSnapshot( snapshot, &prevAutoruns, &prevNAutoruns, RP_TAGS_SVC, RP_TAGS_NOTIFICATION_AUTORUN_CHANGE ); rList_free( snapshot ); } rpal_debug_info( "finished updating snapshots" ); } FREE_AND_NULL( prevServices ); FREE_AND_NULL( prevDrivers ); FREE_AND_NULL( prevAutoruns ); return NULL; }
RPRIVATE RPVOID osTrackerDiffThread ( rEvent isTimeToStop, RPVOID ctx ) { CryptoLib_Hash* prevServices = NULL; RU32 prevNServices = 0; CryptoLib_Hash* prevDrivers = NULL; RU32 prevNDrivers = 0; CryptoLib_Hash* prevAutoruns = NULL; RU32 prevNAutoruns = 0; rList snapshot = NULL; UNREFERENCED_PARAMETER( ctx ); while( !rEvent_wait( isTimeToStop, g_diff_timeout ) ) { rpal_debug_info( "looking for changes in os snapshots" ); if( NULL != ( snapshot = libOs_getServices( TRUE ) ) ) { _processSnapshot( snapshot, &prevServices, &prevNServices, RP_TAGS_SVC, RP_TAGS_NOTIFICATION_SERVICE_CHANGE ); rList_free( snapshot ); } if( rEvent_wait( isTimeToStop, MSEC_FROM_SEC( 5 ) ) ) { break; } #ifdef RPAL_PLATFORM_WINDOWS // Drivers are only available on Windows if( NULL != ( snapshot = libOs_getDrivers( TRUE ) ) ) { _processSnapshot( snapshot, &prevDrivers, &prevNDrivers, RP_TAGS_SVC, RP_TAGS_NOTIFICATION_DRIVER_CHANGE ); rList_free( snapshot ); } if( rEvent_wait( isTimeToStop, MSEC_FROM_SEC( 5 ) ) ) { break; } #endif #if defined( RPAL_PLATFORM_WINDOWS ) || defined( RPAL_PLATFORM_MACOSX ) // Services are currently only available on OSX and Windows if( NULL != ( snapshot = libOs_getAutoruns( TRUE ) ) ) { _processSnapshot( snapshot, &prevAutoruns, &prevNAutoruns, RP_TAGS_SVC, RP_TAGS_NOTIFICATION_AUTORUN_CHANGE ); rList_free( snapshot ); } rpal_debug_info( "finished updating snapshots" ); #endif } FREE_AND_NULL( prevServices ); FREE_AND_NULL( prevDrivers ); FREE_AND_NULL( prevAutoruns ); return NULL; }