Windows Filtering Platform Driver Issue

105 Views Asked by At

I have created an application in which GUI is connected to the driver which is performing some network data inspection. I created two callouts: on V4 Stream Layer and ALE_ESTABLISHED Layer. What is weird is that my program doesn't go into this if statement at all (I'm checking if "I'm here" is showing up in kernel debugger):

static void ProcessStreamData(
    const FWPS_INCOMING_VALUES0* inFixedValues,
    const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
    void* layerData,
    FWPS_CLASSIFY_OUT0* classifyOut) 
{
    KIRQL oldIrql;
    KeAcquireSpinLock(&ConnectionLock, &oldIrql);
    
    FWPS_STREAM_CALLOUT_IO_PACKET0* ioPacket = (FWPS_STREAM_CALLOUT_IO_PACKET0*)layerData;
    FWPS_STREAM_DATA0* streamData = ioPacket->streamData;
    WCHAR* ProcessName = L"unknown";
    ULONGLONG ProcessId = (ULONGLONG)inMetaValues->processId;
    UINT32 LocalIp = inFixedValues->incomingValue[FWPS_FIELD_STREAM_V4_IP_LOCAL_ADDRESS].value.uint32;
    UINT32 RemoteIp = inFixedValues->incomingValue[FWPS_FIELD_STREAM_V4_IP_REMOTE_ADDRESS].value.uint32;
    UINT16 LocalPort = inFixedValues->incomingValue[FWPS_FIELD_STREAM_V4_IP_LOCAL_PORT].value.uint16;
    UINT16 RemotePort = inFixedValues->incomingValue[FWPS_FIELD_STREAM_V4_IP_REMOTE_PORT].value.uint16;

    for (int i = 0; i < MAX_CONNECTIONS; i++)
    {
        ConnectionInfo connection = g_Connections[i];
        
        if (connection.ProcessId == ProcessId && connection.LocalIp == LocalIp && connection.RemoteIp == RemoteIp && connection.LocalPort == LocalPort && connection.RemotePort == RemotePort)
        {
            KdPrint(("I'm here"));
            if (streamData->flags == FWPS_STREAM_FLAG_RECEIVE) {
                g_Connections[i].BytesReceived += streamData->dataLength;
        
            }
            else if (streamData->flags == FWPS_STREAM_FLAG_SEND) {
                g_Connections[i].BytesSent += streamData->dataLength;
            }
        }
    }

    KeReleaseSpinLock(&ConnectionLock, oldIrql);
}

This is called from StreamCalloutConnectClassifyFn:

static void StreamCalloutConnectClassifyFn(
    const FWPS_INCOMING_VALUES0* inFixedValues,
    const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
    void* layerData,
    const FWPS_FILTER0* filter,
    UINT64 /*flowContext*/,
    FWPS_CLASSIFY_OUT0* classifyOut)
{
    // Allowing the traffic for another filter to make a final decision.
    if (FlagOn(classifyOut->rights, FWPS_RIGHT_ACTION_WRITE))
    {
        classifyOut->actionType = FWP_ACTION_CONTINUE;
    }

    ProcessStreamData(inFixedValues, inMetaValues, layerData, classifyOut);

    // Callout function should clear the FWPS_RIGHT_ACTION_WRITE flag when it returns FWP_ACTION_BLOCK for the suggested action
    // and if FWPS_FILTER_FLAG_CLEAR_ACTION_RIGHT flag is set
    if (FWP_ACTION_BLOCK == classifyOut->actionType || FlagOn(filter->flags, FWPS_FILTER_FLAG_CLEAR_ACTION_RIGHT))
    {
        ClearFlag(classifyOut->rights, FWPS_RIGHT_ACTION_WRITE);
    }
}

And this is called from Initialize Callout:

