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 ); } } }
static RVOID publishCloudNotifications ( rList notifications ) { rSequence notif = NULL; RPU8 buff = NULL; RU32 buffSize = 0; RPU8 sig = NULL; RU32 sigSize = 0; rpHCPId curId = { 0 }; rSequence cloudEvent = NULL; rSequence targetId = { 0 }; RU32 eventId = 0; rSequence localEvent = NULL; RU64 expiry = 0; rpHCPId tmpId = { 0 }; rSequence receipt = NULL; while( rList_getSEQUENCE( notifications, RP_TAGS_HBS_CLOUD_NOTIFICATION, ¬if ) ) { cloudEvent = NULL; if( rSequence_getBUFFER( notif, RP_TAGS_BINARY, &buff, &buffSize ) && rSequence_getBUFFER( notif, RP_TAGS_SIGNATURE, &sig, &sigSize ) ) { if( CryptoLib_verify( buff, buffSize, hbs_cloud_pub_key, sig ) ) { if( !rpHcpI_getId( &curId ) ) { rpal_debug_error( "error getting current id for cloud notifications." ); } else { if( !rSequence_deserialise( &cloudEvent, buff, buffSize, NULL ) ) { cloudEvent = NULL; rpal_debug_warning( "error deserializing cloud event." ); } } } else { rpal_debug_warning( "cloud event signature invalid." ); } } if( rpal_memory_isValid( cloudEvent ) ) { if( rSequence_getSEQUENCE( cloudEvent, RP_TAGS_HCP_ID, &targetId ) && rSequence_getRU32( cloudEvent, RP_TAGS_HBS_NOTIFICATION_ID, &eventId ) && rSequence_getSEQUENCE( cloudEvent, RP_TAGS_HBS_NOTIFICATION, &localEvent ) ) { rSequence_getTIMESTAMP( cloudEvent, RP_TAGS_EXPIRY, &expiry ); tmpId = rpHcpI_seqToHcpId( targetId ); curId.id.configId = 0; tmpId.id.configId = 0; if( NULL != ( receipt = rSequence_new() ) ) { if( rSequence_addSEQUENCE( receipt, RP_TAGS_HBS_CLOUD_NOTIFICATION, rSequence_duplicate( cloudEvent ) ) ) { if( !rQueue_add( g_hbs_state.outQueue, receipt, 0 ) ) { rSequence_free( receipt ); receipt = NULL; } } else { rSequence_free( receipt ); receipt = NULL; } } if( curId.raw == tmpId.raw && rpal_time_getGlobal() <= expiry ) { if( !notifications_publish( eventId, localEvent ) ) { rpal_debug_error( "error publishing event from cloud." ); } } else { rpal_debug_warning( "event expired or for wrong id." ); } } if( rpal_memory_isValid( cloudEvent ) ) { rSequence_free( cloudEvent ); cloudEvent = NULL; } } } }
static RPVOID lookForHiddenModulesIn ( rEvent isTimeToStop, RU32 processId ) { rList mods = NULL; rList map = NULL; rSequence region = NULL; RU8 memType = 0; RU8 memProtect = 0; RU64 memBase = 0; RU64 memSize = 0; RPU8 pMem = NULL; RBOOL isPrefetched = FALSE; RBOOL isCurrentExec = FALSE; RBOOL isHidden = FALSE; rSequence procInfo = NULL; #ifdef RPAL_PLATFORM_WINDOWS PIMAGE_DOS_HEADER pDos = NULL; PIMAGE_NT_HEADERS pNt = NULL; #endif if( NULL != ( mods = processLib_getProcessModules( processId ) ) ) { if( NULL != ( map = processLib_getProcessMemoryMap( processId ) ) ) { // Now we got all the info needed for a single process, compare while( rpal_memory_isValid( isTimeToStop ) && !rEvent_wait( isTimeToStop, 0 ) && ( isPrefetched || rList_getSEQUENCE( map, RP_TAGS_MEMORY_REGION, ®ion ) ) ) { if( isPrefetched ) { isPrefetched = FALSE; } if( rSequence_getRU8( region, RP_TAGS_MEMORY_TYPE, &memType ) && rSequence_getRU8( region, RP_TAGS_MEMORY_ACCESS, &memProtect ) && rSequence_getPOINTER64( region, RP_TAGS_BASE_ADDRESS, &memBase ) && rSequence_getRU64( region, RP_TAGS_MEMORY_SIZE, &memSize ) ) { if( PROCESSLIB_MEM_TYPE_PRIVATE == memType || PROCESSLIB_MEM_TYPE_MAPPED == memType ) { if( PROCESSLIB_MEM_ACCESS_EXECUTE == memProtect || PROCESSLIB_MEM_ACCESS_EXECUTE_READ == memProtect || PROCESSLIB_MEM_ACCESS_EXECUTE_READ_WRITE == memProtect || PROCESSLIB_MEM_ACCESS_EXECUTE_WRITE_COPY == memProtect ) { isCurrentExec = TRUE; } else { isCurrentExec = FALSE; } if( !isMemInModule( memBase, memSize, mods ) ) { // Exec memory found outside of a region marked to belong to // a module, keep looking in for module. if( ( 1024 * 1024 * 10 ) >= memSize && processLib_getProcessMemory( processId, NUMBER_TO_PTR( memBase ), memSize, (RPVOID*)&pMem ) ) { isHidden = FALSE; #ifdef RPAL_PLATFORM_WINDOWS // Let's just check for MZ and PE for now, we can get fancy later. pDos = (PIMAGE_DOS_HEADER)pMem; if( IS_WITHIN_BOUNDS( (RPU8)pMem, sizeof( IMAGE_DOS_HEADER ), pMem, memSize ) && IMAGE_DOS_SIGNATURE == pDos->e_magic ) { pNt = (PIMAGE_NT_HEADERS)( (RPU8)pDos + pDos->e_lfanew ); if( IS_WITHIN_BOUNDS( pNt, sizeof( *pNt ), pMem, memSize ) && IMAGE_NT_SIGNATURE == pNt->Signature ) { if( isCurrentExec ) { // If the current region is exec, we've got a hidden module. isHidden = TRUE; } else { // We need to check if the next section in memory is // executable and outside of known modules since the PE // headers may have been marked read-only before the .text. if( rList_getSEQUENCE( map, RP_TAGS_MEMORY_REGION, ®ion ) ) { isPrefetched = TRUE; if( ( PROCESSLIB_MEM_TYPE_PRIVATE == memType || PROCESSLIB_MEM_TYPE_MAPPED == memType ) && ( PROCESSLIB_MEM_ACCESS_EXECUTE == memProtect || PROCESSLIB_MEM_ACCESS_EXECUTE_READ == memProtect || PROCESSLIB_MEM_ACCESS_EXECUTE_READ_WRITE == memProtect || PROCESSLIB_MEM_ACCESS_EXECUTE_WRITE_COPY == memProtect ) ) { isHidden = TRUE; } } } } } #elif defined( RPAL_PLATFORM_LINUX ) || defined( RPAL_PLATFORM_MACOSX ) if( isCurrentExec && 0x7F == ( pMem )[ 0 ] && 'E' == ( pMem )[ 1 ] && 'L' == ( pMem )[ 2 ] && 'F' == ( pMem )[ 3 ] ) { isHidden = TRUE; } #endif rpal_memory_free( pMem ); if( isHidden && !rEvent_wait( isTimeToStop, 0 ) ) { rpal_debug_info( "found a hidden module in %d.", processId ); if( NULL != ( procInfo = processLib_getProcessInfo( processId ) ) ) { if( !rSequence_addSEQUENCE( region, RP_TAGS_PROCESS, procInfo ) ) { rSequence_free( procInfo ); } } rSequence_addTIMESTAMP( region, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() ); notifications_publish( RP_TAGS_NOTIFICATION_HIDDEN_MODULE_DETECTED, region ); break; } rpal_thread_sleep( 10 ); } } } } } rList_free( map ); } rList_free( mods ); } return NULL; }
static RPVOID networkDiffThread ( rEvent isTimeToStop, RPVOID ctx ) { NetLib_Tcp4Table* currentTcp4Table = NULL; NetLib_Tcp4Table* oldTcp4Table = NULL; NetLib_UdpTable* currentUdpTable = NULL; NetLib_UdpTable* oldUdpTable = NULL; RU32 i = 0; RU32 j = 0; RBOOL isFound = FALSE; rSequence notif = NULL; rSequence comp = NULL; RU32 timeout = 100; RU32 nThLoop = 0; UNREFERENCED_PARAMETER( ctx ); while( rpal_memory_isValid( isTimeToStop ) && !rEvent_wait( isTimeToStop, 0 ) ) { if( NULL != oldTcp4Table ) { rpal_memory_free( oldTcp4Table ); oldTcp4Table = NULL; } if( NULL != oldUdpTable ) { rpal_memory_free( oldUdpTable ); oldUdpTable = NULL; } // Swap the old snapshot for the (prev) new one oldTcp4Table = currentTcp4Table; oldUdpTable = currentUdpTable; currentTcp4Table = NULL; currentUdpTable = NULL; // Generate new tables currentTcp4Table = NetLib_getTcp4Table(); currentUdpTable = NetLib_getUdpTable(); // Diff TCP snapshots for new entries if( rpal_memory_isValid( currentTcp4Table ) && rpal_memory_isValid( oldTcp4Table ) ) { for( i = 0; i < currentTcp4Table->nRows; i++ ) { isFound = FALSE; if( rEvent_wait( isTimeToStop, 0 ) ) { break; } for( j = 0; j < oldTcp4Table->nRows; j++ ) { if( isTcpEqual( ¤tTcp4Table->rows[ i ], &oldTcp4Table->rows[ j ] ) ) { isFound = TRUE; break; } } if( !isFound ) { if( NULL != ( notif = rSequence_new() ) ) { if( rSequence_addRU32( notif, RP_TAGS_STATE, currentTcp4Table->rows[ i ].state ) && rSequence_addRU32( notif, RP_TAGS_PROCESS_ID, currentTcp4Table->rows[ i ].pid ) && rSequence_addTIMESTAMP( notif, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() ) ) { if( NULL != ( comp = rSequence_new() ) ) { // Add the destination components if( !rSequence_addIPV4( comp, RP_TAGS_IP_ADDRESS, currentTcp4Table->rows[ i ].destIp ) || !rSequence_addRU16( comp, RP_TAGS_PORT, rpal_ntoh16( (RU16)currentTcp4Table->rows[ i ].destPort ) ) || !rSequence_addSEQUENCE( notif, RP_TAGS_DESTINATION, comp ) ) { rSequence_free( comp ); comp = NULL; } } if( NULL != ( comp = rSequence_new() ) ) { // Add the source components if( !rSequence_addIPV4( comp, RP_TAGS_IP_ADDRESS, currentTcp4Table->rows[ i ].sourceIp ) || !rSequence_addRU16( comp, RP_TAGS_PORT, rpal_ntoh16( (RU16)currentTcp4Table->rows[ i ].sourcePort ) ) || !rSequence_addSEQUENCE( notif, RP_TAGS_SOURCE, comp ) ) { rSequence_free( comp ); comp = NULL; } } rpal_debug_info( "new tcp connection: 0x%08X = 0x%08X:0x%04X ---> 0x%08X:0x%04X -- 0x%08X.", currentTcp4Table->rows[ i ].state, currentTcp4Table->rows[ i ].sourceIp, currentTcp4Table->rows[ i ].sourcePort, currentTcp4Table->rows[ i ].destIp, currentTcp4Table->rows[ i ].destPort, currentTcp4Table->rows[ i ].pid ); notifications_publish( RP_TAGS_NOTIFICATION_NEW_TCP4_CONNECTION, notif ); } rSequence_free( notif ); } } } } else if( 0 != nThLoop ) { rpal_debug_warning( "could not get tcp connections table." ); } // Diff TCP snapshots for new entries if( NULL != currentUdpTable && NULL != oldUdpTable ) { for( i = 0; i < currentUdpTable->nRows; i++ ) { isFound = FALSE; if( rEvent_wait( isTimeToStop, 0 ) ) { break; } for( j = 0; j < oldUdpTable->nRows; j++ ) { if( isUdpEqual( ¤tUdpTable->rows[ i ], &oldUdpTable->rows[ j ] ) ) { isFound = TRUE; break; } } if( !isFound ) { if( NULL != ( notif = rSequence_new() ) ) { if( !rSequence_addIPV4( notif, RP_TAGS_IP_ADDRESS, currentUdpTable->rows[ i ].localIp ) || !rSequence_addRU16( notif, RP_TAGS_PORT, rpal_ntoh16( (RU16)currentUdpTable->rows[ i ].localPort ) ) || !rSequence_addRU32( notif, RP_TAGS_PROCESS_ID, currentUdpTable->rows[ i ].pid ) || !rSequence_addTIMESTAMP( notif, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() ) ) { notif = NULL; } else { rpal_debug_info( "new udp connection: 0x%08X:0x%04X -- 0x%08X.", currentUdpTable->rows[ i ].localIp, currentUdpTable->rows[ i ].localPort, currentUdpTable->rows[ i ].pid ); notifications_publish( RP_TAGS_NOTIFICATION_NEW_UDP4_CONNECTION, notif ); } rSequence_free( notif ); } } } } else if( 0 != nThLoop ) { rpal_debug_warning( "could not get udp connections table." ); } nThLoop++; if( 0 == nThLoop % 10 ) { timeout = libOs_getUsageProportionalTimeout( 1000 ) + 500; } rpal_thread_sleep( timeout ); } rpal_memory_free( currentTcp4Table ); rpal_memory_free( currentUdpTable ); rpal_memory_free( oldTcp4Table ); rpal_memory_free( oldUdpTable ); return NULL; }
static 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 rString assembleOutboundStream ( RpHcp_ModuleId moduleId, rList payload, RU8 sessionKey[ CRYPTOLIB_SYM_KEY_SIZE ], RU8 sessionIv[ CRYPTOLIB_SYM_IV_SIZE ] ) { rString str = NULL; rSequence hdrSeq = NULL; rSequence hcpid = NULL; rBlob blob = NULL; RPCHAR encoded = NULL; RPU8 encBuffer = NULL; RU64 encSize = 0; RPU8 finalBuffer = NULL; RU32 finalSize = 0; RPCHAR hostName = NULL; RBOOL isSuccess = FALSE; OBFUSCATIONLIB_DECLARE( payHdr, RP_HCP_CONFIG_PAYLOAD_HDR ); str = rpal_stringbuffer_new( 0, 0, FALSE ); if( NULL != str ) { if( NULL != ( hdrSeq = rSequence_new() ) ) { if( NULL != ( hcpid = hcpIdToSeq( g_hcpContext.currentId ) ) ) { // System basic information // Host Name if( NULL != ( hostName = libOs_getHostName() ) ) { rSequence_addSTRINGA( hdrSeq, RP_TAGS_HOST_NAME, hostName ); rpal_memory_free( hostName ); } else { rpal_debug_warning( "could not determine hostname" ); } // Internal IP rSequence_addIPV4( hdrSeq, RP_TAGS_IP_ADDRESS, libOs_getMainIp() ); if( rSequence_addSEQUENCE( hdrSeq, RP_TAGS_HCP_ID, hcpid ) && rSequence_addRU8( hdrSeq, RP_TAGS_HCP_MODULE_ID, moduleId ) && rSequence_addBUFFER( hdrSeq, RP_TAGS_SYM_KEY, sessionKey, CRYPTOLIB_SYM_KEY_SIZE ) && rSequence_addBUFFER( hdrSeq, RP_TAGS_SYM_IV, sessionIv, CRYPTOLIB_SYM_IV_SIZE ) ) { if( NULL != g_hcpContext.enrollmentToken && 0 != g_hcpContext.enrollmentTokenSize ) { rSequence_addBUFFER( hdrSeq, RP_TAGS_HCP_ENROLLMENT_TOKEN, g_hcpContext.enrollmentToken, g_hcpContext.enrollmentTokenSize ); } if( NULL != payload ) { blob = rpal_blob_create( 0, 0 ); } if( NULL == payload || NULL != blob ) { if( rSequence_serialise( hdrSeq, blob ) && ( NULL == payload || rList_serialise( payload, blob ) ) ) { encSize = compressBound( rpal_blob_getSize( blob ) ); encBuffer = rpal_memory_alloc( (RU32)encSize ); if( NULL == payload || NULL != encBuffer ) { if( NULL == payload || Z_OK == compress( encBuffer, (uLongf*)&encSize, (RPU8)rpal_blob_getBuffer( blob ), rpal_blob_getSize( blob ) ) ) { FREE_N_NULL( blob, rpal_blob_free ); if( NULL == payload || CryptoLib_fastAsymEncrypt( encBuffer, (RU32)encSize, getC2PublicKey(), &finalBuffer, &finalSize ) ) { FREE_N_NULL( encBuffer, rpal_memory_free ); if( NULL == payload || base64_encode( finalBuffer, finalSize, &encoded, TRUE ) ) { isSuccess = TRUE; if( NULL != payload ) { FREE_N_NULL( finalBuffer, rpal_memory_free ); DO_IFF( rpal_stringbuffer_add( str, "&" ), isSuccess ); OBFUSCATIONLIB_TOGGLE( payHdr ); DO_IFF( rpal_stringbuffer_add( str, (RPCHAR)payHdr ), isSuccess ); DO_IFF( rpal_stringbuffer_add( str, encoded ), isSuccess ); OBFUSCATIONLIB_TOGGLE( payHdr ); } IF_VALID_DO( encoded, rpal_memory_free ); } IF_VALID_DO( finalBuffer, rpal_memory_free ); } } IF_VALID_DO( encBuffer, rpal_memory_free ); } } IF_VALID_DO( blob, rpal_blob_free ); } } } rSequence_free( hdrSeq ); } if( !isSuccess ) { rpal_stringbuffer_free( str ); str = NULL; } } return str; }
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 ); } } }