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.