// Given an atom, find all already executing children, add them to the deny // list and terminate their execution. // This is not the most optimized algorithm but it's simple and only executes // once per new deny tasking. RPRIVATE RVOID denyExistingTree ( RU8 atomId[ HBS_ATOM_ID_SIZE ] ) { RU32 pid = 0; rBlob parents = NULL; RPU8 tmpAtom = NULL; RU32 i = 0; if( NULL != atomId ) { addAtomToDeny( atomId ); if( NULL != ( parents = atoms_getAtomsWithParent( atomId ) ) ) { for( i = 0; i < rpal_blob_getSize( parents ) / HBS_ATOM_ID_SIZE; i++ ) { if( NULL != ( tmpAtom = rpal_blob_arrElem( parents, HBS_ATOM_ID_SIZE, i ) ) ) { denyExistingTree( tmpAtom ); } } rpal_blob_free( parents ); } if( 0 != ( pid = atoms_getPid( atomId ) ) ) { processLib_killProcess( pid ); } } }
// Given an atom, check if it's on the deny list. RPRIVATE RBOOL isAtomDenied ( RPU8 atomId ) { RBOOL isDenied = FALSE; if( rMutex_lock( g_deniedMutex ) ) { if( ( -1 ) != rpal_binsearch_array( rpal_blob_getBuffer( g_denied ), rpal_blob_getSize( g_denied ) / HBS_ATOM_ID_SIZE, HBS_ATOM_ID_SIZE, atomId, (rpal_ordering_func)cmpAtoms ) ) { isDenied = TRUE; } rMutex_unlock( g_deniedMutex ); } return isDenied; }
RBOOL rStack_free ( rStack stack, rStack_freeFunc freeFunc ) { RBOOL isSuccess = FALSE; _prStack pStack = (_prStack)stack; RPVOID tmpElem = NULL; RPVOID tmpBuff = NULL; RU32 tmpSize = 0; RU32 i = 0; if( NULL != stack ) { if( rMutex_lock( pStack->lock ) ) { isSuccess = TRUE; tmpElem = rpal_blob_getBuffer( pStack->blob ); tmpBuff = tmpElem; tmpSize = rpal_blob_getSize( pStack->blob ); for( i = 0; i < pStack->nElements; i++ ) { tmpElem = (RPU8)tmpElem + ( i * pStack->elemSize ); if( IS_WITHIN_BOUNDS( tmpElem, pStack->elemSize, tmpBuff, tmpSize ) ) { if( NULL != freeFunc ) { if( !freeFunc( tmpElem ) ) { isSuccess = FALSE; } } } } rpal_blob_free( pStack->blob ); rMutex_free( pStack->lock ); rpal_memory_free( pStack ); } } return isSuccess; }
RBOOL rStack_removeWith ( rStack stack, rStack_compareFunc compFunc, RPVOID ref, RPVOID pElem ) { RBOOL isRemoved = FALSE; _prStack pStack = (_prStack)stack; RU32 i = 0; RPVOID tmpElem = NULL; if( NULL != stack && NULL != compFunc ) { if( rMutex_lock( pStack->lock ) ) { for( i = 0; i < ( rpal_blob_getSize( pStack->blob ) / pStack->elemSize ); i++ ) { if( NULL != ( tmpElem = rpal_blob_arrElem( pStack->blob, pStack->elemSize, i ) ) ) { if( compFunc( tmpElem, ref ) ) { if( NULL != pElem ) { rpal_memory_memcpy( pElem, tmpElem, pStack->elemSize ); } if( rpal_blob_remove( pStack->blob, i * pStack->elemSize, pStack->elemSize ) ) { pStack->nElements--; isRemoved = TRUE; } break; } } } rMutex_unlock( pStack->lock ); } } return isRemoved; }
// Add an atom to the deny list, which is just a sortled list // on which we do binary searches. RPRIVATE RVOID addAtomToDeny ( RPU8 atomId ) { if( rMutex_lock( g_deniedMutex ) ) { rpal_blob_add( g_denied, atomId, HBS_ATOM_ID_SIZE ); rpal_sort_array( rpal_blob_getBuffer( g_denied ), rpal_blob_getSize( g_denied ) / HBS_ATOM_ID_SIZE, HBS_ATOM_ID_SIZE, (rpal_ordering_func)cmpAtoms ); g_lastDenyActivity = rpal_time_getGlobal(); rMutex_unlock( g_deniedMutex ); } }
static RVOID _elemToHash ( rSequence elem, CryptoLib_Hash* pHash ) { rBlob blob = NULL; if( rpal_memory_isValid( elem ) && NULL != pHash && NULL != ( blob = rpal_blob_create( 0, 0 ) ) ) { if( rSequence_serialise( elem, blob ) ) { CryptoLib_hash( (CryptoLib_Hash*)rpal_blob_getBuffer( blob ), rpal_blob_getSize( blob ), pHash ); } rpal_blob_free( blob ); } }
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 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; }
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 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 RBOOL postHttp ( RPCHAR location, RPCHAR params, RBOOL isEnforceCert, RPVOID* receivedData, RU32* receivedSize ) { RBOOL isSuccess = FALSE; CURL* curlCtx = NULL; RU32 timeout = ( 1000 * 10 ); RCHAR userAgent[] = "rpHCP"; rBlob dataReceived = NULL; RBOOL isDataReturned = FALSE; CURLcode curlError = CURLE_OK; if( NULL != location ) { if( NULL != ( dataReceived = rpal_blob_create( 0, 0 ) ) ) { if( NULL != ( curlCtx = curl_easy_init() ) ) { rpal_debug_info( "posting to %s", location ); if( CURLE_OK == ( curlError = curl_easy_setopt( curlCtx, CURLOPT_URL, location ) ) && CURLE_OK == ( curlError = curl_easy_setopt( curlCtx, CURLOPT_USERAGENT, userAgent ) ) && CURLE_OK == ( curlError = curl_easy_setopt( curlCtx, CURLOPT_POSTFIELDS, params ) ) && CURLE_OK == ( curlError = curl_easy_setopt( curlCtx, CURLOPT_WRITEFUNCTION, (RPVOID)_curlToBuffer ) ) && CURLE_OK == ( curlError = curl_easy_setopt( curlCtx, CURLOPT_WRITEDATA, (RPVOID)dataReceived ) ) && CURLE_OK == ( curlError = curl_easy_setopt( curlCtx, CURLOPT_NOSIGNAL, 1 ) ) ) { if( CURLE_OK == ( curlError = curl_easy_perform( curlCtx ) ) ) { isSuccess = TRUE; if( NULL != receivedData ) { *receivedData = rpal_blob_getBuffer( dataReceived ); isDataReturned = TRUE; } if( NULL != receivedSize ) { *receivedSize = rpal_blob_getSize( dataReceived ); } } else { rpal_debug_warning( "error performing post: %d", curlError ); } } else { rpal_debug_error( "error setting curl options: %d", curlError ); } curl_easy_cleanup( curlCtx ); } else { rpal_debug_error( "error creating curl context" ); } if( !isDataReturned ) { rpal_blob_free( dataReceived ); } else { rpal_blob_freeWrapperOnly( dataReceived ); } } } return isSuccess; }