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; }
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 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 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 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 ); } }
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 ); }
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; }