Exemple #1
0
void 
    test_handles
    (
        void
    )
{
    rList handles = NULL;
    rSequence handle = NULL;
    RU32 nHandles = 0;
    RU32 nNamedHandles = 0;
    RPWCHAR handleName = NULL;

    handles = processLib_getHandles( 0, FALSE, NULL );

    CU_ASSERT_PTR_NOT_EQUAL_FATAL( handles, NULL );

    while( rList_getSEQUENCE( handles, RP_TAGS_HANDLE_INFO, &handle ) )
    {
        nHandles++;
    }

    CU_ASSERT_TRUE( 100 < nHandles );

    rList_free( handles );

    handles = processLib_getHandles( 0, TRUE, NULL );

    CU_ASSERT_PTR_NOT_EQUAL_FATAL( handles, NULL );

    while( rList_getSEQUENCE( handles, RP_TAGS_HANDLE_INFO, &handle ) )
    {
        nNamedHandles++;

        CU_ASSERT_TRUE( rSequence_getSTRINGW( handle, RP_TAGS_HANDLE_NAME, &handleName ) );
        CU_ASSERT_TRUE( 0 != rpal_string_strlenw( handleName ) );
    }

    CU_ASSERT_TRUE( nNamedHandles < nHandles );

    rList_free( handles );
}
static
RBOOL
    _reportEvents
    (
        StatefulMachine* machine
    )
{
    RBOOL isSuccess = FALSE;

    rSequence wrapper = NULL;
    rList events = NULL;
    rSequence event = NULL;
    RU32 i = 0;

    if( NULL != machine )
    {
        if( NULL != ( wrapper = rSequence_new() ) )
        {
            if( NULL != ( events = rList_new( RP_TAGS_EVENT, RPCM_SEQUENCE ) ) )
            {
                for( i = 0; i < machine->history->nElements; i++ )
                {
                    event = ( (StatefulEvent*)machine->history->elements[ i ] )->data;
                    rList_addSEQUENCE( events, rSequence_duplicate( event ) );
                }

                if( !rSequence_addLIST( wrapper, RP_TAGS_EVENTS, events ) )
                {
                    rList_free( events );
                }
                else
                {
                    hbs_timestampEvent( wrapper, 0 );
                    isSuccess = hbs_publish( machine->desc->reportEventType, wrapper );
                }
            }

            rSequence_free( wrapper );
        }
    }

    return isSuccess;
}
Exemple #3
0
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 );
        }
    }
}
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 );
    }
}
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
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
    spotCheckNewProcesses
    (
        rEvent isTimeToStop,
        RPVOID ctx
    )
{
    RU32 pid = 0;
    RTIME timestamp = 0;
    RTIME timeToWait = 0;
    RTIME now = 0;
    rSequence newProcess = NULL;
    rList hollowedModules = NULL;
    LibOsPerformanceProfile perfProfile = { 0 };

    UNREFERENCED_PARAMETER( ctx );

    perfProfile.sanityCeiling = _SANITY_CEILING;
    perfProfile.lastTimeoutValue = _INITIAL_PROFILED_TIMEOUT;
    perfProfile.targetCpuPerformance = 0;
    perfProfile.globalTargetCpuPerformance = GLOBAL_CPU_USAGE_TARGET;
    perfProfile.enforceOnceIn = 7;
    perfProfile.timeoutIncrementPerSec = _PROFILE_INCREMENT;

    while( !rEvent_wait( isTimeToStop, 0 ) )
    {
        if( rQueue_remove( g_newProcessNotifications, &newProcess, NULL, MSEC_FROM_SEC( 5 ) ) )
        {
            if( rSequence_getRU32( newProcess, RP_TAGS_PROCESS_ID, &pid ) &&
                rSequence_getTIMESTAMP( newProcess, RP_TAGS_TIMESTAMP, &timestamp ) )
            {
                timeToWait = timestamp + _CHECK_SEC_AFTER_PROCESS_CREATION;
                now = rpal_time_getGlobalPreciseTime();
                if( now < timeToWait )
                {
                    timeToWait = timeToWait - now;
                    if( _CHECK_SEC_AFTER_PROCESS_CREATION < timeToWait )
                    {
                        // Sanity check
                        timeToWait = _CHECK_SEC_AFTER_PROCESS_CREATION;
                    }
                    rpal_thread_sleep( (RU32)timeToWait );
                }

                if( NULL != ( hollowedModules = _spotCheckProcess( isTimeToStop, pid, &perfProfile ) ) )
                {
                    if( !rSequence_addLIST( newProcess, RP_TAGS_MODULES, hollowedModules ) )
                    {
                        rList_free( hollowedModules );
                    }
                    else
                    {
                        hbs_publish( RP_TAGS_NOTIFICATION_MODULE_MEM_DISK_MISMATCH, 
                                     newProcess );
                    }
                }
            }

            rSequence_free( newProcess );
        }
    }

    return NULL;
}
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;
}
static
rList
    _spotCheckProcess
    (
        rEvent isTimeToStop,
        RU32 pid,
        LibOsPerformanceProfile* perfProfile
    )
{
    rList hollowedModules = NULL;

    rList modules = NULL;
    rSequence module = NULL;
    RPNCHAR modulePath = NULL;
    RU32 fileSize = 0;
    RU64 moduleBase = 0;
    RU64 moduleSize = 0;
    HObs diskSample = NULL;
    rSequence hollowedModule = NULL;
    RU32 lastScratchIndex = 0;
    RU32 nSamplesFound = 0;
    RU32 nSamplesTotal = 0;
    RU32 tmpSamplesFound = 0;
    RU32 tmpSamplesSize = 0;
    RTIME runTime = 0;

    rpal_debug_info( "spot checking process %d", pid );

    if( NULL != ( modules = processLib_getProcessModules( pid ) ) )
    {
        while( !rEvent_wait( isTimeToStop, 0 ) &&
               rList_getSEQUENCE( modules, RP_TAGS_DLL, &module ) )
        {
            libOs_timeoutWithProfile( perfProfile, FALSE, isTimeToStop );
            runTime = rpal_time_getLocal();

            modulePath = NULL;
            lastScratchIndex = 0;

            if( ( rSequence_getSTRINGN( module, 
                                        RP_TAGS_FILE_PATH, 
                                        &modulePath ) ) &&
                rSequence_getPOINTER64( module, RP_TAGS_BASE_ADDRESS, &moduleBase ) &&
                rSequence_getRU64( module, RP_TAGS_MEMORY_SIZE, &moduleSize ) )
            {
                if( 0 != ( fileSize = rpal_file_getSize( modulePath, TRUE ) ) )
                {
                    nSamplesFound = 0;
                    nSamplesTotal = 0;
                    tmpSamplesFound = (RU32)( -1 );

                    while( !rEvent_wait( isTimeToStop, 0 ) &&
                            NULL != ( diskSample = _getModuleDiskStringSample( modulePath,
                                                                                &lastScratchIndex,
                                                                                isTimeToStop,
                                                                                perfProfile ) ) )
                    {
                        libOs_timeoutWithProfile( perfProfile, TRUE, isTimeToStop );

                        tmpSamplesSize = obsLib_getNumPatterns( diskSample );

                        if( 0 != tmpSamplesSize )
                        {
                            tmpSamplesFound = _checkMemoryForStringSample( diskSample,
                                                                            pid,
                                                                            NUMBER_TO_PTR( moduleBase ),
                                                                            moduleSize,
                                                                            isTimeToStop,
                                                                            perfProfile );
                            obsLib_free( diskSample );

                            if( (RU32)( -1 ) == tmpSamplesFound )
                            {
                                break;
                            }

                            nSamplesFound += tmpSamplesFound;
                            nSamplesTotal += tmpSamplesSize;

                            if( _MIN_DISK_SAMPLE_SIZE <= nSamplesTotal &&
                                ( _MIN_SAMPLE_MATCH_PERCENT < ( (RFLOAT)nSamplesFound /
                                                                nSamplesTotal ) * 100 ) &&
                                _MIN_DISK_BIN_COVERAGE_PERCENT <= (RFLOAT)( ( lastScratchIndex *
                                                                                _SCRATCH_SIZE ) /
                                                                            fileSize ) * 100 )
                            {
                                break;
                            }
                        }
                        else
                        {
                            obsLib_free( diskSample );
                        }
                    }
                }
                else
                {
                    rpal_debug_info( "could not get file information, not checking" );
                }

                rpal_debug_info( "process hollowing check found a match in %d ( %d / %d ) from %d passes in %d sec", 
                                    pid,  
                                    nSamplesFound, 
                                    nSamplesTotal,
                                    lastScratchIndex,
                                    rpal_time_getLocal() - runTime );
                    
                if( !rEvent_wait( isTimeToStop, 0 ) &&
                    (RU32)(-1) != tmpSamplesFound &&
                    _MIN_DISK_SAMPLE_SIZE <= nSamplesTotal &&
                    ( ( (RFLOAT)nSamplesFound / nSamplesTotal ) * 100 ) < _MIN_SAMPLE_MATCH_PERCENT )
                {
                    rpal_debug_info( "sign of process hollowing found in process %d", pid );

                    if( NULL != ( hollowedModule = rSequence_duplicate( module ) ) )
                    {
                        if( !rList_addSEQUENCE( hollowedModules, hollowedModule ) )
                        {
                            rSequence_free( hollowedModule );
                        }
                    }
                }
            }
            else
            {
                rpal_debug_info( "module missing characteristic" );
            }
        }

        rList_free( modules );
    }
    else
    {
        rpal_debug_info( "failed to get process modules, might be dead" );
    }

    return hollowedModules;
}
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;
}
        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, &region ) )
                {
                    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;
}
Exemple #12
0
//=============================================================================
//  Entry Point
//=============================================================================
RU32
RPAL_THREAD_FUNC
    RpHcpI_mainThread
    (
        rEvent isTimeToStop
    )
{
    RU32 ret = 0;

    RU64 nextBeaconTime = 0;

    rList cloudMessages = NULL;
    rSequence msg = NULL;
    rList newConfigurations = NULL;
    rList newNotifications = NULL;
    RPU8 newConfigurationHash = NULL;
    RU32 newHashSize = 0;
    rSequence staticConfig = NULL;
    RU8* tmpBuffer = NULL;
    RU32 tmpSize = 0;

    FORCE_LINK_THAT( HCP_IFACE );

    CryptoLib_init();

    getPrivileges();

    // This is the event for the collectors, it is different than the
    // hbs proper event so that we can restart the collectors without
    // signaling hbs as a whole.
    if( NULL == ( g_hbs_state.isTimeToStop = rEvent_create( TRUE ) ) )
    {
        return (RU32)-1;
    }

    // By default, no collectors are running
    rEvent_set( g_hbs_state.isTimeToStop );

    // We attempt to load some initial config from the serialized
    // rSequence that can be patched in this binary.
    if( NULL != ( staticConfig = getStaticConfig() ) )
    {
        if( rSequence_getBUFFER( staticConfig, RP_TAGS_HBS_ROOT_PUBLIC_KEY, &tmpBuffer, &tmpSize ) )
        {
            hbs_cloud_pub_key = rpal_memory_duplicate( tmpBuffer, tmpSize );
            if( NULL == hbs_cloud_pub_key )
            {
                hbs_cloud_pub_key = hbs_cloud_default_pub_key;
            }
            rpal_debug_info( "loading hbs root public key from static config" );
        }

        if( rSequence_getRU32( staticConfig, RP_TAGS_MAX_QUEUE_SIZE, &g_hbs_state.maxQueueNum ) )
        {
            rpal_debug_info( "loading max queue size from static config" );
        }
        else
        {
            g_hbs_state.maxQueueNum = HBS_EXFIL_QUEUE_MAX_NUM;
        }

        if( rSequence_getRU32( staticConfig, RP_TAGS_MAX_SIZE, &g_hbs_state.maxQueueSize ) )
        {
            rpal_debug_info( "loading max queue num from static config" );
        }
        else
        {
            g_hbs_state.maxQueueSize = HBS_EXFIL_QUEUE_MAX_SIZE;
        }

        rSequence_free( staticConfig );
    }
    else
    {
        hbs_cloud_pub_key = hbs_cloud_default_pub_key;
        g_hbs_state.maxQueueNum = HBS_EXFIL_QUEUE_MAX_NUM;
        g_hbs_state.maxQueueSize = HBS_EXFIL_QUEUE_MAX_SIZE;
    }

    if( !rQueue_create( &g_hbs_state.outQueue, freeExfilEvent, g_hbs_state.maxQueueNum ) )
    {
        rEvent_free( g_hbs_state.isTimeToStop );
        return (RU32)-1;
    }

    // We simply enqueue a message to let the cloud know we're starting
    sendStartupEvent();

    while( !rEvent_wait( isTimeToStop, (RU32)nextBeaconTime ) )
    {
        nextBeaconTime = MSEC_FROM_SEC( HBS_DEFAULT_BEACON_TIMEOUT + 
                         ( rpal_rand() % HBS_DEFAULT_BEACON_TIMEOUT_FUZZ ) );

        if( NULL != ( cloudMessages = beaconHome() ) )
        {
            while( rList_getSEQUENCE( cloudMessages, RP_TAGS_MESSAGE, &msg ) )
            {
                // Cloud message indicating next requested beacon time, as a Seconds delta
                if( rSequence_getTIMEDELTA( msg, RP_TAGS_TIMEDELTA, &nextBeaconTime ) )
                {
                    nextBeaconTime = MSEC_FROM_SEC( nextBeaconTime );
                    rpal_debug_info( "received set_next_beacon" );
                }

                if( NULL == newConfigurations &&
                    rSequence_getLIST( msg, RP_TAGS_HBS_CONFIGURATIONS, &newConfigurations ) )
                {
                    rpal_debug_info( "received a new profile" );

                    if( rSequence_getBUFFER( msg, RP_TAGS_HASH, &newConfigurationHash, &newHashSize ) &&
                        newHashSize == CRYPTOLIB_HASH_SIZE )
                    {
                        newConfigurations = rList_duplicate( newConfigurations );
                        rpal_memory_memcpy( &( g_hbs_state.currentConfigHash ), 
                                            newConfigurationHash, 
                                            CRYPTOLIB_HASH_SIZE );
                        g_hbs_state.isProfilePresent = TRUE;
                    }
                    else
                    {
                        newConfigurations = NULL;
                        rpal_debug_error( "profile hash received is invalid" );
                    }
                }

                if( NULL == newNotifications &&
                    rSequence_getLIST( msg, RP_TAGS_HBS_CLOUD_NOTIFICATIONS, &newNotifications ) )
                {
                    rpal_debug_info( "received cloud events" );
                    newNotifications = rList_duplicate( newNotifications );
                }
            }

            rList_free( cloudMessages );
        }

        // If this is the initial boot and we have no profile yet, we'll load a dummy
        // blank profile and use our defaults.
        if( NULL == newConfigurations &&
            !g_hbs_state.isProfilePresent &&
            !rEvent_wait( isTimeToStop, 0 ) )
        {
            newConfigurations = rList_new( RP_TAGS_HCP_MODULES, RPCM_SEQUENCE );
            rpal_debug_info( "setting empty profile" );
        }

        if( NULL != newConfigurations )
        {
            // We try to be as responsive as possible when asked to quit
            // so if we happen to have received the signal during a beacon
            // we will action the quit instead of the config change.
            if( !rEvent_wait( isTimeToStop, 0 ) )
            {
                rpal_debug_info( "begining sensor update on new profile" );
                shutdownCollectors();

                updateCollectorConfigs( newConfigurations );
                rList_free( newConfigurations );
                newConfigurations = NULL;

                startCollectors();
            }
            else
            {
                rList_free( newConfigurations );
            }

            newConfigurations = NULL;
        }

        if( NULL != newNotifications )
        {
            if( !rEvent_wait( isTimeToStop, 0 ) )
            {
                publishCloudNotifications( newNotifications );
            }

            rList_free( newNotifications );

            newNotifications = NULL;
        }
    }

    // We issue one last beacon indicating we are stopping
    sendShutdownEvent();

    // Shutdown everything
    shutdownCollectors();

    // Cleanup the last few resources
    rEvent_free( g_hbs_state.isTimeToStop );
    rQueue_free( g_hbs_state.outQueue );

    CryptoLib_deinit();

    if( hbs_cloud_default_pub_key != hbs_cloud_pub_key &&
        NULL != hbs_cloud_pub_key )
    {
        rpal_memory_free( hbs_cloud_pub_key );
        hbs_cloud_pub_key = NULL;
    }

    return ret;
}
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;
}
Exemple #14
0
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_find_string
    (
        rpcm_tag eventType,
        rSequence event
    )
{
    RU32 pid = 0;
    RU32 currentPid = 0;
    rList searchStrings = NULL;
    rList processes = NULL;
    rSequence process = NULL;
    processLibProcEntry* pids = NULL;
    RU32 nCurrent = 0;
    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 ) ) ) ) &&
            rSequence_getLIST( event, RP_TAGS_STRINGSW, &searchStrings ) )
        {
            currentPid = processLib_getCurrentPid();

            if( NULL != ( processes = rList_new( RP_TAGS_PROCESS, RPCM_SEQUENCE ) ) )
            {
                if( 0 != pid )
                {
                    if( NULL != ( process = _findStringsInProcess( pid, 
                                                                   searchStrings, 
                                                                   minLength, 
                                                                   maxLength ) ) )
                    {
                        if( !rList_addSEQUENCE( processes, process ) )
                        {
                            rSequence_free( process );
                        }
                    }
                }
                else
                {
                    if( NULL != ( pids = processLib_getProcessEntries( TRUE ) ) )
                    {
                        while( 0 != pids[ nCurrent ].pid )
                        {
                            if( currentPid != pids[ nCurrent ].pid )
                            {
                                if( NULL != ( process = _findStringsInProcess( pids[ nCurrent ].pid, 
                                                                               searchStrings, 
                                                                               minLength, 
                                                                               maxLength ) ) )
                                {
                                    if( !rList_addSEQUENCE( processes, process ) )
                                    {
                                        rSequence_free( process );
                                    }
                                }
                            }

                            nCurrent++;
                        }

                        rpal_memory_free( pids );
                    }
                }

                if( !rSequence_addLIST( event, RP_TAGS_PROCESSES, processes ) )
                {
                    rList_free( processes );
                }
            }
        }

        hbs_timestampEvent( event, 0 );
        hbs_publish( RP_TAGS_NOTIFICATION_MEM_FIND_STRING_REP, event );
    }
}
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, &region ) )
                {
                    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 );
    }
}
Exemple #17
0
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
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;
}
//=============================================================================
// PROFILERS
//=============================================================================
RPRIVATE
RBOOL
    profile_processes
    (

    )
{
    RBOOL isSuccess = FALSE;

    processLibProcEntry* processes = NULL;
    processLibProcEntry* process = NULL;
    rSequence processInfo = NULL;
    RPWCHAR processName = NULL;
    rList modules = NULL;
    rSequence module = NULL;
    RPWCHAR moduleName = NULL;

    _Profile profile = { 0 };
    RBOOL isProfileReady = FALSE;
    RBOOL isChanged = FALSE;

    if( NULL != ( processes = processLib_getProcessEntries( FALSE ) ) )
    {
        process = processes;
        while( 0 != process->pid )
        {
            if( NULL != ( processInfo = processLib_getProcessInfo( process->pid, NULL ) ) )
            {
                if( rSequence_getSTRINGW( processInfo, RP_TAGS_FILE_PATH, &processName ) )
                {
                    isProfileReady = FALSE;

                    if( rpal_btree_search( g_profiles_process_module, &processName, &profile, FALSE ) )
                    {
                        isProfileReady = TRUE;
                    }
                    else
                    {
                        if( _init_profile_strw_strw( g_profiles_process_module, processName ) )
                        {
                            if( rpal_btree_add( g_profiles_process_module, &profile, FALSE ) )
                            {
                                isProfileReady = TRUE;
                            }
                            else
                            {
                                _clean_profile( &profile );
                            }
                        }
                    }
                    
                    if( isProfileReady )
                    {
                        if( NULL != ( modules = processLib_getProcessModules( process->pid ) ) )
                        {
                            while( rList_getSEQUENCE( modules, RP_TAGS_DLL, &module ) )
                            {
                                if( rSequence_getSTRINGW( module, RP_TAGS_FILE_PATH, &moduleName ) )
                                {
                                    if( !rpal_btree_search( profile.relations, &moduleName, NULL, FALSE ) &&
                                        rpal_btree_add( profile.relations, &moduleName, FALSE ) )
                                    {
                                        isChanged = TRUE;
                                        if( _isProfileStable( &profile ) )
                                        {
                                            rpal_debug_info( "Stable profile change!" );
                                        }
                                    }
                                }
                            }

                            rList_free( modules );
                        }

                        if( _recordGeneration( &profile, isChanged ) )
                        {
                            rpal_btree_update( g_profiles_process_module, &profile, &profile, FALSE );
                        }
                    }
                }

                rSequence_free( processInfo );
            }

            process++;
        }


        rpal_memory_free( processes );
    }

    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 );
}
static
RVOID
    getDocument
    (
        rpcm_tag notifId,
        rSequence notif
    )
{
    rSequence tmp = NULL;
    DocSearchContext ctx = { 0 };
    RU32 hashSize = 0;
    rList foundDocs = NULL;
    RBOOL isAAlloced = FALSE;
    RBOOL isWAlloced = FALSE;
    UNREFERENCED_PARAMETER( notifId );

    if( NULL != notif )
    {
        if( !rSequence_getSTRINGA( notif, RP_TAGS_STRING_PATTERN, &ctx.exprA ) )
        {
            ctx.exprA = NULL;
        }
        if( !rSequence_getSTRINGW( notif, RP_TAGS_STRING_PATTERN, &ctx.exprW ) )
        {
            ctx.exprW = NULL;
        }
        if( NULL != ctx.exprA && NULL == ctx.exprW )
        {
            ctx.exprW = rpal_string_atow( ctx.exprA );
            isWAlloced = TRUE;
        }
        if( NULL != ctx.exprW && NULL == ctx.exprA )
        {
            ctx.exprA = rpal_string_wtoa( ctx.exprW );
            isAAlloced = TRUE;
        }
        if( !rSequence_getBUFFER( notif, RP_TAGS_HASH, (RPU8*)&ctx.pHash, &hashSize ) ||
            sizeof( *ctx.pHash ) != hashSize )
        {
            // Unexpected hash size, let's not gamble 
            ctx.pHash = NULL;
        }
    }

    if( rMutex_lock( cacheMutex ) )
    {
        if( NULL != ( foundDocs = rList_new( RP_TAGS_FILE_INFO, RPCM_SEQUENCE ) ) )
        {
            while( HbsRingBuffer_find( documentCache, (HbsRingBufferCompareFunc)findDoc, &ctx, &tmp ) )
            {
                // TODO: optimize this since if we're dealing with large files
                // we will be temporarily using large amounts of duplicate memory.
                // We just need to do some shallow free of the datastructures
                // somehow.
                if( NULL != ( tmp = rSequence_duplicate( tmp ) ) )
                {
                    if( !rList_addSEQUENCE( foundDocs, tmp ) )
                    {
                        rSequence_free( tmp );
                    }
                }
            }

            if( !rSequence_addLIST( notif, RP_TAGS_FILES, foundDocs ) )
            {
                rList_free( foundDocs );
            }
        }

        rMutex_unlock( cacheMutex );

        notifications_publish( RP_TAGS_NOTIFICATION_GET_DOCUMENT_REP, notif );
    }

    if( isAAlloced )
    {
        rpal_memory_free( ctx.exprA );
    }
    if( isWAlloced )
    {
        rpal_memory_free( ctx.exprW );
    }
}
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, &region ) ) )
            {
                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, &region ) )
                                            {
                                                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
    osTrackerDiffThread
    (
        rEvent isTimeToStop,
        RPVOID ctx
    )
{
    CryptoLib_Hash* prevServices = NULL;
    RU32 prevNServices = 0;

    CryptoLib_Hash* prevDrivers = NULL;
    RU32 prevNDrivers = 0;

    CryptoLib_Hash* prevAutoruns = NULL;
    RU32 prevNAutoruns = 0;

    rList snapshot = NULL;

    UNREFERENCED_PARAMETER( ctx );

    while( !rEvent_wait( isTimeToStop, g_diff_timeout ) )
    {
        rpal_debug_info( "looking for changes in os snapshots" );

        if( NULL != ( snapshot = libOs_getServices( TRUE ) ) )
        {
            _processSnapshot( snapshot, 
                              &prevServices, 
                              &prevNServices,
                              RP_TAGS_SVC, 
                              RP_TAGS_NOTIFICATION_SERVICE_CHANGE );

            rList_free( snapshot );
        }

        if( rEvent_wait( isTimeToStop, MSEC_FROM_SEC( 5 ) ) )
        {
            break;
        }

        if( NULL != ( snapshot = libOs_getDrivers( TRUE ) ) )
        {
            _processSnapshot( snapshot,
                              &prevDrivers,
                              &prevNDrivers,
                              RP_TAGS_SVC,
                              RP_TAGS_NOTIFICATION_DRIVER_CHANGE );

            rList_free( snapshot );
        }

        if( rEvent_wait( isTimeToStop, MSEC_FROM_SEC( 5 ) ) )
        {
            break;
        }

        if( NULL != ( snapshot = libOs_getAutoruns( TRUE ) ) )
        {
            _processSnapshot( snapshot,
                              &prevAutoruns,
                              &prevNAutoruns,
                              RP_TAGS_SVC,
                              RP_TAGS_NOTIFICATION_AUTORUN_CHANGE );

            rList_free( snapshot );
        }

        rpal_debug_info( "finished updating snapshots" );
    }

    FREE_AND_NULL( prevServices );
    FREE_AND_NULL( prevDrivers );
    FREE_AND_NULL( prevAutoruns );

    return NULL;
}
RPRIVATE
RPVOID
    osTrackerDiffThread
    (
        rEvent isTimeToStop,
        RPVOID ctx
    )
{
    CryptoLib_Hash* prevServices = NULL;
    RU32 prevNServices = 0;

    CryptoLib_Hash* prevDrivers = NULL;
    RU32 prevNDrivers = 0;

    CryptoLib_Hash* prevAutoruns = NULL;
    RU32 prevNAutoruns = 0;

    rList snapshot = NULL;

    UNREFERENCED_PARAMETER( ctx );

    while( !rEvent_wait( isTimeToStop, g_diff_timeout ) )
    {
        rpal_debug_info( "looking for changes in os snapshots" );

        if( NULL != ( snapshot = libOs_getServices( TRUE ) ) )
        {
            _processSnapshot( snapshot, 
                              &prevServices, 
                              &prevNServices,
                              RP_TAGS_SVC, 
                              RP_TAGS_NOTIFICATION_SERVICE_CHANGE );

            rList_free( snapshot );
        }

        if( rEvent_wait( isTimeToStop, MSEC_FROM_SEC( 5 ) ) )
        {
            break;
        }

#ifdef RPAL_PLATFORM_WINDOWS
// Drivers are only available on Windows
        if( NULL != ( snapshot = libOs_getDrivers( TRUE ) ) )
        {
            _processSnapshot( snapshot,
                              &prevDrivers,
                              &prevNDrivers,
                              RP_TAGS_SVC,
                              RP_TAGS_NOTIFICATION_DRIVER_CHANGE );

            rList_free( snapshot );
        }

        if( rEvent_wait( isTimeToStop, MSEC_FROM_SEC( 5 ) ) )
        {
            break;
        }
#endif

#if defined( RPAL_PLATFORM_WINDOWS ) || defined( RPAL_PLATFORM_MACOSX )
// Services are currently only available on OSX and Windows
        if( NULL != ( snapshot = libOs_getAutoruns( TRUE ) ) )
        {
            _processSnapshot( snapshot,
                              &prevAutoruns,
                              &prevNAutoruns,
                              RP_TAGS_SVC,
                              RP_TAGS_NOTIFICATION_AUTORUN_CHANGE );

            rList_free( snapshot );
        }

        rpal_debug_info( "finished updating snapshots" );
#endif
    }

    FREE_AND_NULL( prevServices );
    FREE_AND_NULL( prevDrivers );
    FREE_AND_NULL( prevAutoruns );

    return NULL;
}