static NTSTATUS InitializeCallout(PDEVICE_OBJECT deviceObject)
{
    /*FWPM_SUBLAYER subLayer = {};
    subLayer.displayData.name = const_cast<wchar_t*>(L"TcpInterception Sub-Layer");
    subLayer.subLayerKey = TCP_INTERCEPTION_SUBLAYER;*/

   /* NTSTATUS status = FwpmSubLayerAdd(g_engineHandle, &subLayer, nullptr);*/
    NTSTATUS status;

    FWPS_CALLOUT0 sCallout =
    {
        TCP_INTERCEPTION_TRANSPORT_V4_CALLOUT,  // calloutKey
        0,  // flags
        CalloutConnectClassifyFn,  // classifyFn
        CalloutNotifyFn,  // notifyFn
        FlowDeleteNotifyFn  // flowDeleteFn
    };

    status = FwpsCalloutRegister0(deviceObject, &sCallout, &g_id);
    if (!NT_SUCCESS(status))
    {
        return status;
    }

    FWPM_CALLOUT mCallout = {};
    mCallout.calloutKey = TCP_INTERCEPTION_TRANSPORT_V4_CALLOUT;
    mCallout.applicableLayer = FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4;
    mCallout.displayData.name = const_cast<wchar_t*>(g_displayName);

    status = FwpmCalloutAdd(g_engineHandle, &mCallout, nullptr, nullptr);
    if (!NT_SUCCESS(status))
    {
        return status;
    }



    FWPS_CALLOUT0 StreamCallout =
    {
        STREAM_V4_CALLOUT,
        0,
        StreamCalloutConnectClassifyFn,
        StreamCalloutNotifyFn,
        StreamFlowDeleteNotifyFn
    };
    status = FwpsCalloutRegister0(deviceObject, &StreamCallout, &g_StreamId);
    if (!NT_SUCCESS(status))
    {
        return status;
    }

    FWPM_CALLOUT mStreamCallout = {};
    mStreamCallout.calloutKey = STREAM_V4_CALLOUT;
    mStreamCallout.applicableLayer = FWPM_LAYER_STREAM_V4;
    mStreamCallout.displayData.name = const_cast<wchar_t*>(g_displayNameStream);

    status = FwpmCalloutAdd(g_engineHandle, &mStreamCallout, nullptr, nullptr);
    if (!NT_SUCCESS(status))
    {
        return status;
    }

   /*  Add Filter for TCP only*/
    FWPM_FILTER_CONDITION filterCondition = {};
    filterCondition.fieldKey = FWPM_CONDITION_IP_PROTOCOL;
    filterCondition.matchType = FWP_MATCH_EQUAL;
    filterCondition.conditionValue.type = FWP_UINT8;
    filterCondition.conditionValue.uint16 = IPPROTO_TCP;

    FWPM_FILTER filter = {};
    filter.layerKey = FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4;
    filter.displayData.name = const_cast<wchar_t*>(g_displayName);;
    filter.displayData.description = filter.displayData.name;

    filter.action.type = FWP_ACTION_CALLOUT_INSPECTION;
    filter.action.calloutKey = TCP_INTERCEPTION_TRANSPORT_V4_CALLOUT;
    filter.filterCondition = &filterCondition;
    filter.numFilterConditions = 1;
    filter.subLayerKey = FWPM_SUBLAYER_UNIVERSAL;
    filter.weight.type = FWP_EMPTY;

    status = FwpmFilterAdd(g_engineHandle, &filter, NULL, NULL);
    if (!NT_SUCCESS(status))
    {
        return status;
    }


    FWPM_FILTER Streamfilter = {};
    Streamfilter.layerKey = FWPM_LAYER_STREAM_V4;
    Streamfilter.displayData.name = const_cast<wchar_t*>(g_displayName);;
    Streamfilter.displayData.description = Streamfilter.displayData.name;

    Streamfilter.action.type = FWP_ACTION_CALLOUT_INSPECTION;
    Streamfilter.action.calloutKey = STREAM_V4_CALLOUT;
    Streamfilter.filterCondition = 0;
    Streamfilter.numFilterConditions = 0;
    Streamfilter.subLayerKey = FWPM_SUBLAYER_UNIVERSAL;
    Streamfilter.weight.type = FWP_EMPTY;

    status = FwpmFilterAdd(g_engineHandle, &Streamfilter, NULL, NULL);
    if (!NT_SUCCESS(status))
    {
        return status;
    }

    return status;
}

Does anyone have suggestions?

0

There are 0 best solutions below