static
RVOID
    processGenericSnapshot
    (
        rpcm_tag notifType,
        rSequence event
    )
{
    rList entityList = NULL;
    rSequence entity = NULL;

    UNREFERENCED_PARAMETER( notifType );

    if( rpal_memory_isValid( event ) )
    {
        if( rSequence_getLIST( event, RP_TAGS_AUTORUNS, &entityList ) ||
            rSequence_getLIST( event, RP_TAGS_SVCS, &entityList ) ||
            rSequence_getLIST( event, RP_TAGS_PROCESSES, &entityList ) )
        {
            // Go through the elements, whatever tag
            while( rList_getSEQUENCE( entityList, RPCM_INVALID_TAG, &entity ) )
            {
                processHashedEvent( notifType, entity );
            }
        }
    }
}
Beispiel #2
0
void 
    test_modules
    (
        void
    )
{
    processLibProcEntry* entries = NULL;
    RU32 entryIndex = 0;
    rList mods = NULL;
    rSequence mod = NULL;
    RPWCHAR path = NULL;

    entries = processLib_getProcessEntries( TRUE );

    CU_ASSERT_PTR_NOT_EQUAL_FATAL( entries, NULL );

    CU_ASSERT_NOT_EQUAL_FATAL( entries[ entryIndex ].pid, 0 );

    mods = processLib_getProcessModules( entries[ entryIndex ].pid );

    CU_ASSERT_PTR_NOT_EQUAL( mods, NULL );

    CU_ASSERT_TRUE( rList_getSEQUENCE( mods, RP_TAGS_DLL, &mod ) );

    CU_ASSERT_TRUE( rSequence_getSTRINGW( mod, RP_TAGS_FILE_PATH, &path ) );

    CU_ASSERT_PTR_NOT_EQUAL( path, NULL );
    CU_ASSERT_NOT_EQUAL( rpal_string_strlenw( path ), 0 );

    rSequence_free( mods );

    rpal_memory_free( entries );
}
Beispiel #3
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 );
}
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
    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;
}
Beispiel #6
0
static RBOOL
    updateCollectorConfigs
    (
        rList newConfigs
    )
{
    RBOOL isSuccess = FALSE;
    RU8 unused = 0;
    RU32 i = 0;
    rSequence tmpConf = NULL;
    RU32 confId = 0;

    if( rpal_memory_isValid( newConfigs ) )
    {
        rpal_debug_info( "updating collector configurations." );
        
        for( i = 0; i < ARRAY_N_ELEM( g_collectors ); i++ )
        {
            if( NULL != g_collectors[ i ].conf )
            {
                rpal_debug_info( "freeing collector %d config.", i );
                rSequence_free( g_collectors[ i ].conf );
                g_collectors[ i ].conf = NULL;
            }
        }

        while( rList_getSEQUENCE( newConfigs, RP_TAGS_HBS_CONFIGURATION, &tmpConf ) )
        {
            if( rSequence_getRU32( tmpConf, RP_TAGS_HBS_CONFIGURATION_ID, &confId ) &&
                confId < ARRAY_N_ELEM( g_collectors ) )
            {
                if( rSequence_getRU8( tmpConf, RP_TAGS_IS_DISABLED, &unused ) )
                {
                    g_collectors[ confId ].isEnabled = FALSE;
                }
                else
                {
                    g_collectors[ confId ].isEnabled = TRUE;
                    g_collectors[ confId ].conf = rSequence_duplicate( tmpConf );
                    rpal_debug_info( "set new collector %d config.", confId );
                }
            }
        }
                
        isSuccess = TRUE;
    }

    return isSuccess;
}
Beispiel #7
0
void 
    test_memmap
    (
        void
    )
{
    processLibProcEntry* entries = NULL;
    RU32 entryIndex = 0;
    rList regions = NULL;
    rSequence region = NULL;
    RU32 nRegions = 0;
    
    RU8 type = 0;
    RU8 protect = 0;
    RU64 ptr = 0;
    RU64 size = 0;

    entries = processLib_getProcessEntries( TRUE );

    CU_ASSERT_PTR_NOT_EQUAL_FATAL( entries, NULL );

    CU_ASSERT_NOT_EQUAL_FATAL( entries[ entryIndex ].pid, 0 );

    regions = processLib_getProcessMemoryMap( entries[ entryIndex ].pid );

    CU_ASSERT_PTR_NOT_EQUAL( regions, NULL );

    while( rList_getSEQUENCE( regions, RP_TAGS_MEMORY_REGION, &region ) )
    {
        CU_ASSERT_TRUE( rSequence_getRU8( region, RP_TAGS_MEMORY_TYPE, &type ) );
        CU_ASSERT_TRUE( rSequence_getRU8( region, RP_TAGS_MEMORY_ACCESS, &protect ) );
        CU_ASSERT_TRUE( rSequence_getPOINTER64( region, RP_TAGS_BASE_ADDRESS, &ptr ) );
        CU_ASSERT_TRUE( rSequence_getRU64( region, RP_TAGS_MEMORY_SIZE, &size ) );
        nRegions++;
    }

    CU_ASSERT_TRUE( 2 < nRegions ); 

    rSequence_free( regions );

    rpal_memory_free( entries );
}
static
RBOOL
    isMemInModule
    (
        RU64 memBase,
        RU64 memSize,
        rList modules
    )
{
    RBOOL isInMod = FALSE;
    rSequence mod = NULL;

    RU64 modBase = 0;
    RU64 modSize = 0;

    if( NULL != modules )
    {
        rList_resetIterator( modules );

        while( rList_getSEQUENCE( modules, RP_TAGS_DLL, &mod ) )
        {
            if( rSequence_getPOINTER64( mod, RP_TAGS_BASE_ADDRESS, &modBase ) &&
                rSequence_getRU64( mod, RP_TAGS_MEMORY_SIZE, &modSize ) )
            {
                if( IS_WITHIN_BOUNDS( NUMBER_TO_PTR( memBase ), memSize, NUMBER_TO_PTR( modBase ), modSize ) )
                {
                    isInMod = TRUE;
                    break;
                }
            }
        }

        rList_resetIterator( modules );
    }

    return isInMod;
}
Beispiel #9
0
void 
    test_servicesList
    (
        void
    )
{
    rList svcs = NULL;
    rSequence svc = NULL;
    RU32 type = PROCESSLIB_SVCS;
#if defined( RPAL_PLATFORM_WINDOWS ) || defined( RPAL_PLATFORM_LINUX )
    RPWCHAR svcName = NULL;
#elif defined( RPAL_PLATFORM_MACOSX )
    RPCHAR svcName = NULL;
#endif

    svcs = processLib_getServicesList( type );

    CU_ASSERT_PTR_NOT_EQUAL_FATAL( svcs, NULL );

    CU_ASSERT_TRUE( rList_getSEQUENCE( svcs, RP_TAGS_SVC, &svc ) );

#if defined( RPAL_PLATFORM_WINDOWS ) || defined( RPAL_PLATFORM_LINUX )
    CU_ASSERT_TRUE( rSequence_getSTRINGW( svc, RP_TAGS_SVC_NAME, &svcName ) );

    CU_ASSERT_PTR_NOT_EQUAL( svcName, NULL );

    CU_ASSERT_NOT_EQUAL( rpal_string_strlenw( svcName ), 0 );
#elif defined( RPAL_PLATFORM_MACOSX )
    CU_ASSERT_TRUE( rSequence_getSTRINGA( svc, RP_TAGS_SVC_NAME, &svcName ) );

    CU_ASSERT_PTR_NOT_EQUAL( svcName, NULL );

    CU_ASSERT_NOT_EQUAL( rpal_string_strlen( svcName ), 0 );
#endif

    rSequence_free( svcs );
}
Beispiel #10
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;
}
Beispiel #11
0
static RVOID
    publishCloudNotifications
    (
        rList notifications
    )
{
    rSequence notif = NULL;
    RPU8 buff = NULL;
    RU32 buffSize = 0;
    RPU8 sig = NULL;
    RU32 sigSize = 0;
    rpHCPId curId = { 0 };
    rSequence cloudEvent = NULL;
    rSequence targetId = { 0 };
    RU32 eventId = 0;
    rSequence localEvent = NULL;
    RU64 expiry = 0;
    rpHCPId tmpId = { 0 };
    rSequence receipt = NULL;

    while( rList_getSEQUENCE( notifications, RP_TAGS_HBS_CLOUD_NOTIFICATION, &notif ) )
    {
        cloudEvent = NULL;

        if( rSequence_getBUFFER( notif, RP_TAGS_BINARY, &buff, &buffSize ) &&
            rSequence_getBUFFER( notif, RP_TAGS_SIGNATURE, &sig, &sigSize ) )
        {
            if( CryptoLib_verify( buff, buffSize, hbs_cloud_pub_key, sig ) )
            {
                if( !rpHcpI_getId( &curId ) )
                {
                    rpal_debug_error( "error getting current id for cloud notifications." );
                }
                else
                {
                    if( !rSequence_deserialise( &cloudEvent, buff, buffSize, NULL ) )
                    {
                        cloudEvent = NULL;
                        rpal_debug_warning( "error deserializing cloud event." );
                    }
                }
            }
            else
            {
                rpal_debug_warning( "cloud event signature invalid." );
            }
        }

        if( rpal_memory_isValid( cloudEvent ) )
        {
            if( rSequence_getSEQUENCE( cloudEvent, RP_TAGS_HCP_ID, &targetId ) &&
                rSequence_getRU32( cloudEvent, RP_TAGS_HBS_NOTIFICATION_ID, &eventId ) &&
                rSequence_getSEQUENCE( cloudEvent, RP_TAGS_HBS_NOTIFICATION, &localEvent ) )
            {
                rSequence_getTIMESTAMP( cloudEvent, RP_TAGS_EXPIRY, &expiry );

                tmpId = rpHcpI_seqToHcpId( targetId );

                curId.id.configId = 0;
                tmpId.id.configId = 0;
                
                if( NULL != ( receipt = rSequence_new() ) )
                {
                    if( rSequence_addSEQUENCE( receipt, 
                                               RP_TAGS_HBS_CLOUD_NOTIFICATION, 
                                               rSequence_duplicate( cloudEvent ) ) )
                    {
                        if( !rQueue_add( g_hbs_state.outQueue, receipt, 0 ) )
                        {
                            rSequence_free( receipt );
                            receipt = NULL;
                        }
                    }
                    else
                    {
                        rSequence_free( receipt );
                        receipt = NULL;
                    }
                }

                if( curId.raw == tmpId.raw &&
                    rpal_time_getGlobal() <= expiry )
                {
                    if( !notifications_publish( eventId, localEvent ) )
                    {
                        rpal_debug_error( "error publishing event from cloud." );
                    }
                }
                else
                {
                    rpal_debug_warning( "event expired or for wrong id." );
                }
            }

            if( rpal_memory_isValid( cloudEvent ) )
            {
                rSequence_free( cloudEvent );
                cloudEvent = NULL;
            }
        }
    }
}
Beispiel #12
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
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;
}
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;
}
RBOOL
    collector_22_init
    (
        HbsState* hbsState,
        rSequence config
    )
{
    RBOOL isSuccess = FALSE;
    rList patterns = NULL;
    rSequence pattern = NULL;
    RPCHAR strA = NULL;
    RPWCHAR strW = NULL;
    RPNCHAR tmpN = NULL;
    RU8 patternId = 0;
    RU32 i = 0;

    if( NULL != hbsState &&
        NULL != ( g_extensions = obsLib_new( 0, 0 ) ) )
    {
        if( rSequence_getLIST( config, RP_TAGS_PATTERNS, &patterns ) )
        {
            while( rList_getSEQUENCE( patterns, RP_TAGS_RULE, &pattern ) )
            {
                if( rSequence_getRU8( pattern, RP_TAGS_RULE_NAME, &patternId ) )
                {
                    if( 64 < patternId || 0 == patternId )
                    {
                        rpal_debug_critical( "rule id must be below 64 and 1-based." );
                        continue;
                    }

                    // Base the pattern id to 0
                    patternId--;

                    if( rSequence_getSTRINGA( pattern, RP_TAGS_EXTENSION, &strA ) &&
                        NULL != ( tmpN = rpal_string_aton( strA ) ) )
                    {
                        _addPattern( g_extensions, tmpN, TRUE, NUMBER_TO_PTR( patternId ) );
                        rpal_memory_free( tmpN );
                    }

                    if( rSequence_getSTRINGW( pattern, RP_TAGS_EXTENSION, &strW ) &&
                        NULL != ( tmpN = rpal_string_wton( strW ) ) )
                    {
                        _addPattern( g_extensions, tmpN, TRUE, NUMBER_TO_PTR( patternId ) );
                        rpal_memory_free( tmpN );
                    }

                    if( rSequence_getSTRINGA( pattern, RP_TAGS_STRING_PATTERN, &strA ) &&
                        NULL != ( tmpN = rpal_string_aton( strA ) ) )
                    {
                        _addPattern( g_extensions, tmpN, FALSE, NUMBER_TO_PTR( patternId ) );
                        rpal_memory_free( tmpN );
                    }

                    if( rSequence_getSTRINGW( pattern, RP_TAGS_STRING_PATTERN, &strW ) &&
                        NULL != ( tmpN = rpal_string_wton( strW ) ) )
                    {
                        _addPattern( g_extensions, tmpN, FALSE, NUMBER_TO_PTR( patternId ) );
                        rpal_memory_free( tmpN );
                    }
                }
            }

            if( NULL != ( g_mutex = rMutex_create() ) &&
                NULL != ( g_procContexts = rpal_vector_new() ) &&
                notifications_subscribe( RP_TAGS_NOTIFICATION_FILE_CREATE, NULL, 0, NULL, processFileIo ) &&
                notifications_subscribe( RP_TAGS_NOTIFICATION_FILE_DELETE, NULL, 0, NULL, processFileIo ) &&
                notifications_subscribe( RP_TAGS_NOTIFICATION_FILE_MODIFIED, NULL, 0, NULL, processFileIo ) &&
                notifications_subscribe( RP_TAGS_NOTIFICATION_FILE_READ, NULL, 0, NULL, processFileIo ) &&
                notifications_subscribe( RP_TAGS_NOTIFICATION_NEW_PROCESS, NULL, 0, NULL, processNewProcesses ) &&
                notifications_subscribe( RP_TAGS_NOTIFICATION_EXISTING_PROCESS, NULL, 0, NULL, processNewProcesses ) &&
                notifications_subscribe( RP_TAGS_NOTIFICATION_TERMINATE_PROCESS, NULL, 0, NULL, processTerminateProcesses ) )
            {
                isSuccess = TRUE;
            }
        }
    }

    if( !isSuccess )
    {
        notifications_unsubscribe( RP_TAGS_NOTIFICATION_FILE_CREATE, NULL, processFileIo );
        notifications_unsubscribe( RP_TAGS_NOTIFICATION_FILE_DELETE, NULL, processFileIo );
        notifications_unsubscribe( RP_TAGS_NOTIFICATION_FILE_MODIFIED, NULL, processFileIo );
        notifications_unsubscribe( RP_TAGS_NOTIFICATION_FILE_READ, NULL, processFileIo );
        notifications_unsubscribe( RP_TAGS_NOTIFICATION_NEW_PROCESS, NULL, processNewProcesses );
        notifications_unsubscribe( RP_TAGS_NOTIFICATION_EXISTING_PROCESS, NULL, processNewProcesses );
        notifications_unsubscribe( RP_TAGS_NOTIFICATION_TERMINATE_PROCESS, NULL, processTerminateProcesses );
        obsLib_free( g_extensions );
        g_extensions = NULL;
        if( NULL != g_procContexts )
        {
            for( i = 0; i < g_procContexts->nElements; i++ )
            {
                rpal_memory_free( ( (ProcExtInfo*)g_procContexts->elements[ i ] )->processPath );
                rpal_memory_free( g_procContexts->elements[ i ] );
            }
        }
        rpal_vector_free( g_procContexts );
        g_procContexts = NULL;
        rMutex_free( g_mutex );
        g_mutex = NULL;
    }

    return isSuccess;
}
        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;
}
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;
}
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 );
    }
}
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 );
}
Beispiel #21
0
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;
}