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 _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; }
RPRIVATE RVOID mem_read ( rpcm_tag eventType, rSequence event ) { RU32 pid; RU64 baseAddr; RU32 memSize; RPVOID mem; 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_getRU64( event, RP_TAGS_BASE_ADDRESS, &baseAddr ) && rSequence_getRU32( event, RP_TAGS_MEMORY_SIZE, &memSize ) ) { if( processLib_getProcessMemory( pid, (RPVOID)rpal_ULongToPtr( baseAddr ), memSize, &mem, TRUE ) ) { rSequence_addBUFFER( event, RP_TAGS_MEMORY_DUMP, (RPU8)mem, memSize ); rpal_memory_free( mem ); } else { rSequence_addRU32( event, RP_TAGS_ERROR, rpal_error_getLast() ); rpal_debug_error( "failed to get memory (base address = 0x%llx, size = 0x%x ) for pid 0x%x.", baseAddr, memSize, pid ); } } hbs_timestampEvent( event, 0 ); hbs_publish( RP_TAGS_NOTIFICATION_MEM_READ_REP, event ); } }
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 ); } }
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 ); } }
rSequence rpHcpI_hcpIdToSeq ( rpHCPId id ) { rSequence seq = NULL; if( NULL != ( seq = rSequence_new() ) ) { if( !rSequence_addRU8( seq, RP_TAGS_HCP_ID_ORG, id.id.orgId ) || !rSequence_addRU8( seq, RP_TAGS_HCP_ID_SUBNET, id.id.subnetId ) || !rSequence_addRU32( seq, RP_TAGS_HCP_ID_UNIQUE, id.id.uniqueId ) || !rSequence_addRU8( seq, RP_TAGS_HCP_ID_PLATFORM, id.id.platformId ) || !rSequence_addRU8( seq, RP_TAGS_HCP_ID_CONFIG, id.id.configId ) ) { DESTROY_AND_NULL( seq, rSequence_free ); } } return seq; }
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 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; }
RPRIVATE RVOID processDnsPacket ( KernelAcqDnsPacket* pDns ) { rSequence notification = NULL; RU32 i = 0; DnsLabel* pLabel = NULL; DnsHeader* dnsHeader = NULL; DnsResponseInfo* pResponseInfo = NULL; RCHAR domain[ DNS_LABEL_MAX_SIZE ] = { 0 }; RU16 recordType = 0; RU64 timestamp = 0; Atom parentAtom = { 0 }; if( NULL == pDns ) { return; } dnsHeader = (DnsHeader*)( (RPU8)pDns + sizeof( *pDns ) ); pLabel = (DnsLabel*)dnsHeader->data; // We are parsing DNS packets coming from the kernel. They may: // 1- Be requests and not responses, check there are Answers. // 2- Be maliciously crafter packets so we need extra checking for sanity. if( 0 == dnsHeader->anCount || 0 == dnsHeader->qr || DNS_SANITY_MAX_RECORDS < rpal_ntoh16( dnsHeader->qdCount ) || DNS_SANITY_MAX_RECORDS < rpal_ntoh16( dnsHeader->anCount ) ) { return; } // We need to walk the Questions first to get to the Answers // but we don't really care to record them since they'll be repeated // in the Answers. for( i = 0; i < rpal_ntoh16( dnsHeader->qdCount ); i++ ) { DnsQuestionInfo* pQInfo = NULL; pLabel = dnsReadLabels( pLabel, NULL, (RPU8)dnsHeader, pDns->packetSize, 0, 0 ); pQInfo = (DnsQuestionInfo*)( pLabel ); if( !IS_WITHIN_BOUNDS( pQInfo, sizeof( *pQInfo ), dnsHeader, pDns->packetSize ) ) { rpal_debug_warning( "error parsing dns packet" ); break; } pLabel = (DnsLabel*)( (RPU8)pQInfo + sizeof( *pQInfo ) ); } if( !IS_WITHIN_BOUNDS( pLabel, sizeof( RU16 ), dnsHeader, pDns->packetSize ) ) { rpal_debug_warning( "error parsing dns packet" ); return; } // This is what we care about, the Answers (which also point to each Question). // We will emit one event per Answer so as to keep the DNS_REQUEST event flat and atomic. for( i = 0; i < rpal_ntoh16( dnsHeader->anCount ); i++ ) { pResponseInfo = NULL; // This was the Question for this answer. rpal_memory_zero( domain, sizeof( domain ) ); pLabel = dnsReadLabels( pLabel, domain, (RPU8)dnsHeader, pDns->packetSize, 0, 0 ); pResponseInfo = (DnsResponseInfo*)pLabel; pLabel = (DnsLabel*)( (RPU8)pResponseInfo + sizeof( *pResponseInfo ) + rpal_ntoh16( pResponseInfo->rDataLength ) ); if( !IS_WITHIN_BOUNDS( pResponseInfo, sizeof( *pResponseInfo ), dnsHeader, pDns->packetSize ) ) { rpal_debug_warning( "error parsing dns packet" ); break; } if( NULL == ( notification = rSequence_new() ) ) { rpal_debug_warning( "error parsing dns packet" ); break; } // This is a timestamp coming from the kernel so it is not globally adjusted. // We'll adjust it with the global offset. timestamp = pDns->ts; timestamp += MSEC_FROM_SEC( rpal_time_getGlobalFromLocal( 0 ) ); // Try to relate the DNS request to the owner process, this only works on OSX // at the moment (since the kernel does not expose the PID at the packet capture // stage), and even on OSX it's the DNSResolver process. So it's not super useful // but regardless we have the mechanism here as it's better than nothing and when // we add better resolving in the kernel it will work transparently. parentAtom.key.process.pid = pDns->pid; parentAtom.key.category = RP_TAGS_NOTIFICATION_NEW_PROCESS; if( atoms_query( &parentAtom, timestamp ) ) { HbsSetParentAtom( notification, parentAtom.id ); } rSequence_addTIMESTAMP( notification, RP_TAGS_TIMESTAMP, timestamp ); rSequence_addSTRINGA( notification, RP_TAGS_DOMAIN_NAME, domain ); rSequence_addRU32( notification, RP_TAGS_PROCESS_ID, pDns->pid ); recordType = rpal_ntoh16( pResponseInfo->recordType ); rSequence_addRU16( notification, RP_TAGS_MESSAGE_ID, rpal_ntoh16( dnsHeader->msgId ) ); rSequence_addRU16( notification, RP_TAGS_DNS_TYPE, recordType ); if( DNS_A_RECORD == recordType ) { rSequence_addIPV4( notification, RP_TAGS_IP_ADDRESS, *(RU32*)pResponseInfo->rData ); } else if( DNS_AAAA_RECORD == recordType ) { rSequence_addIPV6( notification, RP_TAGS_IP_ADDRESS, pResponseInfo->rData ); } else if( DNS_CNAME_RECORD == recordType ) { // CNAME records will have another label as a value and not an IP. rpal_memory_zero( domain, sizeof( domain ) ); dnsReadLabels( (DnsLabel*)pResponseInfo->rData, domain, (RPU8)dnsHeader, pDns->packetSize, 0, 0 ); rSequence_addSTRINGA( notification, RP_TAGS_CNAME, domain ); } else { // Right now we only care for A, CNAME and AAAA records. rSequence_free( notification ); notification = NULL; continue; } hbs_publish( RP_TAGS_NOTIFICATION_DNS_REQUEST, notification ); rSequence_free( notification ); notification = NULL; } }
RPRIVATE RVOID dnsUmDiffThread ( rEvent isTimeToStop ) { rSequence notif = NULL; rBlob snapCur = NULL; rBlob snapPrev = NULL; _dnsRecord rec = { 0 }; _dnsRecord* pCurRec = NULL; RU32 i = 0; LibOsPerformanceProfile perfProfile = { 0 }; #ifdef RPAL_PLATFORM_WINDOWS PDNSCACHEENTRY pDnsEntry = NULL; PDNSCACHEENTRY pPrevDnsEntry = NULL; #endif perfProfile.enforceOnceIn = 1; perfProfile.sanityCeiling = MSEC_FROM_SEC( 10 ); perfProfile.lastTimeoutValue = 100; perfProfile.targetCpuPerformance = 0; perfProfile.globalTargetCpuPerformance = GLOBAL_CPU_USAGE_TARGET; perfProfile.timeoutIncrementPerSec = 1; while( !rEvent_wait( isTimeToStop, 0 ) ) { if( kAcq_isAvailable() ) { // If kernel acquisition becomes available, try kernel again. return; } libOs_timeoutWithProfile( &perfProfile, FALSE, isTimeToStop ); if( NULL != ( snapCur = rpal_blob_create( 0, 10 * sizeof( rec ) ) ) ) { #ifdef RPAL_PLATFORM_WINDOWS if( TRUE == getCache( &pDnsEntry ) ) { while( NULL != pDnsEntry ) { rec.flags = pDnsEntry->dwFlags; rec.type = pDnsEntry->wType; if( NULL != ( rec.name = rpal_string_strdup( pDnsEntry->pszName ) ) ) { rpal_blob_add( snapCur, &rec, sizeof( rec ) ); } pPrevDnsEntry = pDnsEntry; pDnsEntry = pDnsEntry->pNext; freeCacheEntry( pPrevDnsEntry->pszName, DnsFreeFlat ); freeCacheEntry( pPrevDnsEntry, DnsFreeFlat ); } rpal_sort_array( rpal_blob_getBuffer( snapCur ), rpal_blob_getSize( snapCur ) / sizeof( rec ), sizeof( rec ), _cmpDns ); } #elif defined( RPAL_PLATFORM_MACOSX ) rpal_thread_sleep( MSEC_FROM_SEC( 2 ) ); #endif // Do a general diff of the snapshots to find new entries. if( NULL != snapPrev ) { i = 0; while( !rEvent_wait( isTimeToStop, 0 ) && NULL != ( pCurRec = rpal_blob_arrElem( snapCur, sizeof( rec ), i++ ) ) ) { if( -1 == rpal_binsearch_array( rpal_blob_getBuffer( snapPrev ), rpal_blob_getSize( snapPrev ) / sizeof( rec ), sizeof( rec ), pCurRec, (rpal_ordering_func)_cmpDns ) ) { if( NULL != ( notif = rSequence_new() ) ) { rSequence_addSTRINGN( notif, RP_TAGS_DOMAIN_NAME, pCurRec->name ); rSequence_addRU16( notif, RP_TAGS_DNS_TYPE, pCurRec->type ); rSequence_addRU32( notif, RP_TAGS_DNS_FLAGS, pCurRec->flags ); hbs_timestampEvent( notif, 0 ); hbs_publish( RP_TAGS_NOTIFICATION_DNS_REQUEST, notif ); rSequence_free( notif ); } } } } } if( NULL != snapPrev ) { _freeRecords( snapPrev ); rpal_blob_free( snapPrev ); snapPrev = NULL; } snapPrev = snapCur; snapCur = NULL; libOs_timeoutWithProfile( &perfProfile, TRUE, isTimeToStop ); } if( NULL != snapPrev ) { _freeRecords( snapPrev ); rpal_blob_free( snapPrev ); snapPrev = NULL; } }
static RPVOID 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; }
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; }
static RVOID processHashedEvent ( rpcm_tag notifType, rSequence event ) { RPWCHAR nameW = NULL; RPCHAR nameA = NULL; CryptoLib_Hash* pHash = NULL; CryptoLib_Hash localHash = { 0 }; UNREFERENCED_PARAMETER( notifType ); if( rpal_memory_isValid( event ) ) { if( rSequence_getSTRINGA( event, RP_TAGS_FILE_PATH, &nameA ) || rSequence_getSTRINGW( event, RP_TAGS_FILE_PATH, &nameW ) || rSequence_getSTRINGA( event, RP_TAGS_DLL, &nameA ) || rSequence_getSTRINGW( event, RP_TAGS_DLL, &nameW ) || rSequence_getSTRINGA( event, RP_TAGS_EXECUTABLE, &nameA ) || rSequence_getSTRINGW( event, RP_TAGS_EXECUTABLE, &nameW ) ) { rSequence_getBUFFER( event, RP_TAGS_HASH, (RPU8*)&pHash, NULL ); if( NULL != nameA ) { if( NULL == pHash ) { if( _MAX_FILE_HASH_SIZE < rpal_file_getSize( nameA, TRUE ) ) { rSequence_unTaintRead( event ); rSequence_addRU32( event, RP_TAGS_ERROR, RPAL_ERROR_FILE_TOO_LARGE ); if( rSequence_getSTRINGA( event, RP_TAGS_FILE_PATH, &nameA ) || rSequence_getSTRINGA( event, RP_TAGS_DLL, &nameA ) || rSequence_getSTRINGA( event, RP_TAGS_EXECUTABLE, &nameA ) ) { // Find the name again with shortcircuit } } else if( CryptoLib_hashFileA( nameA, &localHash, TRUE ) ) { pHash = &localHash; } } processCodeIdentA( nameA, pHash, 0, event ); } else if( NULL != nameW ) { if( NULL == pHash ) { if( _MAX_FILE_HASH_SIZE < rpal_file_getSizew( nameW, TRUE ) ) { rSequence_unTaintRead( event ); rSequence_addRU32( event, RP_TAGS_ERROR, RPAL_ERROR_FILE_TOO_LARGE ); if( rSequence_getSTRINGW( event, RP_TAGS_FILE_PATH, &nameW ) || rSequence_getSTRINGW( event, RP_TAGS_DLL, &nameW ) || rSequence_getSTRINGW( event, RP_TAGS_EXECUTABLE, &nameW ) ) { // Find the name again with shortcircuit } } else if( CryptoLib_hashFileW( nameW, &localHash, TRUE ) ) { pHash = &localHash; } } processCodeIdentW( nameW, pHash, 0, event ); } } } }
static RVOID processNewModule ( rpcm_tag notifType, rSequence event ) { RPWCHAR nameW = NULL; RPCHAR nameA = NULL; CryptoLib_Hash fileHash = { 0 }; RU64 size = 0; UNREFERENCED_PARAMETER( notifType ); if( rpal_memory_isValid( event ) ) { if( rSequence_getSTRINGA( event, RP_TAGS_FILE_PATH, &nameA ) || rSequence_getSTRINGW( event, RP_TAGS_FILE_PATH, &nameW ) ) { if( ( NULL != nameA && _MAX_FILE_HASH_SIZE < rpal_file_getSize( nameA, TRUE ) ) || ( NULL != nameW && _MAX_FILE_HASH_SIZE < rpal_file_getSizew( nameW, TRUE ) ) ) { // We already read from the event, but we will be careful. rSequence_unTaintRead( event ); rSequence_addRU32( event, RP_TAGS_ERROR, RPAL_ERROR_FILE_TOO_LARGE ); // We need to re-get the paths in case adding the error triggered // a change in the structure. if( rSequence_getSTRINGA( event, RP_TAGS_FILE_PATH, &nameA ) || rSequence_getSTRINGW( event, RP_TAGS_FILE_PATH, &nameW ) ) { // Find the name again with shortcircuit } } else { if( NULL != nameA && !CryptoLib_hashFileA( nameA, &fileHash, TRUE ) ) { rpal_debug_info( "unable to fetch file hash for ident" ); } if( NULL != nameW && !CryptoLib_hashFileW( nameW, &fileHash, TRUE ) ) { rpal_debug_info( "unable to fetch file hash for ident" ); } } rSequence_getRU64( event, RP_TAGS_MEMORY_SIZE, &size ); if( NULL != nameA ) { processCodeIdentA( nameA, &fileHash, size, event ); } else if( NULL != nameW ) { processCodeIdentW( nameW, &fileHash, size, event ); } } } }
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; }
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 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 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 RVOID processFileIo ( rpcm_tag notifType, rSequence event ) { ProcExtInfo* ctx = NULL; RPNCHAR path = NULL; RPVOID patternCtx = 0; RU8 patternId = 0; RPU8 atomId = NULL; RU32 pid = 0; rSequence newEvent = NULL; UNREFERENCED_PARAMETER( notifType ); if( rSequence_getSTRINGN( event, RP_TAGS_FILE_PATH, &path ) && HbsGetParentAtom( event, &atomId ) && rSequence_getRU32( event, RP_TAGS_PROCESS_ID, &pid ) ) { if( rMutex_lock( g_mutex ) ) { obsLib_resetSearchState( g_extensions ); if( obsLib_setTargetBuffer( g_extensions, path, rpal_string_strsize( path ) ) ) { while( obsLib_nextHit( g_extensions, &patternCtx, NULL ) ) { if( NULL != ctx || NULL != ( ctx = getProcContext( atomId ) ) ) { patternId = (RU8)PTR_TO_NUMBER( patternCtx ); if( !IS_FLAG_ENABLED( ctx->extBitMask, (RU64)1 << patternId ) ) { rpal_debug_info( "process " RF_U32 " observed file io " RF_U64, pid, patternId + 1 ); ENABLE_FLAG( ctx->extBitMask, (RU64)1 << patternId ); if( NULL != ( newEvent = rSequence_new() ) ) { HbsSetParentAtom( newEvent, atomId ); rSequence_addRU32( newEvent, RP_TAGS_PROCESS_ID, pid ); rSequence_addRU8( newEvent, RP_TAGS_RULE_NAME, patternId + 1 ); rSequence_addSTRINGN( newEvent, RP_TAGS_FILE_PATH, ctx->processPath ); hbs_publish( RP_TAGS_NOTIFICATION_FILE_TYPE_ACCESSED, newEvent ); rSequence_free( newEvent ); } } } else { rpal_debug_error( "error getting process context" ); break; } } } rMutex_unlock( g_mutex ); } } }
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 ); } } }
static RBOOL notifyOfKernelModule ( KernelAcqModule* module ) { RBOOL isSuccess = FALSE; rSequence notif = NULL; RU32 pathLength = 0; RU32 i = 0; RPNCHAR dirSep = RPAL_FILE_LOCAL_DIR_SEP_N; RPNCHAR cleanPath = NULL; Atom parentAtom = { 0 }; if( NULL != module ) { if( NULL != ( notif = rSequence_new() ) ) { module->ts += MSEC_FROM_SEC( rpal_time_getGlobalFromLocal( 0 ) ); hbs_timestampEvent( notif, module->ts ); parentAtom.key.category = RP_TAGS_NOTIFICATION_NEW_PROCESS; parentAtom.key.process.pid = module->pid; if( atoms_query( &parentAtom, module->ts ) ) { HbsSetParentAtom( notif, parentAtom.id ); } rSequence_addRU32( notif, RP_TAGS_PROCESS_ID, module->pid ); rSequence_addPOINTER64( notif, RP_TAGS_BASE_ADDRESS, (RU64)module->baseAddress ); rSequence_addRU64( notif, RP_TAGS_MEMORY_SIZE, module->imageSize ); if( 0 != ( pathLength = rpal_string_strlen( module->path ) ) ) { cleanPath = rpal_file_clean( module->path ); rSequence_addSTRINGN( notif, RP_TAGS_FILE_PATH, cleanPath ? cleanPath : module->path ); rpal_memory_free( cleanPath ); // For compatibility with user mode we extract the module name. for( i = pathLength - 1; i != 0; i-- ) { if( dirSep[ 0 ] == module->path[ i ] ) { i++; break; } } rSequence_addSTRINGN( notif, RP_TAGS_MODULE_NAME, &( module->path[ i ] ) ); if( hbs_publish( RP_TAGS_NOTIFICATION_MODULE_LOAD, notif ) ) { isSuccess = TRUE; } } rSequence_free( notif ); } } 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 ); }