//============================================================================= // rMutex API //============================================================================= rMutex rMutex_create ( ) { rMutex mutex = NULL; mutex = rpal_memory_alloc( sizeof( _rMutex ) ); if( rpal_memory_isValid( mutex ) ) { #ifdef RPAL_PLATFORM_WINDOWS ((_rMutex*)mutex)->hMutex = CreateMutex( NULL, FALSE, NULL ); if( NULL == ((_rMutex*)mutex)->hMutex ) { rpal_memory_free( mutex ); mutex = NULL; } #elif defined( RPAL_PLATFORM_LINUX ) || defined( RPAL_PLATFORM_MACOSX ) pthread_mutex_init( &((_rMutex*)mutex)->hMutex, NULL ); #endif } return mutex; }
//============================================================================= // rEvent API //============================================================================= rEvent rEvent_create ( RBOOL isManualReset ) { _rEvent* evt = NULL; evt = rpal_memory_alloc( sizeof( *evt ) ); if( rpal_memory_isValid( evt ) ) { #ifdef RPAL_PLATFORM_WINDOWS evt->waitCount = 0; evt->hEvent = CreateEvent( NULL, isManualReset, FALSE, NULL ); if( NULL == evt->hEvent ) { rpal_memory_free( evt ); evt = NULL; } #elif defined( RPAL_PLATFORM_LINUX ) || defined( RPAL_PLATFORM_MACOSX ) pthread_mutex_init( &evt->hMutex, NULL ); pthread_cond_init( &evt->hCond, NULL ); evt->isManualReset = isManualReset; evt->isOn = FALSE; #endif } return (rEvent)evt; }
//============================================================================= // Public API //============================================================================= HObs obsLib_new ( RU32 nMaxMem, ObsType searchType ) { _PHObs obs = NULL; obs = rpal_memory_alloc( sizeof( _HObs ) ); if( rpal_memory_isValid( obs ) ) { obs->root = newNode(); if( NULL != obs->root ) { obs->currentOffset = 0; obs->maxDepth = 0; obs->maxMem = nMaxMem; obs->searchType = searchType; obs->targetBuffer = NULL; obs->currentState = NULL; obs->curHits = NULL; obs->curDepth = 0; obs->nPatterns = 0; } else { rpal_memory_free( obs ); obs = NULL; } } return (HObs)obs; }
//============================================================================= // rRwLock API //============================================================================= rRwLock rRwLock_create ( ) { _rRwLock* lock; lock = rpal_memory_alloc( sizeof( *lock ) ); if( rpal_memory_isValid( lock ) ) { lock->evtCanRead = rEvent_create( TRUE ); lock->evtCanWrite = rEvent_create( TRUE ); lock->stateLock = rMutex_create(); lock->readCount = 0; if( !rpal_memory_isValid( lock->evtCanRead ) || !rpal_memory_isValid( lock->evtCanWrite ) || !rpal_memory_isValid( lock->stateLock ) ) { rEvent_free( lock->evtCanRead ); rEvent_free( lock->evtCanWrite ); rMutex_free( lock->stateLock ); rpal_memory_free( lock ); lock = NULL; } else { rEvent_set( lock->evtCanRead ); } } return (rRwLock)lock; }
//============================================================================= // rRefCount API //============================================================================= rRefCount rRefCount_create ( rRefCount_freeFunc freeFunc, RPVOID pElem, RU32 elemSize ) { _rRefCount* ref = NULL; ref = rpal_memory_alloc( sizeof( *ref ) ); if( rpal_memory_isValid( ref ) ) { ref->mutex = rMutex_create(); if( rpal_memory_isValid( ref->mutex ) ) { ref->count = 1; ref->freeFunc = freeFunc; ref->pElem = pElem; ref->elemSize = elemSize; } else { rpal_memory_free( ref ); ref = NULL; } } return (rRefCount)ref; }
rStack rStack_new ( RU32 elemSize ) { _prStack stack = NULL; stack = rpal_memory_alloc( sizeof( _rStack ) ); if( NULL != stack ) { stack->blob = rpal_blob_create( 0, 0 ); if( NULL != stack->blob ) { stack->nElements = 0; stack->elemSize = elemSize; if( NULL == ( stack->lock = rMutex_create() ) ) { rpal_blob_free( stack->blob ); rpal_memory_free( stack ); stack = NULL; } } else { rpal_memory_free( stack ); stack = NULL; } } return stack; }
RPRIVATE RVOID _processSnapshot ( rList snapshot, CryptoLib_Hash** prevSnapshot, RU32* prevNumElem, rpcm_tag elemTag, rpcm_tag notifTag ) { CryptoLib_Hash hash = { 0 }; RU32 i = 0; CryptoLib_Hash* tmpSnap = NULL; rSequence elem = NULL; if( NULL == prevSnapshot || NULL == prevNumElem ) { return; } if( NULL != ( tmpSnap = rpal_memory_alloc( sizeof( hash ) * rList_getNumElements( snapshot ) ) ) ) { i = 0; while( rList_getSEQUENCE( snapshot, elemTag, &elem ) ) { _elemToHash( elem, &hash ); tmpSnap[ i ] = hash; if( NULL != *prevSnapshot ) { if( ( -1 ) == rpal_binsearch_array( *prevSnapshot, *prevNumElem, sizeof( hash ), &hash, (rpal_ordering_func)_cmpHashes ) ) { hbs_timestampEvent( elem, 0 ); hbs_publish( notifTag, elem ); } } i++; } FREE_AND_NULL( *prevSnapshot ); *prevSnapshot = tmpSnap; *prevNumElem = i; tmpSnap = NULL; rpal_sort_array( *prevSnapshot, *prevNumElem, sizeof( hash ), (rpal_ordering_func)_cmpHashes ); } }
static RBOOL getStoreConf ( ) { RBOOL isSuccess = FALSE; RPU8 storeFile = NULL; RU32 storeFileSize = 0; rpHCPIdentStore* storeV2 = NULL; OBFUSCATIONLIB_DECLARE( store, RP_HCP_CONFIG_IDENT_STORE ); OBFUSCATIONLIB_TOGGLE( store ); if( rpal_file_read( (RPNCHAR)store, (RPVOID)&storeFile, &storeFileSize, FALSE ) ) { if( sizeof( rpHCPIdentStore ) <= storeFileSize ) { storeV2 = (rpHCPIdentStore*)storeFile; if( storeV2->enrollmentTokenSize == storeFileSize - sizeof( rpHCPIdentStore ) ) { isSuccess = TRUE; rpal_debug_info( "ident store found" ); if( NULL != ( g_hcpContext.enrollmentToken = rpal_memory_alloc( storeV2->enrollmentTokenSize ) ) ) { rpal_memory_memcpy( g_hcpContext.enrollmentToken, storeV2->enrollmentToken, storeV2->enrollmentTokenSize ); g_hcpContext.enrollmentTokenSize = storeV2->enrollmentTokenSize; } g_hcpContext.currentId = storeV2->agentId; } else { rpal_debug_warning( "inconsistent ident store, reseting" ); rpal_file_delete( (RPNCHAR)store, FALSE ); } } rpal_memory_free( storeFile ); } OBFUSCATIONLIB_TOGGLE( store ); // Set some always-correct defaults g_hcpContext.currentId.id.platformId = RP_HCP_ID_MAKE_PLATFORM( RP_HCP_PLATFORM_CURRENT_CPU, RP_HCP_PLATFORM_CURRENT_MAJOR, RP_HCP_PLATFORM_CURRENT_MINOR ); return isSuccess; }
RPCHAR liburl_encode ( RPCHAR str ) { RPCHAR encoded = NULL; RU32 index = 0; RU32 numToEncode = 0; RU32 len = 0; RCHAR escaped[ 3 ] = {0}; if( NULL != str ) { len = rpal_string_strlen( str ); for( index = 0; index < len; index++ ) { if( !isValidUrlChar( *(str + index) ) ) { numToEncode++; } } encoded = rpal_memory_alloc( len + sizeof(RCHAR) + numToEncode ); numToEncode = 0; if( rpal_memory_isValid( encoded ) ) { for( index = 0; index < len; index++ ) { if( !isValidUrlChar( *(str + index) ) ) { sprintf( (RPCHAR)&escaped, "%02X", *(str + index) ); *(encoded + index + numToEncode) = escaped[ 0 ]; numToEncode++; *(encoded + index + numToEncode) = escaped[ 1 ]; } else { *(encoded + index + numToEncode) = *(str + index); } } } } return encoded; }
static RBOOL assembleRanges ( rList mods, _MemRange** pRanges, RU32* pNRanges ) { RBOOL isSuccess = FALSE; _MemRange* memRanges = NULL; rSequence mod = NULL; RU64 base = 0; RU64 size = 0; RU32 i = 0; if( rpal_memory_isValid( mods ) && NULL != pRanges && NULL != pNRanges ) { if( NULL != ( memRanges = rpal_memory_alloc( sizeof( _MemRange ) * rList_getNumElements( mods ) ) ) ) { rList_resetIterator( mods ); while( rList_getSEQUENCE( mods, RP_TAGS_DLL, &mod ) ) { if( rSequence_getPOINTER64( mod, RP_TAGS_BASE_ADDRESS, &base ) && rSequence_getRU64( mod, RP_TAGS_MEMORY_SIZE, &size ) ) { memRanges[ i ].base = base; memRanges[ i ].size = size; i++; } } if( rpal_sort_array( memRanges, i, sizeof( _MemRange ), (rpal_ordering_func)rpal_order_RU64 ) ) { isSuccess = TRUE; *pRanges = memRanges; *pNRanges = i; } } } return isSuccess; }
StatefulEvent* SMEvent_new ( rpcm_tag eventType, rSequence data ) { StatefulEvent* event = NULL; rSequence wrapper = NULL; if( NULL != data ) { if( NULL != ( wrapper = rSequence_new() ) ) { if( NULL != ( event = rpal_memory_alloc( sizeof( *event ) ) ) ) { if( NULL != ( event->ref = rRefCount_create( (rRefCount_freeFunc)_freeEvent, event, sizeof( *event ) ) ) ) { if( rSequence_addSEQUENCE( wrapper, eventType, data ) ) { event->data = wrapper; event->eventType = eventType; rSequence_getTIMESTAMP( data, RP_TAGS_TIMESTAMP, &event->ts ); } else { rSequence_free( wrapper ); } } else { rpal_memory_free( event ); event = NULL; rSequence_free( wrapper ); } } else { rSequence_free( wrapper ); } } } return event; }
static ProcExtInfo* getProcContext ( RPU8 atomId ) { ProcExtInfo* procInfo = NULL; RU32 index = 0; if( (RU32)-1 != ( index = rpal_binsearch_array( g_procContexts->elements, g_procContexts->nElements, sizeof( ProcExtInfo* ), &atomId, (rpal_ordering_func)_cmpContext ) ) ) { procInfo = g_procContexts->elements[ index ]; } else { if( NULL != ( procInfo = rpal_memory_alloc( sizeof( *procInfo ) ) ) ) { rpal_memory_memcpy( procInfo->atomId, atomId, sizeof( procInfo->atomId ) ); if( !rpal_vector_add( g_procContexts, procInfo ) ) { rpal_memory_free( procInfo ); rpal_debug_error( "error adding new process to history" ); procInfo = NULL; } else { rpal_sort_array( g_procContexts->elements, g_procContexts->nElements, sizeof( ProcExtInfo* ), (rpal_ordering_func)_cmpContext ); } } } return procInfo; }
PObsNode newNode ( ) { PObsNode node = NULL; node = rpal_memory_alloc( sizeof( ObsNode ) + ( DEFAULT_ALLOCATED_PATTERNS * sizeof( RPVOID ) ) ); if( rpal_memory_isValid( node ) ) { node->nElements = 0; node->pSigsHit = NULL; node->startOffset = 0; node->nAllocated = DEFAULT_ALLOCATED_PATTERNS; } return node; }
rString rpal_stringbuffer_new ( RU32 initialSize, RU32 growBy ) { _rString* pStr = NULL; pStr = rpal_memory_alloc( sizeof( _rString ) ); if( rpal_memory_isValid( pStr ) ) { pStr->blob = rpal_blob_create( initialSize, growBy ); if( NULL == pStr->blob ) { rpal_memory_free( pStr ); pStr = NULL; } } return (rString)pStr; }
static StatefulMachine* _newMachineFrom ( StatefulMachineDescriptor* desc ) { StatefulMachine* machine = NULL; if( NULL != desc ) { if( NULL != ( machine = rpal_memory_alloc( sizeof( *machine ) ) ) ) { machine->desc = desc; machine->currentState = 0; if( NULL == ( machine->history = rpal_vector_new() ) ) { rpal_memory_free( machine ); machine = NULL; } } } return machine; }
PObsSig newSig ( RPU8 pPattern, RU32 patternSize, RPVOID context ) { PObsSig sig = NULL; if( NULL != pPattern && 0 != patternSize ) { sig = rpal_memory_alloc( sizeof( ObsSig ) + patternSize ); if( rpal_memory_isValid( sig ) ) { sig->pContext = context; sig->sigSize = patternSize; } } return sig; }
static HObs _getModuleDiskStringSample ( RPNCHAR modulePath, RU32* pLastScratch, rEvent isTimeToStop, LibOsPerformanceProfile* perfProfile ) { HObs sample = NULL; RPU8 scratch = NULL; rFile hFile = NULL; RU32 read = 0; RPU8 start = NULL; RPU8 end = NULL; RU32 toSkip = 0; RU32 longestLength = 0; RBOOL isUnicode = FALSE; RPU8 sampleNumber = 0; rBloom stringsSeen = NULL; RU64 readOffset = 0; UNREFERENCED_PARAMETER( isTimeToStop ); if( NULL != modulePath && NULL != pLastScratch ) { readOffset = *pLastScratch * _SCRATCH_SIZE; if( NULL != ( stringsSeen = rpal_bloom_create( _MAX_DISK_SAMPLE_SIZE, 0.0001 ) ) ) { if( NULL != ( scratch = rpal_memory_alloc( _SCRATCH_SIZE ) ) ) { if( rFile_open( modulePath, &hFile, RPAL_FILE_OPEN_EXISTING | RPAL_FILE_OPEN_READ ) ) { if( readOffset == rFile_seek( hFile, readOffset, rFileSeek_SET ) && 0 != ( read = rFile_readUpTo( hFile, _SCRATCH_SIZE, scratch ) ) ) { if( NULL != ( sample = obsLib_new( _MAX_DISK_SAMPLE_SIZE, 0 ) ) ) { ( *pLastScratch )++; start = scratch; end = scratch + read; // We parse for strings up to 'read', we don't care about the // memory boundary, we might truncate some strings but we're // sampling anyway. while( !rEvent_wait( isTimeToStop, 0 ) && ( start >= scratch ) && ( start >= scratch ) && ( start + _MIN_SAMPLE_STR_LEN ) < ( scratch + read ) && _MAX_DISK_SAMPLE_SIZE >= PTR_TO_NUMBER( sampleNumber ) ) { libOs_timeoutWithProfile( perfProfile, TRUE, isTimeToStop ); isUnicode = FALSE; if( _longestString( (RPCHAR)start, (RU32)( end - start ), &toSkip, &longestLength, &isUnicode ) && _MIN_SAMPLE_STR_LEN <= longestLength && _MAX_SAMPLE_STR_LEN >= longestLength ) { if( rpal_bloom_addIfNew( stringsSeen, start, longestLength ) ) { if( obsLib_addPattern( sample, start, longestLength, sampleNumber ) ) { sampleNumber++; } } } start += toSkip; } } } rFile_close( hFile ); } rpal_memory_free( scratch ); } rpal_bloom_destroy( stringsSeen ); } } return sample; }
static RU32 _checkMemoryForStringSample ( HObs sample, RU32 pid, RPVOID moduleBase, RU64 moduleSize, rEvent isTimeToStop, LibOsPerformanceProfile* perfProfile ) { RPU8 pMem = NULL; RU8* sampleList = NULL; RPU8 sampleNumber = 0; RU32 nSamples = 0; RU32 nSamplesFound = (RU32)(-1); UNREFERENCED_PARAMETER( isTimeToStop ); if( NULL != sample && 0 != pid && NULL != moduleBase && 0 != moduleSize && _MIN_DISK_SAMPLE_SIZE <= ( nSamples = obsLib_getNumPatterns( sample ) ) ) { if( NULL != ( sampleList = rpal_memory_alloc( sizeof( RU8 ) * nSamples ) ) ) { rpal_memory_zero( sampleList, sizeof( RU8 ) * nSamples ); if( processLib_getProcessMemory( pid, moduleBase, moduleSize, (RPVOID*)&pMem, TRUE ) ) { if( obsLib_setTargetBuffer( sample, pMem, (RU32)moduleSize ) ) { while( !rEvent_wait( isTimeToStop, 0 ) && obsLib_nextHit( sample, (RPVOID*)&sampleNumber, NULL ) ) { libOs_timeoutWithProfile( perfProfile, TRUE, isTimeToStop ); if( sampleNumber < (RPU8)NUMBER_TO_PTR( nSamples ) && 0 == sampleList[ (RU32)PTR_TO_NUMBER( sampleNumber ) ] ) { sampleList[ (RU32)PTR_TO_NUMBER( sampleNumber ) ] = 1; nSamplesFound++; } } } rpal_memory_free( pMem ); } else { rpal_debug_info( "failed to get memory for %d: 0x%016X ( 0x%016X ) error %d", pid, moduleBase, moduleSize, rpal_error_getLast() ); } rpal_memory_free( sampleList ); } } return nSamplesFound; }
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; }
RBOOL doBeacon ( RpHcp_ModuleId sourceModuleId, rList toSend, rList* pReceived ) { RBOOL isSuccess = FALSE; RPU8 receivedData = NULL; RU32 receivedSize = 0; RPU8 encodedData = NULL; RPU8 rawPayloadBuff = NULL; RU32 rawPayloadSize = 0; RU32 zError = 0; RPU8 signature = NULL; RPU8 payloadBuff = NULL; RU32 payloadSize = 0; RU8 sessionKey[ CRYPTOLIB_SYM_KEY_SIZE ] = {0}; RU8 sessionIv[ CRYPTOLIB_SYM_IV_SIZE ] = {0}; rString payloadToSend = NULL; RU32 decryptedSize = 0; RPU8 tmpBuff = NULL; RU64 tmpSize = 0; OBFUSCATIONLIB_DECLARE( url1, RP_HCP_CONFIG_HOME_URL_PRIMARY ); OBFUSCATIONLIB_DECLARE( url2, RP_HCP_CONFIG_HOME_URL_SECONDARY ); RPCHAR effectivePrimary = (RPCHAR)url1; RPCHAR effectiveSecondary = (RPCHAR)url2; rpal_debug_info( "called by module %d.", sourceModuleId ); // Pre-generate the session key and iv we want for the session CryptoLib_genRandomBytes( sessionKey, sizeof( sessionKey ) ); CryptoLib_genRandomBytes( sessionIv, sizeof( sessionIv ) ); // Assemble the stream to send payloadToSend = assembleOutboundStream( sourceModuleId, toSend, sessionKey, sessionIv ); if( NULL != payloadToSend ) { // Send the beacon if( NULL == g_hcpContext.primaryUrl ) { OBFUSCATIONLIB_TOGGLE( url1 ); OBFUSCATIONLIB_TOGGLE( url2 ); } else { effectivePrimary = g_hcpContext.primaryUrl; effectiveSecondary = g_hcpContext.secondaryUrl; } if( postHttp( effectivePrimary, rpal_stringbuffer_getString( payloadToSend ), FALSE, (RPVOID*)&receivedData, &receivedSize ) ) { isSuccess = TRUE; } else if( postHttp( effectiveSecondary, rpal_stringbuffer_getString( payloadToSend ), FALSE, (RPVOID*)&receivedData, &receivedSize ) ) { isSuccess = TRUE; rpal_debug_info( "beacon using secondary home." ); } else { rpal_debug_warning( "could not contact server." ); } if( NULL == g_hcpContext.primaryUrl ) { OBFUSCATIONLIB_TOGGLE( url1 ); OBFUSCATIONLIB_TOGGLE( url2 ); } if( isSuccess ) { isSuccess = FALSE; if( NULL != receivedData && 0 != receivedSize ) { if( NULL != pReceived ) { *pReceived = NULL; // Process the data received encodedData = findAndCapEncodedDataInBeacon( receivedData, receivedSize ); if( NULL != encodedData ) { if( stripBeaconEncoding( (RPCHAR)encodedData, &rawPayloadBuff, &rawPayloadSize ) ) { if( rawPayloadSize >= CRYPTOLIB_SIGNATURE_SIZE ) { // Verify signature signature = rawPayloadBuff; payloadBuff = signature + CRYPTOLIB_SIGNATURE_SIZE; payloadSize = rawPayloadSize - CRYPTOLIB_SIGNATURE_SIZE; if( verifyC2Signature( payloadBuff, payloadSize, signature ) ) { // Remove the symetric crypto using the session key if( CryptoLib_symDecrypt( payloadBuff, payloadSize, sessionKey, sessionIv, &decryptedSize ) ) { // Remove the compression tmpSize = rpal_ntoh32( *(RU32*)payloadBuff ); if( 0 != tmpSize && (-1) != tmpSize ) { tmpBuff = rpal_memory_alloc( (RSIZET)tmpSize ); if( rpal_memory_isValid( tmpBuff ) ) { if( Z_OK == ( zError = uncompress( tmpBuff, (uLongf*)&tmpSize, payloadBuff + sizeof( RU32 ), payloadSize - sizeof( RU32 ) ) ) ) { // Payload is valid, turn it into a sequence to return if( rList_deserialise( pReceived, tmpBuff, (RU32)tmpSize, NULL ) ) { rpal_debug_info( "success." ); isSuccess = TRUE; } else { rpal_debug_error( "could not deserialise list." ); } } else { rpal_debug_error( "could not decompress received data: %d (%d bytes).", zError, payloadSize ); } rpal_memory_free( tmpBuff ); } else { rpal_debug_error( "could not allocate memory for data received, asking for: %d.", tmpSize ); } } else { rpal_debug_error( "invalid size field in decrypted data." ); } } else { rpal_debug_error( "failed to decrypt received data." ); } } else { rpal_debug_error( "signature verification failed." ); } } else { rpal_debug_error( "stripped payload failed sanity check." ); } rpal_memory_free( rawPayloadBuff ); } else { rpal_debug_error( "could not strip BASE64 encoding." ); } } else { rpal_debug_error( "could not find the encoded data." ); } } else { rpal_debug_info( "not interested in the returned data." ); isSuccess = TRUE; } FREE_AND_NULL( receivedData ); receivedSize = 0; } else { rpal_debug_warning( "no data received from the server." ); isSuccess = FALSE; } } rpal_stringbuffer_free( payloadToSend ); } else { rpal_debug_error( "failed to generate payload for beacon." ); } return isSuccess; }
static RU32 _krnlSendReceive ( RU32 op, RPU8 pArgs, RU32 argsSize, RPU8 pResult, RU32 resultSize, RU32* pSizeUsed ) { RU32 error = (RU32)(-1); RU32 nRetries = 1; // Check whether this particular function is available on // this platform via kernel. if( op >= KERNEL_ACQ_OP_COUNT || !g_platform_availability[ op ] ) { return error; } if( rMutex_lock( g_km_mutex ) ) { while( 0 != nRetries ) { #ifdef RPAL_PLATFORM_MACOSX KernelAcqCommand cmd = { 0 }; cmd.pArgs = pArgs; cmd.argsSize = argsSize; cmd.pResult = pResult; cmd.resultSize = resultSize; cmd.pSizeUsed = pSizeUsed; fd_set readset = { 0 }; struct timeval timeout = { 0 }; int waitVal = 0; error = setsockopt( g_km_socket, SYSPROTO_CONTROL, op, &cmd, sizeof( cmd ) ); #elif defined( RPAL_PLATFORM_WINDOWS ) RU32 ioBufferSize = sizeof( KernelAcqCommand ) + argsSize; RPU8 ioBuffer = NULL; KernelAcqCommand* pCmd = NULL; if( NULL != ( ioBuffer = rpal_memory_alloc( ioBufferSize ) ) ) { pCmd = (KernelAcqCommand*)ioBuffer; pCmd->op = op; pCmd->dataOffset = sizeof( KernelAcqCommand ); pCmd->argsSize = argsSize; if( NULL != pArgs && 0 != argsSize ) { rpal_memory_memcpy( pCmd->data, pArgs, argsSize ); } if( DeviceIoControl( g_km_handle, (DWORD)IOCTL_EXCHANGE_DATA, ioBuffer, ioBufferSize, pResult, resultSize, (LPDWORD)pSizeUsed, NULL ) ) { error = 0; } else { error = rpal_error_getLast(); } rpal_memory_free( ioBuffer ); } else { error = RPAL_ERROR_NOT_ENOUGH_MEMORY; } #else UNREFERENCED_PARAMETER( op ); UNREFERENCED_PARAMETER( pArgs ); UNREFERENCED_PARAMETER( argsSize ); UNREFERENCED_PARAMETER( pResult ); UNREFERENCED_PARAMETER( resultSize ); UNREFERENCED_PARAMETER( pSizeUsed ); break; #endif // Success, return in. if( 0 == error ) { break; } // Looks like we had a failure, this may be a sign from the kernel // that it must unload, so we'll give it a chance and toggle our // connection. _kAcq_deinit( FALSE ); if( !_kAcq_init( FALSE ) ) { break; } nRetries--; } rMutex_unlock( g_km_mutex ); } return error; }
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; }
RBOOL processMessage ( rSequence seq ) { RBOOL isSuccess = FALSE; RU8 command = 0; rSequence idSeq = NULL; rpHCPId tmpId = { 0 }; rpHCPId emptyId = { 0 }; RU64 tmpTime = 0; rThread hQuitThread = 0; rpHCPIdentStore identStore = {0}; RPU8 token = NULL; RU32 tokenSize = 0; OBFUSCATIONLIB_DECLARE( store, RP_HCP_CONFIG_IDENT_STORE ); if( NULL != seq ) { if( rSequence_getRU8( seq, RP_TAGS_OPERATION, &command ) ) { rpal_debug_info( "Received command 0x%0X.", command ); switch( command ) { case RP_HCP_COMMAND_LOAD_MODULE: isSuccess = loadModule( &g_hcpContext, seq ); break; case RP_HCP_COMMAND_UNLOAD_MODULE: isSuccess = unloadModule( &g_hcpContext, seq ); break; case RP_HCP_COMMAND_SET_HCP_ID: if( rSequence_getSEQUENCE( seq, RP_TAGS_HCP_IDENT, &idSeq ) ) { tmpId = seqToHcpId( idSeq ); if( 0 != rpal_memory_memcmp( &emptyId, &tmpId, sizeof( emptyId ) ) ) { g_hcpContext.currentId = tmpId; OBFUSCATIONLIB_TOGGLE( store ); if( rSequence_getBUFFER( seq, RP_TAGS_HCP_ENROLLMENT_TOKEN, &token, &tokenSize ) ) { identStore.agentId = tmpId; if( saveHcpId( (RPNCHAR)store, &identStore, token, tokenSize ) ) { isSuccess = TRUE; } if( NULL != g_hcpContext.enrollmentToken ) { rpal_memory_free( g_hcpContext.enrollmentToken ); g_hcpContext.enrollmentToken = NULL; } if( NULL != ( g_hcpContext.enrollmentToken = rpal_memory_alloc( tokenSize ) ) ) { rpal_memory_memcpy( g_hcpContext.enrollmentToken, token, tokenSize ); g_hcpContext.enrollmentTokenSize = tokenSize; isSuccess = TRUE; } } else { rpal_debug_warning( "hcp id is missing token" ); } OBFUSCATIONLIB_TOGGLE( store ); } } break; case RP_HCP_COMMAND_SET_GLOBAL_TIME: if( rSequence_getTIMESTAMP( seq, RP_TAGS_TIMESTAMP, &tmpTime ) ) { rpal_time_setGlobalOffset( tmpTime - rpal_time_getLocal() ); isSuccess = TRUE; } break; case RP_HCP_COMMAND_QUIT: if( 0 != ( hQuitThread = rpal_thread_new( thread_quitAndCleanup, NULL ) ) ) { rpal_thread_free( hQuitThread ); isSuccess = TRUE; } break; case RP_HCP_COMMAND_UPGRADE: isSuccess = upgradeHcp( seq ); break; default: break; } if( isSuccess ) { rpal_debug_info( "Command was successful." ); } else { rpal_debug_warning( "Command was not successful." ); } } } return isSuccess; }
static RU32 _scanProcessWith ( RU32 pid, YaraMatchContext* matchContext, YR_RULES* rules, rEvent isTimeToStop ) { RU32 scanError = (RU32)(-1); rList modules = NULL; rSequence module = NULL; _MemRange* memRanges = NULL; RU32 i = 0; rList memoryMap = NULL; rSequence memoryRegion = NULL; RU8 memAccess = 0; RU64 mem = 0; RU64 memSize = 0; RPU8 buffer = NULL; // First pass is to scan known modules if( NULL != ( modules = processLib_getProcessModules( pid ) ) ) { rpal_debug_info( "scanning process %d module memory with yara", pid ); // We also generate an optimized list of module ranges for later if( NULL != ( memRanges = rpal_memory_alloc( sizeof( _MemRange ) * rList_getNumElements( modules ) ) ) ) { while( ( NULL == isTimeToStop || !rEvent_wait( isTimeToStop, MSEC_FROM_SEC( 5 ) ) ) && rList_getSEQUENCE( modules, RP_TAGS_DLL, &module ) ) { if( rSequence_getPOINTER64( module, RP_TAGS_BASE_ADDRESS, &mem ) && rSequence_getRU64( module, RP_TAGS_MEMORY_SIZE, &memSize ) ) { memRanges[ i ].base = mem; memRanges[ i ].size = memSize; i++; matchContext->regionBase = mem; matchContext->regionSize = memSize; matchContext->moduleInfo = module; if( processLib_getProcessMemory( pid, (RPVOID)NUMBER_TO_PTR( mem ), memSize, (RPVOID*)&buffer, TRUE ) ) { rpal_debug_info( "yara scanning module region of size 0x%lx", memSize ); if( NULL != rules || rMutex_lock( g_global_rules_mutex ) ) { if( ERROR_SUCCESS != ( scanError = yr_rules_scan_mem( NULL == rules ? g_global_rules : rules, buffer, (size_t)memSize, SCAN_FLAGS_FAST_MODE | SCAN_FLAGS_PROCESS_MEMORY, _yaraMemMatchCallback, matchContext, 60 ) ) ) { rpal_debug_warning( "Yara module scan error: %d 0x%lx 0x%lx: %d", pid, mem, memSize, scanError ); } if( NULL == rules ) { rMutex_unlock( g_global_rules_mutex ); } } rpal_memory_free( buffer ); rpal_debug_info( "finished region" ); } } } } rList_free( modules ); } // Optimize the memory ranges if( rpal_memory_isValid( memRanges ) && !rpal_sort_array( memRanges, i, sizeof( _MemRange ), (rpal_ordering_func)rpal_order_RU64 ) ) { rpal_memory_free( memRanges ); memRanges = NULL; } // Second pass is to go through executable non-module areas if( NULL != ( memoryMap = processLib_getProcessMemoryMap( pid ) ) ) { rpal_debug_info( "scanning process %d non-module memory with yara", pid ); while( ( NULL == isTimeToStop || !rEvent_wait(isTimeToStop, MSEC_FROM_SEC( 5 ) ) ) && rList_getSEQUENCE( memoryMap, RP_TAGS_MEMORY_REGION, &memoryRegion ) ) { if( rSequence_getPOINTER64( memoryRegion, RP_TAGS_BASE_ADDRESS, &mem ) && rSequence_getRU64( memoryRegion, RP_TAGS_MEMORY_SIZE, &memSize ) && rSequence_getRU8( memoryRegion, RP_TAGS_MEMORY_ACCESS, &memAccess ) && ( PROCESSLIB_MEM_ACCESS_EXECUTE == memAccess || PROCESSLIB_MEM_ACCESS_EXECUTE_READ == memAccess || PROCESSLIB_MEM_ACCESS_EXECUTE_READ_WRITE == memAccess || PROCESSLIB_MEM_ACCESS_EXECUTE_WRITE_COPY == memAccess ) ) { // If it's in a known module, skip if( (RU32)( -1 ) != rpal_binsearch_array_closest( memRanges, i, sizeof( _MemRange ), &mem, (rpal_ordering_func)rpal_order_RU64, TRUE ) ) { continue; } matchContext->regionBase = mem; matchContext->regionSize = memSize; matchContext->moduleInfo = NULL; if( processLib_getProcessMemory( pid, (RPVOID)NUMBER_TO_PTR(mem), memSize, (RPVOID*)&buffer, TRUE ) ) { rpal_debug_info( "yara scanning memory region of size 0x%lx", memSize ); if( NULL != rules || rMutex_lock( g_global_rules_mutex ) ) { if( ERROR_SUCCESS != ( scanError = yr_rules_scan_mem( NULL == rules ? g_global_rules : rules, buffer, (size_t)memSize, SCAN_FLAGS_FAST_MODE | SCAN_FLAGS_PROCESS_MEMORY, _yaraMemMatchCallback, matchContext, 60 ) ) ) { rpal_debug_warning( "Yara memory scan error: %d 0x%lx 0x%lx: %d", pid, mem, memSize, scanError ); } if( NULL == rules ) { rMutex_unlock( g_global_rules_mutex ); } } rpal_memory_free( buffer ); } } } rList_free( memoryMap ); } if( rpal_memory_isValid( memRanges ) ) { rpal_memory_free( memRanges ); } return scanError; }
static RBOOL getSnapshot ( processEntry* toSnapshot ) { RBOOL isSuccess = FALSE; RU32 i = 0; if( NULL != toSnapshot ) { rpal_memory_zero( toSnapshot, sizeof( g_snapshot_1 ) ); } if( NULL != toSnapshot ) { #ifdef RPAL_PLATFORM_WINDOWS HANDLE hSnapshot = NULL; PROCESSENTRY32W procEntry = { 0 }; procEntry.dwSize = sizeof( procEntry ); if( INVALID_HANDLE_VALUE != ( hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ) ) ) { if( Process32FirstW( hSnapshot, &procEntry ) ) { isSuccess = TRUE; do { if( 0 == procEntry.th32ProcessID ) { continue; } toSnapshot[ i ].pid = procEntry.th32ProcessID; toSnapshot[ i ].ppid = procEntry.th32ParentProcessID; i++; } while( Process32NextW( hSnapshot, &procEntry ) && MAX_SNAPSHOT_SIZE > i ); } CloseHandle( hSnapshot ); } #elif defined( RPAL_PLATFORM_LINUX ) RWCHAR procDir[] = _WCH( "/proc/" ); rDir hProcDir = NULL; rFileInfo finfo = {0}; if( rDir_open( (RPWCHAR)&procDir, &hProcDir ) ) { isSuccess = TRUE; while( rDir_next( hProcDir, &finfo ) && MAX_SNAPSHOT_SIZE > i ) { if( rpal_string_wtoi( (RPWCHAR)finfo.fileName, &( toSnapshot[ i ].pid ) ) && 0 != toSnapshot[ i ].pid ) { i++; } } rDir_close( hProcDir ); } #elif defined( RPAL_PLATFORM_MACOSX ) int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; struct kinfo_proc* infos = NULL; size_t size = 0; int ret = 0; int j = 0; if( 0 == ( ret = sysctl( mib, ARRAY_N_ELEM( mib ), infos, &size, NULL, 0 ) ) ) { if( NULL != ( infos = rpal_memory_alloc( size ) ) ) { while( 0 != ( ret = sysctl( mib, ARRAY_N_ELEM( mib ), infos, &size, NULL, 0 ) ) && ENOMEM == errno ) { if( NULL == ( infos = rpal_memory_realloc( infos, size ) ) ) { break; } } } } if( 0 == ret && NULL != infos ) { isSuccess = TRUE; size = size / sizeof( struct kinfo_proc ); for( j = 0; j < size; j++ ) { toSnapshot[ i ].pid = infos[ j ].kp_proc.p_pid; toSnapshot[ i ].ppid = infos[ j ].kp_eproc.e_ppid; i++; } if( NULL != infos ) { rpal_memory_free( infos ); infos = NULL; } } #endif } return isSuccess; }