static 
RPVOID
    networkDiffThread
    (
        rEvent isTimeToStop,
        RPVOID ctx
    )
{
    NetLib_Tcp4Table* currentTcp4Table = NULL;
    NetLib_Tcp4Table* oldTcp4Table = NULL;

    NetLib_UdpTable* currentUdpTable = NULL;
    NetLib_UdpTable* oldUdpTable = NULL;

    RU32 i = 0;
    RU32 j = 0;
    RBOOL isFound = FALSE;

    rSequence notif = NULL;
    rSequence comp = NULL;

    RU32 timeout = 100;
    RU32 nThLoop = 0;

    UNREFERENCED_PARAMETER( ctx );

    while( rpal_memory_isValid( isTimeToStop ) &&
           !rEvent_wait( isTimeToStop, 0 ) )
    {
        if( NULL != oldTcp4Table )
        {
            rpal_memory_free( oldTcp4Table );
            oldTcp4Table = NULL;
        }

        if( NULL != oldUdpTable )
        {
            rpal_memory_free( oldUdpTable );
            oldUdpTable = NULL;
        }

        // Swap the old snapshot for the (prev) new one
        oldTcp4Table = currentTcp4Table;
        oldUdpTable = currentUdpTable;
        currentTcp4Table = NULL;
        currentUdpTable = NULL;

        // Generate new tables
        currentTcp4Table = NetLib_getTcp4Table();
        currentUdpTable = NetLib_getUdpTable();

        // Diff TCP snapshots for new entries
        if( rpal_memory_isValid( currentTcp4Table ) &&
            rpal_memory_isValid( oldTcp4Table ) )
        {
            for( i = 0; i < currentTcp4Table->nRows; i++ )
            {
                isFound = FALSE;

                if( rEvent_wait( isTimeToStop, 0 ) )
                {
                    break;
                }

                for( j = 0; j < oldTcp4Table->nRows; j++ )
                {
                    if( isTcpEqual( &currentTcp4Table->rows[ i ], &oldTcp4Table->rows[ j ] ) )
                    {
                        isFound = TRUE;
                        break;
                    }
                }

                if( !isFound )
                {
                    if( NULL != ( notif = rSequence_new() ) )
                    {
                        if( rSequence_addRU32( notif, 
                                               RP_TAGS_STATE, 
                                               currentTcp4Table->rows[ i ].state ) &&
                            rSequence_addRU32( notif, 
                                               RP_TAGS_PROCESS_ID, 
                                               currentTcp4Table->rows[ i ].pid ) &&
                            rSequence_addTIMESTAMP( notif, 
                                                    RP_TAGS_TIMESTAMP, 
                                                    rpal_time_getGlobal() ) )
                        {
                            if( NULL != ( comp = rSequence_new() ) )
                            {
                                // Add the destination components
                                if( !rSequence_addIPV4( comp, 
                                                        RP_TAGS_IP_ADDRESS, 
                                                        currentTcp4Table->rows[ i ].destIp ) ||
                                    !rSequence_addRU16( comp, 
                                                        RP_TAGS_PORT, 
                                                        rpal_ntoh16( (RU16)currentTcp4Table->rows[ i ].destPort ) ) ||
                                    !rSequence_addSEQUENCE( notif, 
                                                            RP_TAGS_DESTINATION, 
                                                            comp ) )
                                {
                                    rSequence_free( comp );
                                    comp = NULL;
                                }
                            }

                            if( NULL != ( comp = rSequence_new() ) )
                            {
                                // Add the source components
                                if( !rSequence_addIPV4( comp, 
                                                        RP_TAGS_IP_ADDRESS, 
                                                        currentTcp4Table->rows[ i ].sourceIp ) ||
                                    !rSequence_addRU16( comp, 
                                                        RP_TAGS_PORT, 
                                                        rpal_ntoh16( (RU16)currentTcp4Table->rows[ i ].sourcePort ) ) ||
                                    !rSequence_addSEQUENCE( notif, 
                                                            RP_TAGS_SOURCE, 
                                                            comp ) )
                                {
                                    rSequence_free( comp );
                                    comp = NULL;
                                }
                            }

                            rpal_debug_info( "new tcp connection: 0x%08X = 0x%08X:0x%04X ---> 0x%08X:0x%04X -- 0x%08X.",
                                currentTcp4Table->rows[ i ].state,
                                currentTcp4Table->rows[ i ].sourceIp,
                                currentTcp4Table->rows[ i ].sourcePort,
                                currentTcp4Table->rows[ i ].destIp,
                                currentTcp4Table->rows[ i ].destPort,
                                currentTcp4Table->rows[ i ].pid );
                            notifications_publish( RP_TAGS_NOTIFICATION_NEW_TCP4_CONNECTION, notif );
                        }

                        rSequence_free( notif );
                    }
                }
            }
        }
        else if( 0 != nThLoop )
        {
            rpal_debug_warning( "could not get tcp connections table." );
        }


        // Diff TCP snapshots for new entries
        if( NULL != currentUdpTable &&
            NULL != oldUdpTable )
        {
            for( i = 0; i < currentUdpTable->nRows; i++ )
            {
                isFound = FALSE;

                if( rEvent_wait( isTimeToStop, 0 ) )
                {
                    break;
                }

                for( j = 0; j < oldUdpTable->nRows; j++ )
                {
                    if( isUdpEqual( &currentUdpTable->rows[ i ], &oldUdpTable->rows[ j ] ) )
                    {
                        isFound = TRUE;
                        break;
                    }
                }

                if( !isFound )
                {
                    if( NULL != ( notif = rSequence_new() ) )
                    {
                        if( !rSequence_addIPV4( notif, 
                                                RP_TAGS_IP_ADDRESS, 
                                                currentUdpTable->rows[ i ].localIp ) ||
                            !rSequence_addRU16( notif, 
                                                RP_TAGS_PORT, 
                                                rpal_ntoh16( (RU16)currentUdpTable->rows[ i ].localPort ) ) ||
                            !rSequence_addRU32( notif, 
                                                RP_TAGS_PROCESS_ID, 
                                                currentUdpTable->rows[ i ].pid ) ||
                            !rSequence_addTIMESTAMP( notif, 
                                                     RP_TAGS_TIMESTAMP, 
                                                     rpal_time_getGlobal() ) )
                        {
                            notif = NULL;
                        }
                        else
                        {
                            rpal_debug_info( "new udp connection: 0x%08X:0x%04X -- 0x%08X.",
                                currentUdpTable->rows[ i ].localIp,
                                currentUdpTable->rows[ i ].localPort,
                                currentUdpTable->rows[ i ].pid );
                            notifications_publish( RP_TAGS_NOTIFICATION_NEW_UDP4_CONNECTION, notif );
                        }

                        rSequence_free( notif );
                    }
                }
            }
        }
        else if( 0 != nThLoop )
        {
            rpal_debug_warning( "could not get udp connections table." );
        }

        nThLoop++;
        if( 0 == nThLoop % 10 )
        {
            timeout = libOs_getUsageProportionalTimeout( 1000 ) + 500;
        }

        rpal_thread_sleep( timeout );
    }

    rpal_memory_free( currentTcp4Table );
    rpal_memory_free( currentUdpTable );
    rpal_memory_free( oldTcp4Table );
    rpal_memory_free( oldUdpTable );

    return NULL;
}
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;
    }
}
예제 #3
0
static
rString
    assembleOutboundStream
    (
        RpHcp_ModuleId moduleId,
        rList payload,
        RU8 sessionKey[ CRYPTOLIB_SYM_KEY_SIZE ],
        RU8 sessionIv[ CRYPTOLIB_SYM_IV_SIZE ]
    )
{
    rString str = NULL;

    rSequence hdrSeq = NULL;
    rSequence hcpid = NULL;

    rBlob blob = NULL;

    RPCHAR encoded = NULL;

    RPU8 encBuffer = NULL;
    RU64 encSize = 0;

    RPU8 finalBuffer = NULL;
    RU32 finalSize = 0;

    RPCHAR hostName = NULL;

    RBOOL isSuccess = FALSE;

    OBFUSCATIONLIB_DECLARE( payHdr, RP_HCP_CONFIG_PAYLOAD_HDR );

    str = rpal_stringbuffer_new( 0, 0, FALSE );

    if( NULL != str )
    {
        if( NULL != ( hdrSeq = rSequence_new() ) )
        {
            if( NULL != ( hcpid = hcpIdToSeq( g_hcpContext.currentId ) ) )
            {
                // System basic information
                // Host Name
                if( NULL != ( hostName = libOs_getHostName() ) )
                {
                    rSequence_addSTRINGA( hdrSeq, RP_TAGS_HOST_NAME, hostName );
                    rpal_memory_free( hostName );
                }
                else
                {
                    rpal_debug_warning( "could not determine hostname" );
                }

                // Internal IP
                rSequence_addIPV4( hdrSeq, RP_TAGS_IP_ADDRESS, libOs_getMainIp() );

                if( rSequence_addSEQUENCE( hdrSeq, RP_TAGS_HCP_ID, hcpid ) &&
                    rSequence_addRU8( hdrSeq, RP_TAGS_HCP_MODULE_ID, moduleId ) &&
                    rSequence_addBUFFER( hdrSeq, RP_TAGS_SYM_KEY, sessionKey, CRYPTOLIB_SYM_KEY_SIZE ) &&
                    rSequence_addBUFFER( hdrSeq, RP_TAGS_SYM_IV, sessionIv, CRYPTOLIB_SYM_IV_SIZE ) )
                {
                    if( NULL != g_hcpContext.enrollmentToken &&
                        0 != g_hcpContext.enrollmentTokenSize )
                    {
                        rSequence_addBUFFER( hdrSeq, RP_TAGS_HCP_ENROLLMENT_TOKEN, g_hcpContext.enrollmentToken, g_hcpContext.enrollmentTokenSize );
                    }

                    if( NULL != payload )
                    {
                        blob = rpal_blob_create( 0, 0 );
                    }

                    if( NULL == payload ||
                        NULL != blob )
                    {
                        if( rSequence_serialise( hdrSeq, blob ) &&
                            ( NULL == payload ||
                              rList_serialise( payload, blob ) ) )
                        {
                            encSize = compressBound( rpal_blob_getSize( blob ) );
                            encBuffer = rpal_memory_alloc( (RU32)encSize );

                            if( NULL == payload ||
                                NULL != encBuffer )
                            {
                                if( NULL == payload ||
                                    Z_OK == compress( encBuffer, (uLongf*)&encSize, (RPU8)rpal_blob_getBuffer( blob ), rpal_blob_getSize( blob ) ) )
                                {
                                    FREE_N_NULL( blob, rpal_blob_free );

                                    if( NULL == payload ||
                                        CryptoLib_fastAsymEncrypt( encBuffer, (RU32)encSize, getC2PublicKey(), &finalBuffer, &finalSize ) )
                                    {
                                        FREE_N_NULL( encBuffer, rpal_memory_free );

                                        if( NULL == payload ||
                                            base64_encode( finalBuffer, finalSize, &encoded, TRUE ) )
                                        {
                                            isSuccess = TRUE;

                                            if( NULL != payload )
                                            {
                                                FREE_N_NULL( finalBuffer, rpal_memory_free );

                                                DO_IFF( rpal_stringbuffer_add( str, "&" ), isSuccess );

                                                OBFUSCATIONLIB_TOGGLE( payHdr );

                                                DO_IFF( rpal_stringbuffer_add( str, (RPCHAR)payHdr ), isSuccess );
                                                DO_IFF( rpal_stringbuffer_add( str, encoded ), isSuccess );
                                        
                                                OBFUSCATIONLIB_TOGGLE( payHdr );
                                            }

                                            IF_VALID_DO( encoded, rpal_memory_free );
                                        }

                                        IF_VALID_DO( finalBuffer, rpal_memory_free );
                                    }
                                }

                                IF_VALID_DO( encBuffer, rpal_memory_free );
                            }
                        }

                        IF_VALID_DO( blob, rpal_blob_free );
                    }
                }
            }

            rSequence_free( hdrSeq );
        }

        if( !isSuccess )
        {
            rpal_stringbuffer_free( str );
            str = NULL;
        }
    }

    return str;
}