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

50 views Asked by At

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.

0

There are 0 answers