2

Why do some functions in the callback function in WFP fail to be called normally?


Well, actually the demand is not troublesome. I need to use the TOS coverage of all IP packets sent by this machine as a custom field. So I modified the TOS field in the filtered callback function, and then recalculated the checksum. Everything is fine at this point. However, when I try to call an external function that generates a hash in the callback, something goes wrong - it compiles fine, but the WFP driver cannot be started at all in the test environment.

VOID generate_sign(
    _In_ unsigned char* key,
    _In_ unsigned int t,
    _Out_ unsigned char* result) {

    unsigned char input[SHA_DIGEST_LENGTH + 1];
    memset(input, 0, sizeof(input));
    input[0] = *key;

    unsigned char hash[SHA_DIGEST_LENGTH];
    SHA1(input, sizeof(input), hash);

    *result = 0;
    for (int i = 0; i < SHA_DIGEST_LENGTH; i++) {
        *result ^= hash[i];
    }
}
VOID FilterCallback_Sec(
    const FWPS_INCOMING_VALUES0* pInFixedValues,
    const FWPS_INCOMING_METADATA_VALUES* pInMetaValues,
    PVOID pLayerData,
    const VOID* context,
    const FWPS_FILTER* pFilter,
    UINT64 flowContext,
    FWPS_CLASSIFY_OUT* pClassifyOut) 
{
    UNREFERENCED_PARAMETER(pInFixedValues);
    UNREFERENCED_PARAMETER(pFilter);
    UNREFERENCED_PARAMETER(flowContext);
    UNREFERENCED_PARAMETER(pClassifyOut);

    if (pInMetaValues->currentMetadataValues & FWPS_METADATA_FIELD_IP_HEADER_SIZE) {
        PNET_BUFFER_LIST nbl = (PNET_BUFFER_LIST)pLayerData;
        PNET_BUFFER nb = NET_BUFFER_LIST_FIRST_NB(nbl);
        ULONG ipHeaderSize = pInMetaValues->ipHeaderSize;
        PVOID ipHeader = NdisGetDataBuffer(nb, ipHeaderSize, NULL, 1, 0);

        if (ipHeader != NULL) {
            UINT32 pid = (UINT32)pInMetaValues->processId;
            UINT32 srcAddr = ((PIPV4_HEADER)ipHeader)->SourceAddress;
            UINT32 dstAddr = ((PIPV4_HEADER)ipHeader)->DestinationAddress;
            
            unsigned char key[] = "secret";
            unsigned int timestamp = GetKernelTimestamp() / 10;
            unsigned int sign = 0;

            KIRQL oldIrql, newIrql;
            oldIrql = KeGetCurrentIrql();
            if (oldIrql > DISPATCH_LEVEL) {
                KeLowerIrql(DISPATCH_LEVEL);
            }

            // Here👇
            generate_sign(key, timestamp, &sign);

            KeRaiseIrql(oldIrql, &newIrql);

            ((PIPV4_HEADER)ipHeader)->TypeOfService = sign;
            ((PIPV4_HEADER)ipHeader)->HeaderChecksum = 0;
            ((PIPV4_HEADER)ipHeader)->HeaderChecksum = ComputeIpHeaderChecksum(ipHeader, ipHeaderSize);
            KdPrint(("[WFP Driver]PID: %d\tSrcAddr: %d.%d.%d.%d\tDstAddr:%d.%d.%d.%d\tNew TOS:0x%x\tHeaderChecksum:0x%x\r\n",
                pid,
                srcAddr & 0xFF, (srcAddr >> 8) & 0xFF, (srcAddr >> 16) & 0xFF, (srcAddr >> 24) & 0xFF,
                dstAddr & 0xFF, (dstAddr >> 8) & 0xFF, (dstAddr >> 16) & 0xFF, (dstAddr >> 24) & 0xFF,
                ((PIPV4_HEADER)ipHeader)->TypeOfService,
                ((PIPV4_HEADER)ipHeader)->HeaderChecksum));
        }
    }
}

As long as I call these functions, the above situation will occur, and when I don't call, the driver starts normally. I tried changing the IRQL level, but it didn't work.
This title and content for this question was made by "Windroid Xie" at this link: https://stackoverflow.com/questions/77590185/why-do-some-functions-in-the-callback-function-in-wfp-fail-to-be-called-normally. Contributions on stackoverflow.com are made under this license.

C Linux

0 Answers

Give your answer

Be sure to answer with an explanation on why your solution works.

Don't see an answer for your question?
Ask here

Search tags used in this post