예제 #1
0
RPRIVATE
RVOID
    _cleanupModuleEntry
    (
        rpHCPModuleInfo* mod
    )
{
    rEvent_free( mod->context.isTimeToStop );
    rpal_thread_free( mod->hThread );

    if( mod->isOsLoaded )
    {
#ifdef RPAL_PLATFORM_WINDOWS
        FreeLibrary( (HMODULE)(mod->hModule) );
#elif defined( RPAL_PLATFORM_LINUX ) || defined( RPAL_PLATFORM_MACOSX )
        dlclose( mod->hModule );
#endif
    }
    else
    {
        MemoryFreeLibrary( mod->hModule );
    }

    rpal_debug_info( "module %d cleaned up", mod->id );
    rpal_memory_zero( mod, sizeof( *mod ) );
}
예제 #2
0
RBOOL
    rpal_blob_remove
    (
        rBlob blob,
        RU32 startOffset,
        RU32 size
    )
{
    RBOOL isSuccess = FALSE;
    _prBlob pBlob = (_prBlob)blob;
    
    if( NULL != pBlob &&
        IS_WITHIN_BOUNDS( pBlob->pData + startOffset, size, pBlob->pData, pBlob->sizeUsed ) &&
        rpal_memory_isValid( pBlob->pData ) )
    {
        rpal_memory_memcpy( pBlob->pData + startOffset, pBlob->pData + startOffset + size, pBlob->sizeUsed - size - startOffset );
        pBlob->sizeUsed -= size;

        if( rpal_memory_isValid( pBlob->pData ) )
        {
            pBlob->pData = rpal_memory_realloc_from( pBlob->pData, pBlob->sizeUsed + sizeof( RWCHAR ), pBlob->from );
            pBlob->currentSize = pBlob->sizeUsed;

            if( NULL != pBlob->pData )
            {
                // We allocate WCHAR more than we need always to ensure that if the buffer contains a wide string it will be terminated
                rpal_memory_zero( pBlob->pData + pBlob->sizeUsed, sizeof( RWCHAR ) );
                isSuccess = TRUE;
            }
        }
    }

    return isSuccess;
}
static RVOID
    modKernelModeDiff
    (
        rEvent isTimeToStop
    )
{
    RU32 i = 0;
    RU32 nScratch = 0;
    RU32 prev_nScratch = 0;
    KernelAcqModule new_from_kernel[ 200 ] = { 0 };
    KernelAcqModule prev_from_kernel[ 200 ] = { 0 };

    while( !rEvent_wait( isTimeToStop, 1000 ) )
    {
        nScratch = ARRAY_N_ELEM( new_from_kernel );
        rpal_memory_zero( new_from_kernel, sizeof( new_from_kernel ) );
        if( !kAcq_getNewModules( new_from_kernel, &nScratch ) )
        {
            rpal_debug_warning( "kernel acquisition for new modules failed" );
            g_is_kernel_failure = TRUE;
            break;
        }

        for( i = 0; i < prev_nScratch; i++ )
        {
            notifyOfKernelModule( &(prev_from_kernel[ i ]) );
        }

        rpal_memory_memcpy( prev_from_kernel, new_from_kernel, sizeof( prev_from_kernel ) );
        prev_nScratch = nScratch;
    }
}
예제 #4
0
RBOOL
	rpal_blob_insert
	(
		rBlob blob,
		RPVOID pData,
		RU32 size,
        RU32 offset
	)
{
	RBOOL isAdded = FALSE;

    _prBlob pBlob = (_prBlob)blob;

	if( rpal_memory_isValid( blob ) &&
		NULL != pData &&
		0 != size )
	{
		if( pBlob->currentSize - pBlob->sizeUsed < size )
		{
			pBlob->currentSize += ( 0 != pBlob->growBy ? pBlob->growBy : size );
			pBlob->pData = rpal_memory_realloc_from( pBlob->pData,
													 pBlob->currentSize + sizeof( RWCHAR ),
													 pBlob->from );
		}

		if( rpal_memory_isValid( pBlob->pData ) )
		{
            // Relocate existing data
            rpal_memory_memmove( pBlob->pData + offset + size, 
                                 pBlob->pData + offset, 
                                 pBlob->sizeUsed - offset );

			rpal_memory_memcpy( pBlob->pData + offset, pData, size );

			pBlob->sizeUsed += size;
            
            // We allocate WCHAR more than we need always to ensure that if the buffer contains a wide string it will be terminated
            rpal_memory_zero( pBlob->pData + pBlob->sizeUsed, sizeof( RWCHAR ) );

			isAdded = TRUE;
		}
	}
    else if( NULL == pData ||
		     0 == size )
    {
        isAdded = TRUE;
    }

    if( isAdded )
    {
        if( !rpal_memory_isValid( pBlob->pData ) )
        {
            isAdded = FALSE;
            rpal_debug_break();
        }
    }

	return isAdded;
}
예제 #5
0
RBOOL
	rpal_blob_add
	(
		rBlob blob,
		RPVOID pData,
		RU32 size
	)
{
	RBOOL isAdded = FALSE;

	if( rpal_memory_isValid( blob ) &&
		NULL != pData &&
		0 != size )
	{
		if( ((_prBlob)blob)->currentSize - ((_prBlob)blob)->sizeUsed < size )
		{
			((_prBlob)blob)->currentSize += ( ( 0 != ((_prBlob)blob)->growBy && size < ((_prBlob)blob)->growBy ) ? ((_prBlob)blob)->growBy : size );
			((_prBlob)blob)->pData = rpal_memory_realloc_from( ((_prBlob)blob)->pData,
                                                               ((_prBlob)blob)->currentSize + sizeof( RWCHAR ),
															   ((_prBlob)blob)->from );
		}

		if( rpal_memory_isValid( ((_prBlob)blob)->pData ) )
		{
			rpal_memory_memcpy( ((_prBlob)blob)->pData + ((_prBlob)blob)->sizeUsed, pData, size );

			((_prBlob)blob)->sizeUsed += size;
            
            // We allocate WCHAR more than we need always to ensure that if the buffer contains a wide string it will be terminated
            rpal_memory_zero( ((_prBlob)blob)->pData + ((_prBlob)blob)->sizeUsed, sizeof( RWCHAR ) );

			isAdded = TRUE;
		}
	}
    else if( NULL == pData ||
		     0 == size )
    {
        isAdded = TRUE;
    }

    if( isAdded )
    {
        if( !rpal_memory_isValid( ((_prBlob)blob)->pData ) )
        {
            isAdded = FALSE;
            rpal_debug_break();
        }
    }

	return isAdded;
}
예제 #6
0
RBOOL
    addHitToNode
    (
        PObsNode node,
        PObsSig sig
    )
{
    RBOOL isSuccess = FALSE;
    PObsSig* tmp = NULL;
    RU32 numHits = 0;

    if( rpal_memory_isValid( node ) &&
        rpal_memory_isValid( sig ) )
    {
        tmp = node->pSigsHit;

        if( NULL != tmp )
        {
            while( NULL != *tmp )
            {
                numHits++;
                tmp++;
            }
        }

        node->pSigsHit = rpal_memory_realloc( node->pSigsHit, ( ( numHits + 2 ) * sizeof( PObsSig ) ) );

        tmp = node->pSigsHit;
        if( NULL != tmp )
        {
            rpal_memory_zero( (RPU8)tmp + ( numHits * sizeof( PObsSig ) ), 2 * sizeof( PObsSig ) );

            while( NULL != *tmp )
            {
                tmp++;
            }

            *tmp = sig;

            isSuccess = TRUE;
        }
    }

    return isSuccess;
}
RPRIVATE
RVOID
    dnsKmDiffThread
    (
        rEvent isTimeToStop
    )
{
    RU8 new_from_kernel[ DNS_KB_PACKET_BUFFER * 1024 ] = { 0 };
    RU8 prev_from_kernel[ DNS_KB_PACKET_BUFFER * 1024 ] = { 0 };

    RU32 sizeInNew = 0;
    RU32 sizeInPrev = 0;

    KernelAcqDnsPacket* pPacket = NULL;

    while( !rEvent_wait( isTimeToStop, 1000 ) )
    {
        rpal_memory_zero( new_from_kernel, sizeof( new_from_kernel ) );
        sizeInNew = sizeof( new_from_kernel );

        if( !kAcq_getNewDnsPackets( (KernelAcqDnsPacket*)new_from_kernel, &sizeInNew ) )
        {
            rpal_debug_warning( "kernel acquisition for new dns packets failed" );
            break;
        }

        pPacket = (KernelAcqDnsPacket*)prev_from_kernel;
        while( IS_WITHIN_BOUNDS( pPacket, sizeof( *pPacket ), prev_from_kernel, sizeInPrev ) &&
               0 != pPacket->ts &&
               IS_WITHIN_BOUNDS( pPacket, sizeof( *pPacket ) + pPacket->packetSize, prev_from_kernel, sizeInPrev ) )
        {
            processDnsPacket( pPacket );

            pPacket = (KernelAcqDnsPacket*)( (RPU8)pPacket + sizeof( *pPacket ) + pPacket->packetSize );
        }

        rpal_memory_memcpy( prev_from_kernel, new_from_kernel, sizeInNew );
        sizeInPrev = sizeInNew;
    }
}
static
RU32
    _checkMemoryForStringSample
    (
        HObs sample,
        RU32 pid,
        RPVOID moduleBase,
        RU64 moduleSize,
        rEvent isTimeToStop,
        LibOsPerformanceProfile* perfProfile
    )
{
    RPU8 pMem = NULL;
    RU8* sampleList = NULL;
    RPU8 sampleNumber = 0;
    RU32 nSamples = 0;
    RU32 nSamplesFound = (RU32)(-1);

    UNREFERENCED_PARAMETER( isTimeToStop );

    if( NULL != sample &&
        0 != pid &&
        NULL != moduleBase &&
        0 != moduleSize &&
        _MIN_DISK_SAMPLE_SIZE <= ( nSamples = obsLib_getNumPatterns( sample ) ) )
    {
        if( NULL != ( sampleList = rpal_memory_alloc( sizeof( RU8 ) * nSamples ) ) )
        {
            rpal_memory_zero( sampleList, sizeof( RU8 ) * nSamples );

            if( processLib_getProcessMemory( pid, moduleBase, moduleSize, (RPVOID*)&pMem, TRUE ) )
            {
                if( obsLib_setTargetBuffer( sample, pMem, (RU32)moduleSize ) )
                {
                    while( !rEvent_wait( isTimeToStop, 0 ) &&
                           obsLib_nextHit( sample, (RPVOID*)&sampleNumber, NULL ) )
                    {
                        libOs_timeoutWithProfile( perfProfile, TRUE, isTimeToStop );

                        if( sampleNumber < (RPU8)NUMBER_TO_PTR( nSamples ) &&
                            0 == sampleList[ (RU32)PTR_TO_NUMBER( sampleNumber ) ] )
                        {
                            sampleList[ (RU32)PTR_TO_NUMBER( sampleNumber ) ] = 1;
                            nSamplesFound++;
                        }
                    }
                }

                rpal_memory_free( pMem );
            }
            else
            {
                rpal_debug_info( "failed to get memory for %d: 0x%016X ( 0x%016X ) error %d", 
                                 pid, 
                                 moduleBase, 
                                 moduleSize,
                                 rpal_error_getLast() );
            }

            rpal_memory_free( sampleList );
        }
    }

    return nSamplesFound;
}
예제 #9
0
RPRIVATE_TESTABLE
RBOOL 
    loadModule
    (
        rpHCPContext* hcpContext,
        rSequence seq
    )
{
    RBOOL isSuccess = FALSE;

    RU32 moduleIndex = (RU32)(-1);

    RPU8 tmpBuff = NULL;
    RU32 tmpSize = 0;

    RPU8 tmpSig = NULL;
    RU32 tmpSigSize = 0;

    rpal_thread_func pEntry = NULL;

    rpHCPModuleContext* modContext = NULL;

    OBFUSCATIONLIB_DECLARE( entryName, RP_HCP_CONFIG_MODULE_ENTRY );
    OBFUSCATIONLIB_DECLARE( recvMessage, RP_HCP_CONFIG_MODULE_RECV_MESSAGE );

    if( NULL != seq &&
        NULL != hcpContext )
    {
        for( moduleIndex = 0; moduleIndex < RP_HCP_CONTEXT_MAX_MODULES; moduleIndex++ )
        {
            if( 0 == hcpContext->modules[ moduleIndex ].hThread )
            {
                // Found an empty spot
                break;
            }
        }
    }

    if( RP_HCP_CONTEXT_MAX_MODULES != moduleIndex &&
        (RU32)(-1) != moduleIndex )
    {
        // We got an empty spot for our module
        if( rSequence_getRU8( seq, 
                              RP_TAGS_HCP_MODULE_ID, 
                              &(hcpContext->modules[ moduleIndex ].id ) ) &&
            rSequence_getBUFFER( seq,
                                 RP_TAGS_BINARY, 
                                 &tmpBuff, 
                                 &tmpSize ) &&
            rSequence_getBUFFER( seq,
                                 RP_TAGS_SIGNATURE,
                                 &tmpSig,
                                 &tmpSigSize ) &&
            CRYPTOLIB_SIGNATURE_SIZE == tmpSigSize )
        {
            // We got the data, now verify the buffer signature
            if( CryptoLib_verify( tmpBuff, tmpSize, getRootPublicKey(), tmpSig ) )
            {
                // Ready to load the module
                rpal_debug_info( "loading module in memory" );
                hcpContext->modules[ moduleIndex ].hModule = MemoryLoadLibrary( tmpBuff, tmpSize );

                if( NULL != hcpContext->modules[ moduleIndex ].hModule )
                {
                    OBFUSCATIONLIB_TOGGLE( entryName );

                    pEntry = (rpal_thread_func)MemoryGetProcAddress( hcpContext->modules[ moduleIndex ].hModule,
                                                            (RPCHAR)entryName );

                    OBFUSCATIONLIB_TOGGLE( entryName );

                    if( NULL != pEntry )
                    {
                        modContext = &(hcpContext->modules[ moduleIndex ].context);

                        modContext->pCurrentId = &( hcpContext->currentId );
                        modContext->func_sendHome = doSend;
                        modContext->isTimeToStop = rEvent_create( TRUE );
                        modContext->rpalContext = rpal_Context_get();
                        modContext->isOnlineEvent = hcpContext->isCloudOnline;

                        if( NULL != modContext->isTimeToStop )
                        {
                            hcpContext->modules[ moduleIndex ].isTimeToStop = modContext->isTimeToStop;

                            OBFUSCATIONLIB_TOGGLE( recvMessage );
                            hcpContext->modules[ moduleIndex ].func_recvMessage =
                                    (rpHCPModuleMsgEntry)MemoryGetProcAddress( hcpContext->modules[ moduleIndex ].hModule,
                                                                               (RPCHAR)recvMessage );
                            OBFUSCATIONLIB_TOGGLE( recvMessage );

                            hcpContext->modules[ moduleIndex ].hThread = rpal_thread_new( pEntry, modContext );

                            if( 0 != hcpContext->modules[ moduleIndex ].hThread )
                            {
                                CryptoLib_hash( tmpBuff, tmpSize, &(hcpContext->modules[ moduleIndex ].hash ) );
                                hcpContext->modules[ moduleIndex ].isOsLoaded = FALSE;
                                isSuccess = TRUE;
                            }
                            else
                            {
                                rpal_debug_warning( "Error creating handler thread for new module." );
                            }
                        }
                    }
                    else
                    {
                        rpal_debug_warning( "Could not find new module's entry point." );
                    }
                }
                else
                {
                    rpal_debug_warning( "Error loading module in memory." );
                }
            }
            else
            {
                rpal_debug_warning( "New module signature invalid." );
            }
        }
        else
        {
            rpal_debug_warning( "Could not find core module components to load." );
        }

        // Main cleanup
        if( !isSuccess )
        {
            if( NULL != modContext )
            {
                IF_VALID_DO( modContext->isTimeToStop, rEvent_free );
            }

            if( NULL != hcpContext->modules[ moduleIndex ].hModule )
            {
                MemoryFreeLibrary( hcpContext->modules[ moduleIndex ].hModule );
            }

            rpal_memory_zero( &(hcpContext->modules[ moduleIndex ] ),
                              sizeof( hcpContext->modules[ moduleIndex ] ) );
        }
    }
    else
    {
        rpal_debug_error( "Could not find a spot for new module, or invalid module id!" );
    }

    return isSuccess;
}
RPRIVATE
RVOID
    processDnsPacket
    (
        KernelAcqDnsPacket* pDns
    )
{
    rSequence notification = NULL;
    RU32 i = 0;
    DnsLabel* pLabel = NULL;
    DnsHeader* dnsHeader = NULL;
    DnsResponseInfo* pResponseInfo = NULL;
    RCHAR domain[ DNS_LABEL_MAX_SIZE ] = { 0 };
    RU16 recordType = 0;
    RU64 timestamp = 0;
    Atom parentAtom = { 0 };

    if( NULL == pDns )
    {
        return;
    }

    dnsHeader = (DnsHeader*)( (RPU8)pDns + sizeof( *pDns ) );
    pLabel = (DnsLabel*)dnsHeader->data;

    // We are parsing DNS packets coming from the kernel. They may:
    // 1- Be requests and not responses, check there are Answers.
    // 2- Be maliciously crafter packets so we need extra checking for sanity.
    if( 0 == dnsHeader->anCount ||
        0 == dnsHeader->qr ||
        DNS_SANITY_MAX_RECORDS < rpal_ntoh16( dnsHeader->qdCount ) ||
        DNS_SANITY_MAX_RECORDS < rpal_ntoh16( dnsHeader->anCount ) )
    {
        return;
    }

    // We need to walk the Questions first to get to the Answers
    // but we don't really care to record them since they'll be repeated
    // in the Answers.
    for( i = 0; i < rpal_ntoh16( dnsHeader->qdCount ); i++ )
    {
        DnsQuestionInfo* pQInfo = NULL;

        pLabel = dnsReadLabels( pLabel, NULL, (RPU8)dnsHeader, pDns->packetSize, 0, 0 );

        pQInfo = (DnsQuestionInfo*)( pLabel );
        if( !IS_WITHIN_BOUNDS( pQInfo, sizeof( *pQInfo ), dnsHeader, pDns->packetSize ) )
        {
            rpal_debug_warning( "error parsing dns packet" );
            break;
        }

        pLabel = (DnsLabel*)( (RPU8)pQInfo + sizeof( *pQInfo ) );
    }

    if( !IS_WITHIN_BOUNDS( pLabel, sizeof( RU16 ), dnsHeader, pDns->packetSize ) )
    {
        rpal_debug_warning( "error parsing dns packet" );
        return;
    }

    // This is what we care about, the Answers (which also point to each Question).
    // We will emit one event per Answer so as to keep the DNS_REQUEST event flat and atomic.
    for( i = 0; i < rpal_ntoh16( dnsHeader->anCount ); i++ )
    {
        pResponseInfo = NULL;
            
        // This was the Question for this answer.
        rpal_memory_zero( domain, sizeof( domain ) );
        pLabel = dnsReadLabels( pLabel, domain, (RPU8)dnsHeader, pDns->packetSize, 0, 0 );

        pResponseInfo = (DnsResponseInfo*)pLabel;
        pLabel = (DnsLabel*)( (RPU8)pResponseInfo + sizeof( *pResponseInfo ) + rpal_ntoh16( pResponseInfo->rDataLength ) );

        if( !IS_WITHIN_BOUNDS( pResponseInfo, sizeof( *pResponseInfo ), dnsHeader, pDns->packetSize ) )
        {
            rpal_debug_warning( "error parsing dns packet" );
            break;
        }

        if( NULL == ( notification = rSequence_new() ) )
        {
            rpal_debug_warning( "error parsing dns packet" );
            break;
        }

        // This is a timestamp coming from the kernel so it is not globally adjusted.
        // We'll adjust it with the global offset.
        timestamp = pDns->ts;
        timestamp += MSEC_FROM_SEC( rpal_time_getGlobalFromLocal( 0 ) );

        // Try to relate the DNS request to the owner process, this only works on OSX
        // at the moment (since the kernel does not expose the PID at the packet capture
        // stage), and even on OSX it's the DNSResolver process. So it's not super useful
        // but regardless we have the mechanism here as it's better than nothing and when
        // we add better resolving in the kernel it will work transparently.
        parentAtom.key.process.pid = pDns->pid;
        parentAtom.key.category = RP_TAGS_NOTIFICATION_NEW_PROCESS;
        if( atoms_query( &parentAtom, timestamp ) )
        {
            HbsSetParentAtom( notification, parentAtom.id );
        }

        rSequence_addTIMESTAMP( notification, RP_TAGS_TIMESTAMP, timestamp );
        rSequence_addSTRINGA( notification, RP_TAGS_DOMAIN_NAME, domain );
        rSequence_addRU32( notification, RP_TAGS_PROCESS_ID, pDns->pid );

        recordType = rpal_ntoh16( pResponseInfo->recordType );

        rSequence_addRU16( notification, RP_TAGS_MESSAGE_ID, rpal_ntoh16( dnsHeader->msgId ) );
        rSequence_addRU16( notification, RP_TAGS_DNS_TYPE, recordType );

        if( DNS_A_RECORD == recordType )
        {
            rSequence_addIPV4( notification, RP_TAGS_IP_ADDRESS, *(RU32*)pResponseInfo->rData );
        }
        else if( DNS_AAAA_RECORD == recordType )
        {
            rSequence_addIPV6( notification, RP_TAGS_IP_ADDRESS, pResponseInfo->rData );
        }
        else if( DNS_CNAME_RECORD == recordType )
        {
            // CNAME records will have another label as a value and not an IP.
            rpal_memory_zero( domain, sizeof( domain ) );
            dnsReadLabels( (DnsLabel*)pResponseInfo->rData, domain, (RPU8)dnsHeader, pDns->packetSize, 0, 0 );
            rSequence_addSTRINGA( notification, RP_TAGS_CNAME, domain );
        }
        else
        {
            // Right now we only care for A, CNAME and AAAA records.
            rSequence_free( notification );
            notification = NULL;
            continue;
        }

        hbs_publish( RP_TAGS_NOTIFICATION_DNS_REQUEST, notification );
        rSequence_free( notification );
        notification = NULL;
    }
}
예제 #11
0
static
VOID WINAPI 
    ServiceMain
    (
        DWORD  dwArgc,
        RPCHAR lpszArgv
    )
{
    RU32 memUsed = 0;
    RWCHAR svcName[] = { _SERVICE_NAME };
    RU32 i = 0;

    UNREFERENCED_PARAMETER( dwArgc );
    UNREFERENCED_PARAMETER( lpszArgv );


    if( NULL == ( g_svc_status_handle = RegisterServiceCtrlHandlerW( svcName, SvcCtrlHandler ) ) )
    {
        return;
    }

    rpal_memory_zero( &g_svc_status, sizeof( g_svc_status ) );
    g_svc_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    g_svc_status.dwControlsAccepted = 0;
    g_svc_status.dwCurrentState = SERVICE_START_PENDING;
    g_svc_status.dwWin32ExitCode = 0;
    g_svc_status.dwServiceSpecificExitCode = 0;
    g_svc_status.dwCheckPoint = 0;
    SetServiceStatus( g_svc_status_handle, &g_svc_status );

    if( NULL == ( g_timeToQuit = rEvent_create( TRUE ) ) )
    {
        g_svc_status.dwControlsAccepted = 0;
        g_svc_status.dwCurrentState = SERVICE_STOPPED;
        g_svc_status.dwWin32ExitCode = GetLastError();
        g_svc_status.dwCheckPoint = 1;
        SetServiceStatus( g_svc_status_handle, &g_svc_status );
        return;
    }

    rpal_debug_info( "initialising rpHCP." );
    if( !rpHostCommonPlatformLib_launch( g_svc_primary, g_svc_secondary ) )
    {
        rpal_debug_warning( "error launching hcp." );
    }

    for( i = 0; i < ARRAY_N_ELEM( g_manual_loads ); i++ )
    {
        if( NULL != g_manual_loads[ i ].modPath )
        {
            if( 0 != g_manual_loads[ i ].nMod )
            {
#ifdef HCP_EXE_ENABLE_MANUAL_LOAD
                rpHostCommonPlatformLib_load( g_manual_loads[ i ].modPath, g_manual_loads[ i ].nMod );
#endif
            }
            else
            {
                rpal_debug_error( "Mismatched number of -m modulePath and -n moduleId statements provided!" );
            }

            rpal_memory_free( g_manual_loads[ i ].modPath );
            g_manual_loads[ i ].modPath = NULL;
        }
        else
        {
            break;
        }
    }

    g_svc_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
    g_svc_status.dwCurrentState = SERVICE_RUNNING;
    g_svc_status.dwWin32ExitCode = 0;
    g_svc_status.dwCheckPoint = 1;
    SetServiceStatus( g_svc_status_handle, &g_svc_status );

    rpal_debug_info( "...running, waiting to exit..." );
    rEvent_wait( g_timeToQuit, RINFINITE );
    rEvent_free( g_timeToQuit );

    rpal_debug_info( "...exiting..." );
    rpal_Context_cleanup();

    memUsed = rpal_memory_totalUsed();
    if( 0 != memUsed )
    {
        rpal_debug_critical( "Memory leak: %d bytes.\n", memUsed );
        //rpal_memory_findMemory();
#ifdef RPAL_FEATURE_MEMORY_ACCOUNTING
        rpal_memory_printDetailedUsage();
#endif
    }

    g_svc_status.dwControlsAccepted = 0;
    g_svc_status.dwCurrentState = SERVICE_STOPPED;
    g_svc_status.dwWin32ExitCode = 0;
    g_svc_status.dwCheckPoint = 3;
    SetServiceStatus( g_svc_status_handle, &g_svc_status );
}
static RBOOL
    getSnapshot
    (
        processEntry* toSnapshot
    )
{
    RBOOL isSuccess = FALSE;
    RU32 i = 0;

    if( NULL != toSnapshot )
    {
        rpal_memory_zero( toSnapshot, sizeof( g_snapshot_1 ) );
    }

    if( NULL != toSnapshot )
    {
#ifdef RPAL_PLATFORM_WINDOWS
        HANDLE hSnapshot = NULL;
        PROCESSENTRY32W procEntry = { 0 };
        procEntry.dwSize = sizeof( procEntry );

        if( INVALID_HANDLE_VALUE != ( hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ) ) )
        {
            if( Process32FirstW( hSnapshot, &procEntry ) )
            {
                isSuccess = TRUE;

                do
                {
                    if( 0 == procEntry.th32ProcessID )
                    {
                        continue;
                    }

                    toSnapshot[ i ].pid = procEntry.th32ProcessID;
                    toSnapshot[ i ].ppid = procEntry.th32ParentProcessID;
                    i++;
                } while( Process32NextW( hSnapshot, &procEntry ) &&
                         MAX_SNAPSHOT_SIZE > i );
            }

            CloseHandle( hSnapshot );
        }
#elif defined( RPAL_PLATFORM_LINUX )
        RWCHAR procDir[] = _WCH( "/proc/" );
        rDir hProcDir = NULL;
        rFileInfo finfo = {0};

        if( rDir_open( (RPWCHAR)&procDir, &hProcDir ) )
        {
            isSuccess = TRUE;

            while( rDir_next( hProcDir, &finfo ) &&
                   MAX_SNAPSHOT_SIZE > i )
            {
                if( rpal_string_wtoi( (RPWCHAR)finfo.fileName, &( toSnapshot[ i ].pid ) )
                    && 0 != toSnapshot[ i ].pid )
                {
                    i++;
                }
            }

            rDir_close( hProcDir );
        }
#elif defined( RPAL_PLATFORM_MACOSX )
        int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
        struct kinfo_proc* infos = NULL;
        size_t size = 0;
        int ret = 0;
        int j = 0;

        if( 0 == ( ret = sysctl( mib, ARRAY_N_ELEM( mib ), infos, &size, NULL, 0 ) ) )
        {
            if( NULL != ( infos = rpal_memory_alloc( size ) ) )
            {
                while( 0 != ( ret = sysctl( mib, ARRAY_N_ELEM( mib ), infos, &size, NULL, 0 ) ) && ENOMEM == errno )
                {
                    if( NULL == ( infos = rpal_memory_realloc( infos, size ) ) )
                    {
                        break;
                    }
                }
            }
        }

        if( 0 == ret && NULL != infos )
        {
            isSuccess = TRUE;
            size = size / sizeof( struct kinfo_proc );
            for( j = 0; j < size; j++ )
            {
                toSnapshot[ i ].pid = infos[ j ].kp_proc.p_pid;
                toSnapshot[ i ].ppid = infos[ j ].kp_eproc.e_ppid;
                i++;
            }

            if( NULL != infos )
            {
                rpal_memory_free( infos );
                infos = NULL;
            }
        }
#endif
    }

    return isSuccess;
}
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;
}
static RVOID
    kernelModeDiff
    (
        rEvent isTimeToStop
    )
{
    RU32 i = 0;
    RU32 nScratch = 0;
    RU32 nProcessEntries = 0;
    KernelAcqProcess new_from_kernel[ 200 ] = { 0 };
    processEntry tracking_user[ MAX_SNAPSHOT_SIZE ] = { 0 };
    
    while( !rEvent_wait( isTimeToStop, 1000 ) )
    {
        nScratch = ARRAY_N_ELEM( new_from_kernel );
        rpal_memory_zero( new_from_kernel, sizeof( new_from_kernel ) );
        if( !kAcq_getNewProcesses( new_from_kernel, &nScratch ) )
        {
            rpal_debug_warning( "kernel acquisition for new processes failed" );
            g_is_kernel_failure = TRUE;
            break;
        }

        for( i = 0; i < nScratch; i++ )
        {
            notifyOfProcess( new_from_kernel[ i ].pid,
                             new_from_kernel[ i ].ppid,
                             TRUE,
                             new_from_kernel[ i ].path,
                             new_from_kernel[ i ].cmdline,
                             new_from_kernel[ i ].uid,
                             new_from_kernel[ i ].ts );

            if( nProcessEntries >= ARRAY_N_ELEM( tracking_user ) - 1 )
            {
                continue;
            }

            tracking_user[ nProcessEntries ].pid = new_from_kernel[ i ].pid;
            tracking_user[ nProcessEntries ].ppid = new_from_kernel[ i ].ppid;
            nProcessEntries++;
        }

        for( i = 0; i < nProcessEntries; i++ )
        {
            if( !processLib_isPidInUse( tracking_user[ i ].pid ) )
            {
                notifyOfProcess( tracking_user[ i ].pid, 
                                 tracking_user[ i ].ppid, 
                                 FALSE, 
                                 NULL, 
                                 NULL,
                                 KERNEL_ACQ_NO_USER_ID,
                                 0 );
                if( nProcessEntries != i + 1 )
                {
                    rpal_memory_memmove( &(tracking_user[ i ]), &(tracking_user[ i + 1 ]), nProcessEntries - i + 1 );
                }
                nProcessEntries--;
            }
        }
    }
}
예제 #15
0
static
rList
    assembleRequest
    (
        RPU8 optCrashCtx,
        RU32 optCrashCtxSize
    )
{
    rSequence req = NULL;
    RU32 moduleIndex = 0;
    rList msgList = NULL;
    rList modList = NULL;
    rSequence modEntry = NULL;

    if( NULL != ( req = rSequence_new() ) )
    {
        // Add some basic info
        rSequence_addRU32( req, RP_TAGS_MEMORY_USAGE, rpal_memory_totalUsed() );
        rSequence_addTIMESTAMP( req, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() );

        // If we have a crash context to report
        if( NULL != optCrashCtx )
        {
            if( !rSequence_addBUFFER( req, RP_TAGS_HCP_CRASH_CONTEXT, optCrashCtx, optCrashCtxSize ) )
            {
                rpal_debug_error( "error adding crash context of size %d to hcp beacon", optCrashCtxSize );
            }
            else
            {
                rpal_debug_info( "crash context is being bundled in hcp beacon" );
            }
        }

        // List of loaded modules
        if( NULL != ( modList = rList_new( RP_TAGS_HCP_MODULE, RPCM_SEQUENCE ) ) )
        {
            for( moduleIndex = 0; moduleIndex < RP_HCP_CONTEXT_MAX_MODULES; moduleIndex++ )
            {
                if( NULL != g_hcpContext.modules[ moduleIndex ].hModule )
                {
                    if( NULL != ( modEntry = rSequence_new() ) )
                    {
                        if( !rSequence_addBUFFER( modEntry, 
                                                    RP_TAGS_HASH, 
                                                    g_hcpContext.modules[ moduleIndex ].hash, 
                                                    sizeof( g_hcpContext.modules[ moduleIndex ].hash ) ) ||
                            !rSequence_addRU8( modEntry, 
                                                RP_TAGS_HCP_MODULE_ID, 
                                                g_hcpContext.modules[ moduleIndex ].id ) ||
                            !rList_addSEQUENCE( modList, modEntry ) )
                        {
                            break;
                        }

                        // We take the opportunity to cleanup the list of modules...
                        if( rpal_thread_wait( g_hcpContext.modules[ moduleIndex ].hThread, 0 ) )
                        {
                            // This thread has exited, which is our signal that the module
                            // has stopped executing...
                            rEvent_free( g_hcpContext.modules[ moduleIndex ].isTimeToStop );
                            rpal_thread_free( g_hcpContext.modules[ moduleIndex ].hThread );
                            rpal_memory_zero( &(g_hcpContext.modules[ moduleIndex ]),
                                              sizeof( g_hcpContext.modules[ moduleIndex ] ) );

                            if( !rSequence_addRU8( modEntry, RP_TAGS_HCP_MODULE_TERMINATED, 1 ) )
                            {
                                break;
                            }
                        }
                    }
                }
            }

            if( !rSequence_addLIST( req, RP_TAGS_HCP_MODULES, modList ) )
            {
                rList_free( modList );
            }
        }

        if( NULL != ( msgList = rList_new( RP_TAGS_MESSAGE, RPCM_SEQUENCE ) ) )
        {
            if( !rList_addSEQUENCE( msgList, req ) )
            {
                rList_free( msgList );
                rSequence_free( req );
                msgList = NULL;
            }
        }
        else
        {
            rSequence_free( req );
        }
    }

    return msgList;
}
예제 #16
0
PObsNode
    addTransition
    (
        PObsNode parent,
        PObsNode node,
        PObsNode to,
        RU8 onValue
    )
{
    PObsNode retNode = NULL;
    RU32 currentNodeSize = 0;
    RU8 numElemToAdd = 0;
    RU8 indexToInsert = 0;
    PObsNode originalNode = node;
    RU32 i = 0;

    if( rpal_memory_isValid( node ) )
    {
        currentNodeSize = sizeof( ObsNode ) + ( node->nElements * sizeof( RPVOID ) );

        if( !IS_IN_RANGE( node, onValue ) )
        {
            if( onValue >= node->startOffset + node->nElements )
            {
                numElemToAdd = onValue - ( node->startOffset + node->nElements ) + 1;
            }
            else
            {
                numElemToAdd = node->startOffset - onValue;
            }

            if( node->nAllocated < node->nElements + numElemToAdd )
            {
                node = rpal_memory_realloc( node, currentNodeSize + ( numElemToAdd * sizeof( RPVOID ) ) );
                rpal_memory_zero( node->elements + node->nElements, numElemToAdd * sizeof( RPVOID ) );
                node->nAllocated = node->nElements + numElemToAdd;
            }

            if( onValue < node->startOffset &&
                0 < node->nElements )
            {
                rpal_memory_memmove( node->elements + numElemToAdd, node->elements, node->nElements * sizeof( RPVOID ) );
                node->startOffset = node->startOffset - (RU8)numElemToAdd;
            }

            node->nElements += numElemToAdd;

            // The above realloc may have changed the pointer so we need
            // to update it in the parent, if it exists...
            if( NULL != parent &&
                originalNode != node )
            {
                for( i = 0; i < parent->nElements; i++ )
                {
                    if( originalNode == parent->elements[ i ] )
                    {
                        parent->elements[ i ] = node;
                    }
                }
            }
        }

        indexToInsert = EFFECTIVE_INDEX( node, onValue );

        if( NULL == node->elements[ indexToInsert ] )
        {
            node->elements[ indexToInsert ] = to;

            retNode = node;
        }
    }

    return retNode;
}