Exemple #1
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 );
}
static
RPVOID
    lookForHiddenModules
    (
        rEvent isTimeToStop,
        RPVOID ctx
    )
{
    processLibProcEntry* procs = NULL;
    processLibProcEntry* proc = NULL;

    UNREFERENCED_PARAMETER( ctx );

    if( NULL != ( procs = processLib_getProcessEntries( TRUE ) ) )
    {
        proc = procs;

        while( 0 != proc->pid &&
            rpal_memory_isValid( isTimeToStop ) &&
            !rEvent_wait( isTimeToStop, 0 ) )
        {
            lookForHiddenModulesIn( isTimeToStop, proc->pid );

            proc++;
        }

        rpal_memory_free( procs );
    }

    return NULL;
}
Exemple #3
0
void 
    test_processInfo
    (
        void
    )
{
    processLibProcEntry* entries = NULL;
    RU32 entryIndex = 0;
    rSequence proc = 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 );

    proc = processLib_getProcessInfo( entries[ entryIndex ].pid );

    CU_ASSERT_PTR_NOT_EQUAL( proc, NULL );

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

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

    rSequence_free( proc );

    rpal_memory_free( entries );
}
Exemple #4
0
void 
    test_procEntries
    (
        void
    )
{
    processLibProcEntry* entries = NULL;
    RU32 entryIndex = 0;
    RU32 nEntries = 0;

    entries = processLib_getProcessEntries( TRUE );

    CU_ASSERT_PTR_NOT_EQUAL_FATAL( entries, NULL );

    while( 0 != entries[ entryIndex ].pid )
    {
        nEntries++;

        entryIndex++;
    }

    CU_ASSERT_TRUE( 5 < nEntries );

    rpal_memory_free( entries );
	
	entries = processLib_getProcessEntries( FALSE );

    CU_ASSERT_PTR_NOT_EQUAL_FATAL( entries, NULL );

    while( 0 != entries[ entryIndex ].pid )
    {
        nEntries++;

        entryIndex++;
    }

    CU_ASSERT_TRUE( 5 < nEntries );

    rpal_memory_free( entries );
}
static
RPVOID
    lookForHiddenModulesConstantly
    (
        rEvent isTimeToStop,
        RPVOID ctx
    )
{
    rSequence originalRequest = (rSequence)ctx;
    processLibProcEntry* procs = NULL;
    processLibProcEntry* proc = NULL;
    LibOsPerformanceProfile perfProfile = { 0 };

    perfProfile.enforceOnceIn = 4;
    perfProfile.sanityCeiling = MSEC_FROM_SEC( 20 );
    perfProfile.lastTimeoutValue = 200;
    perfProfile.targetCpuPerformance = 0;
    perfProfile.globalTargetCpuPerformance = GLOBAL_CPU_USAGE_TARGET;
    perfProfile.timeoutIncrementPerSec = 50;

    while( rpal_memory_isValid( isTimeToStop ) && 
           !rEvent_wait( isTimeToStop, 0 ) )
    {
        if( NULL != ( procs = processLib_getProcessEntries( TRUE ) ) )
        {
            proc = procs;

            while( 0 != proc->pid &&
                   rpal_memory_isValid( isTimeToStop ) &&
                   !rEvent_wait( isTimeToStop, _TIMEOUT_BETWEEN_CONSTANT_PROCESSS ) )
            {
                if( hbs_whenCpuBelow( _CPU_WATERMARK, _MAX_CPU_WAIT, isTimeToStop ) )
                {
                    lookForHiddenModulesIn( isTimeToStop, proc->pid, originalRequest, &perfProfile );
                }

                proc++;
            }

            rpal_memory_free( procs );
        }
    }

    return NULL;
}
Exemple #6
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
RVOID
    doScan
    (
        rpcm_tag eventType,
        rSequence event
    )
{
    RU32 pid = 0;
    RPWCHAR fileW = NULL;
    RPCHAR fileA = NULL;
    RPWCHAR procW = NULL;
    RPCHAR procA = NULL;
    RPU8 rulesBuffer = NULL;
    RU32 rulesBufferSize = 0;
    YR_RULES* rules = NULL;
    YaraMatchContext matchContext = { 0 };
    processLibProcEntry* processes = NULL;
    processLibProcEntry* curProc = NULL;
    RU32 scanError = 0;
    rSequence processInfo = NULL;
    RPWCHAR tmpW = NULL;
    RPCHAR tmpA = NULL;

    UNREFERENCED_PARAMETER( eventType );

    if( rpal_memory_isValid( event ) )
    {
        rSequence_getRU32( event, RP_TAGS_PROCESS_ID, &pid );
        rSequence_getSTRINGW( event, RP_TAGS_FILE_PATH, &fileW );
        rSequence_getSTRINGA( event, RP_TAGS_FILE_PATH, &fileA );
        rSequence_getSTRINGW( event, RP_TAGS_PROCESS, &procW );
        rSequence_getSTRINGA( event, RP_TAGS_PROCESS, &procA );

        if( rSequence_getBUFFER( event, RP_TAGS_RULES, &rulesBuffer, &rulesBufferSize ) )
        {
            rules = loadYaraRules( rulesBuffer, rulesBufferSize );
        }

        if( NULL != rules )
        {
            if( NULL != fileW )
            {
                fileA = rpal_string_wtoa( fileW );
            }

            if( NULL != procW )
            {
                procA = rpal_string_wtoa( procW );
            }

            if( NULL != fileA )
            {
                rpal_debug_info( "scanning file with yara" );
                matchContext.fileInfo = event;

                // Scan this file
                if( ERROR_SUCCESS != ( scanError = yr_rules_scan_file( rules,
                                                                       fileA,
                                                                       SCAN_FLAGS_FAST_MODE,
                                                                       _yaraFileMatchCallback,
                                                                       &matchContext,
                                                                       60 ) ) )
                {
                    rpal_debug_warning( "Yara file scan error: %d", scanError );
                }
            }
            else if( NULL != procA )
            {
                // Scan processes matching
                if( NULL != ( processes = processLib_getProcessEntries( TRUE ) ) )
                {
                    curProc = processes;
                    while( 0 != curProc->pid )
                    {
                        if( NULL != ( processInfo = processLib_getProcessInfo( curProc->pid, NULL ) ) )
                        {
                            if( rSequence_getSTRINGW( processInfo, RP_TAGS_FILE_PATH, &tmpW ) ||
                                rSequence_getSTRINGA( processInfo, RP_TAGS_FILE_PATH, &tmpA ) )
                            {
                                if( NULL != tmpW )
                                {
                                    tmpA = rpal_string_wtoa( tmpW );
                                }

                                if( NULL != tmpA )
                                {
                                    if( rpal_string_match( procA, tmpA, RPAL_PLATFORM_FS_CASE_SENSITIVITY ) )
                                    {
                                        matchContext.pid = curProc->pid;
                                        matchContext.processInfo = processInfo;

                                        scanError = _scanProcessWith( curProc->pid,
                                                                      &matchContext,
                                                                      rules,
                                                                      NULL );
                                    }
                                }

                                if( NULL != tmpW && NULL != tmpA )
                                {
                                    // If both are allocated it means we got a strW and converted to A
                                    // so we must free the strA version.
                                    rpal_memory_free( tmpA );
                                }
                            }

                            rSequence_free( processInfo );
                        }

                        curProc++;
                    }

                    rpal_memory_free( processes );
                }
            }
            else if( 0 != pid )
            {
                // Scan this process
                matchContext.pid = pid;
                scanError = _scanProcessWith( pid, &matchContext, rules, NULL );
                rSequence_free( matchContext.processInfo );
            }
            else
            {
                // Scan all processes
                if( NULL != ( processes = processLib_getProcessEntries( TRUE ) ) )
                {
                    curProc = processes;
                    while( 0 != curProc->pid )
                    {
                        matchContext.pid = curProc->pid;

                        scanError = _scanProcessWith( curProc->pid, &matchContext, rules, NULL );
                        rSequence_free( matchContext.processInfo );

                        curProc++;
                    }
                        
                    rpal_memory_free( processes );
                }
            }


            if( NULL != fileW && NULL != fileA )
            {
                // If both are allocated it means we got a strW and converted to A
                // so we must free the strA version.
                rpal_memory_free( fileA );
            }

            if( NULL != procW && NULL != procA )
            {
                // If both are allocated it means we got a strW and converted to A
                // so we must free the strA version.
                rpal_memory_free( procA );
            }

            yr_rules_destroy( rules );
        }
        else
        {
            rpal_debug_warning( "no rules in yara scan request" );
            reportError( event, RPAL_ERROR_NOT_SUPPORTED, "yara rules do not parse" );
        }
    }

    rpal_debug_info( "finished on demand yara scan" );
    reportError( event, scanError, "done" );

    yr_finalize_thread();
}
static
RPVOID
    continuousMemScan
    (
        rEvent isTimeToStop,
        RPVOID ctx
    )
{
    processLibProcEntry* processes = NULL;
    processLibProcEntry* curProc = NULL;
    RU32 thisProcId = 0;
    YaraMatchContext matchContext = { 0 };
    RU32 scanError = 0;

    UNREFERENCED_PARAMETER( ctx );

    thisProcId = processLib_getCurrentPid();

    while( !rEvent_wait( isTimeToStop, 0 ) )
    {
        // Wait until we have global rules to look for.
        if( rMutex_lock( g_global_rules_mutex ) )
        {
            if( NULL == g_global_rules )
            {
                rMutex_unlock( g_global_rules_mutex );
                rEvent_wait( isTimeToStop, MSEC_FROM_SEC( 30 ) );
                continue;
            }
            rMutex_unlock( g_global_rules_mutex );
        }

        if( NULL != ( processes = processLib_getProcessEntries( TRUE ) ) )
        {
            curProc = processes;
            while( 0 != curProc->pid )
            {
                // We can't examine our own memory for the risk of tripping on the sigs themselves.
                if( curProc->pid == thisProcId ) continue;

                rpal_debug_info( "yara scanning pid %d", curProc->pid );

                matchContext.pid = curProc->pid;
                matchContext.processInfo = NULL;
                matchContext.moduleInfo = NULL;

                scanError = _scanProcessWith( curProc->pid, &matchContext, NULL, isTimeToStop );

                rSequence_free( matchContext.processInfo );

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

                curProc++;
            }

            rpal_memory_free( processes );
        }
    }

    yr_finalize_thread();

    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;
}
Exemple #10
0
static RVOID
    injectIntoProcess
    (

    )
{
    RNCHAR strSeDebug[] = _NC( "SeDebugPrivilege" );
    processLibProcEntry* procIds = NULL;
    processLibProcEntry* tmpProcId = NULL;
    rSequence targetProc = NULL;
    RU32 targetPid = 0;
    RPWCHAR procName = NULL;
    RWCHAR targetProcName[] = _WCH( "EXPLORER.EXE" );

    HANDLE hProc = NULL;
    RU32 selfSize = 0;

    RPVOID remoteDest = NULL;

    SIZE_T payloadSize = 0;
    RPU8 payloadBuff = NULL;
    
    rpal_debug_info( "getting debug privilege to inject..." );
    if( !Get_Privilege( strSeDebug ) )
    {
        rpal_debug_error( "could not get debug privilege, are we running as admin?" );
        return;
    }

    rpal_debug_info( "getting process list to find explorer.exe" );
    procIds = processLib_getProcessEntries( FALSE );
    tmpProcId = procIds;
    while( NULL != tmpProcId )
    {
        if( NULL != ( targetProc = processLib_getProcessInfo( tmpProcId->pid, NULL ) ) )
        {
            if( rSequence_getSTRINGN( targetProc, RP_TAGS_FILE_PATH, &procName ) )
            {
                rpal_string_toupper( procName );
                if( NULL != rpal_string_strstr( procName, targetProcName ) )
                {
                    rpal_debug_info( "found the target process: %d", tmpProcId->pid );
                    targetPid = tmpProcId->pid;
                }
                else
                {
                    rpal_debug_info( "not target process, next..." );
                }
            }
            else
            {
                rpal_debug_warning( "process without file path, odd..." );
            }

            rSequence_free( targetProc );
            targetProc = NULL;

            if( 0 != targetPid )
            {
                break;
            }
        }

        tmpProcId++;
    }

    rpal_memory_free( procIds );

    if( 0 != targetPid )
    {
        rpal_debug_info( "getting size of self..." );
        if( (RU32)(-1) != ( selfSize = rpal_file_getSize( g_self_path, FALSE ) ) )
        {
            rpal_debug_info( "opening target process with right privileges..." );
            if( NULL != ( hProc = OpenProcess( PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, targetPid ) ) )
            {
                rpal_debug_info( "allocating required memory in remote process..." );
                if( NULL != ( remoteDest = VirtualAllocEx( hProc, NULL, selfSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE ) ) )
                {
                    rpal_debug_info( "reading payload to memory before writing it to remote." );
                    if( rpal_file_read( g_self_path, (RPVOID*)&payloadBuff, (RU32*)&payloadSize, FALSE ) )
                    {
                        rpal_debug_info( "writing payload to remote process." );
                        if( WriteProcessMemory( hProc, remoteDest, payloadBuff, payloadSize, &payloadSize ) &&
                            payloadSize == selfSize )
                        {
                            rpal_debug_info( "successfully written payload to remote process. This should look like an injected PE although no thread was started." );
                        }
                        else
                        {
                            rpal_debug_error( "error writing payload to remote process." );
                        }

                        rpal_memory_free( payloadBuff );
                    }
                    else
                    {
                        rpal_debug_error( "error reading ourselves as payload." );
                    }
                }
                else
                {
                    rpal_debug_error( "error allocating memory in remote process." );
                }

                CloseHandle( hProc );
            }
            else
            {
                rpal_debug_error( "error opening process with VM privilges." );
            }
        }
        else
        {
            rpal_debug_error( "error getting size of self." );
        }
    }
}
//=============================================================================
// 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;
}
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_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 );
    }
}