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 ); } } }
static RVOID processFile ( rSequence notif ) { RPCHAR fileA = NULL; RPWCHAR fileW = NULL; RPU8 fileContent = NULL; RU32 fileSize = 0; CryptoLib_Hash hash = { 0 }; if( NULL != notif ) { obsLib_resetSearchState( matcherA ); obsLib_resetSearchState( matcherW ); if( ( rSequence_getSTRINGA( notif, RP_TAGS_FILE_PATH, &fileA ) && obsLib_setTargetBuffer( matcherA, fileA, ( rpal_string_strlen( fileA ) + 1 ) * sizeof( RCHAR ) ) && obsLib_nextHit( matcherA, NULL, NULL ) ) || ( rSequence_getSTRINGW( notif, RP_TAGS_FILE_PATH, &fileW ) && obsLib_setTargetBuffer( matcherW, fileW, ( rpal_string_strlenw( fileW ) + 1 ) * sizeof( RWCHAR ) ) && obsLib_nextHit( matcherW, NULL, NULL ) ) ) { // This means it's a file of interest. if( ( NULL != fileA && ( ( DOCUMENT_MAX_SIZE >= rpal_file_getSize( fileA, TRUE ) && rpal_file_read( fileA, (RPVOID*)&fileContent, &fileSize, TRUE ) && CryptoLib_hash( fileContent, fileSize, &hash ) ) || CryptoLib_hashFileA( fileA, &hash, TRUE ) ) ) || ( NULL != fileW && ( ( DOCUMENT_MAX_SIZE >= rpal_file_getSizew( fileW, TRUE ) && rpal_file_readw( fileW, (RPVOID*)&fileContent, &fileSize, TRUE ) && CryptoLib_hash( fileContent, fileSize, &hash ) ) || CryptoLib_hashFileW( fileW, &hash, TRUE ) ) ) ) { // We acquired the hash, either by reading the entire file in memory // which we will use for caching, or if it was too big by hashing it // sequentially on disk. rSequence_unTaintRead( notif ); rSequence_addBUFFER( notif, RP_TAGS_HASH, (RPU8)&hash, sizeof( hash ) ); notifications_publish( RP_TAGS_NOTIFICATION_NEW_DOCUMENT, notif ); } if( rMutex_lock( cacheMutex ) ) { if( NULL == fileContent || !rSequence_addBUFFER( notif, RP_TAGS_FILE_CONTENT, fileContent, fileSize ) || !HbsRingBuffer_add( documentCache, notif ) ) { rSequence_free( notif ); } rMutex_unlock( cacheMutex ); } else { rSequence_free( notif ); } if( NULL != fileContent ) { rpal_memory_free( fileContent ); } } else { rSequence_free( notif ); } } }
static rList beaconHome ( ) { rList response = NULL; rList exfil = NULL; rSequence msg = NULL; RU32 nExfilMsg = 0; rSequence tmpMessage = NULL; if( NULL != ( exfil = rList_new( RP_TAGS_MESSAGE, RPCM_SEQUENCE ) ) ) { if( NULL != ( msg = rSequence_new() ) ) { if( rSequence_addBUFFER( msg, RP_TAGS_HASH, g_hbs_state.currentConfigHash, CRYPTOLIB_HASH_SIZE ) ) { if( !rList_addSEQUENCE( exfil, msg ) ) { rSequence_free( msg ); msg = NULL; } tmpMessage = msg; } else { rSequence_free( msg ); msg = NULL; } } while( rQueue_remove( g_hbs_state.outQueue, &msg, NULL, 0 ) ) { nExfilMsg++; if( !rList_addSEQUENCE( exfil, msg ) ) { rSequence_free( msg ); } } rpal_debug_info( "%d messages ready for exfil.", nExfilMsg ); if( rpHcpI_beaconHome( exfil, &response ) ) { rpal_debug_info( "%d messages received from cloud.", rList_getNumElements( response ) ); } else if( g_hbs_state.maxQueueSize > rList_getEstimateSize( exfil ) ) { rpal_debug_info( "beacon failed, re-adding %d messages.", rList_getNumElements( exfil ) ); // We will attempt to re-add the existing messages back in the queue since this failed rList_resetIterator( exfil ); while( rList_getSEQUENCE( exfil, RP_TAGS_MESSAGE, &msg ) ) { // Ignore message we generate temporarily for the beacon if( tmpMessage == msg ) { rSequence_free( msg ); continue; } if( !rQueue_add( g_hbs_state.outQueue, msg, 0 ) ) { rSequence_free( msg ); } } rList_shallowFree( exfil ); exfil = NULL; } else { rpal_debug_warning( "beacon failed but discarded exfil because of its size." ); } if( NULL != exfil ) { rList_free( exfil ); } } return response; }
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; }
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 ); } } }