@“Peter_Viscarola_(OSR)” I am sorry for being impolite
I am copying the contents of the original PDF below which has four sections. It has the driver code excerpts, the crash analysis, comparison on a laptop where things work fine (setting break points like Peter suggested) and system information where the crash was seen.
Crash In NetIO.sys When Using A WFP Based Driver
Section 1: Driver Information
The purpose of this driver is to identify at the kernel layer user space applications that initiate a session. In certain installations we observed crashes pointing to NETIO.sys. To get to the root of the problem a stripped-down driver was created which does not have all the functionality of the original driver. In this driver sample the callout is added to the layer FWPM_LAYER_ALE_CONNECT_REDIRECT_V4. The API call sequence is roughly as follows.
InitializationCode() {
NtStatus = FwpmTransactionBegin0(hFilterEngine, 0);
NtStatus = FwpmSubLayerAdd(hFilterEngine, &fwpmSublayer, NULL);
NtStatus = FwpsCalloutRegister(DeviceObject, &fwpsCallout, calloutID);
NtStatus = FwpmCalloutAdd0(hFilterEngine, &fwpmCallout, NULL, calloutID);
condition[0].fieldKey = FWPM_CONDITION_IP_LOCAL_PORT;
condition[0].matchType = FWP_MATCH_LESS_OR_EQUAL;
condition[0].conditionValue.type = FWP_UINT16;
condition[0].conditionValue.uint16 = 65535;
fwpmFilter.action.type = FWP_ACTION_CALLOUT_UNKNOWN;
fwpmFilter.weight.uint32 = 50000;
fwpmFilter.numFilterConditions = 1;
fwpmFilter.filterCondition = condition;fwpmFilter.action.calloutKey = calloutGUID;
NtStatus = FwpmFilterAdd0(hFilterEngine, &fwpmFilter, NULL, filterID);
NtStatus = FwpmTransactionCommit0(hFilterEngine);
NtStatus = FwpsInjectionHandleCreate(AF_INET,
FWPS_INJECTION_TYPE_TRANSPORT | FWPS_INJECTION_TYPE_FORWARD |
FWPS_INJECTION_TYPE_NETWORK, &hInjectionHandle);
}
void ClassifyFn (
{
NtStatus = FwpsAcquireClassifyHandle((void*)classifyContext, 0, &(pktCtx-
classifyHandle));
NtStatus = FwpsAcquireWritableLayerDataPointer(pktCtx->classifyHandle, filter-
filterId, 0, &writableLayerData, classifyOut);
NtStatus = FwpsPendClassify(pktCtx->classifyHandle, filter->filterId, 0, pktCtx-
classifyOut);
//Allocate a WorkItem to get the application name.
IoQueueWorkItem(workItem, GetApplicationName, DelayedWorkQueue,
(void*)pktCtx);classifyOut->actionType = FWP_ACTION_BLOCK;
classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
}
void
GetApplicationName(
In PDEVICE_OBJECT DevObject,
In PVOID ctx
)
//After all processing the code goes to exit where the pend operation is complete and the packet is let
//through. The crash is seen when invoking FwpsApplyModifiedLayerData.
Exit:
if (ctx != NULL) {
if (pktCtx->workItem != NULL) {
IoFreeWorkItem(pktCtx->workItem);
}
pktCtx->classifyOut->actionType = FWP_ACTION_PERMIT;
pktCtx->classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
/* I also experimented with pktCtx->classifyOut->rights |=
FWPS_RIGHT_ACTION_WRITE; */
if (pktCtx->layerData != NULL && pktCtx->classifyHandle != 0)
FwpsApplyModifiedLayerData(pktCtx->classifyHandle, pktCtx->layerData, 0);
if (pktCtx->classifyHandle != 0) {
FwpsCompleteClassify(pktCtx->classifyHandle, 0, pktCtx->classifyOut);
FwpsReleaseClassifyHandle(pktCtx->classifyHandle);
}
if (pktCtx->classifyOut)ExFreePool(pktCtx->classifyOut);
ExFreePoolWithTag(ctx, PKT_TAG);
}
}
Section 2: Crash Analysis On Memory Dump File
1: kd> !analyze -v
SYSTEM_THREAD_EXCEPTION_NOT_HANDLED (7e)
Arg1: ffffffffc0000005, The exception code that was not handled => Access violation code c0000005
raised when invalid memory is access
Arg2: fffff80487d9e6ec, The address that the exception occurred at => This address is the code
location which has the bug
Arg3: fffff90d1eac7708, Exception Record Address
Arg4: fffff90d1eac6f40, Context Record Address
1: kd> u fffff80487d9e6ec => Disassembly of code location where exception is seen
NETIO!FeApplyModifiedLayerData+0x2c:fffff80487d9e6ec 80783800 cmp byte ptr [rax+38h],0 ** REDACTED ** 1: kd> dd rax fffff90d
1eac6f40 00000000 00000000 00000000 00000000
BUGCHECK_CODE: 7e
BUGCHECK_P1: ffffffffc0000005
BUGCHECK_P2: fffff80487d9e6ec
BUGCHECK_P3: fffff90d1eac7708
BUGCHECK_P4: fffff90d1eac6f40
EXCEPTION_RECORD: fffff90d1eac7708 – (.exr 0xfffff90d1eac7708)
ExceptionAddress: fffff80487d9e6ec (NETIO!FeApplyModifiedLayerData+0x000000000000002c)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 0000000000000000
Parameter[1]: 0000000000000038
Attempt to read from address 0000000000000038
CONTEXT: fffff90d1eac6f40 – (.cxr 0xfffff90d1eac6f40)
rax=0000000000000000 rbx=0000000000000000 rcx=ffffd681c17a8180rdx=0000000000000000 rsi=0000000000000000 rdi=0000432f00003319
rip=fffff80487d9e6ec rsp=fffff90d1eac7940 rbp=ffffc409885035a0
r8=ffffc40964cd5340 r9=4121890e4b3f792b r10=fffff804832bf8e0
r11=fffff80487dca4f8 r12=0000000000000300 r13=0000000000000000
r14=0000000000000000 r15=fffff80483d24440
iopl=0
nv up ei ng nz na pe nc
cs=0010 ss=0000 ds=002b es=002b fs=0053 gs=002b
efl=00050282
NETIO!FeApplyModifiedLayerData+0x2c:
fffff80487d9e6ec 80783800 cmp byte ptr [rax+38h],0 ds:002b:00000000
00000038=??
Resetting default scope
BLACKBOXBSD: 1 (!blackboxbsd)
BLACKBOXNTFS: 1 (!blackboxntfs)
BLACKBOXPNP: 1 (!blackboxpnp)
BLACKBOXWINLOGON: 1
PROCESS_NAME: System
READ_ADDRESS: 0000000000000038
ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The
memory could not be %s.
EXCEPTION_CODE_STR: c0000005
EXCEPTION_PARAMETER1: 0000000000000000
EXCEPTION_PARAMETER2: 0000000000000038
EXCEPTION_STR: 0xc0000005
STACK_TEXT:
fffff90d1eac7940 fffff804
8813793a : ffffc409866db060 ffffc409
84c56510 ffffc4097fb9d080 01000000
00100000 : NETIO!FeApplyModifiedLayerData+0x2c
fffff90d1eac7970 fffff804
7f101c78 : fffff8047f103180 ffffc409
7f2ef020 ffffc4097dd49710 00000000
00000000 : fwpkclnt!FwpsApplyModifiedLayerData0+0x1afffff90d1eac79a0 fffff804
83274835 : ffffc40984c56510 ffffc409
81834920 ffffc40984c56510 ffffc409
7a584080 : TestDriver!GetApplicationInformation+0x1d8
[C:\Users\WinnyThomas\Desktop\TestDriver\TestDriver\TestDriver.cpp @ 176]
fffff90d1eac7a00 fffff804
832b86d5 : ffffc40980d5a040 ffffc409
80d5a040 fffff80483274700 ffffc409
00000000 : nt!IopProcessWorkItem+0x135
fffff90d1eac7a70 fffff804
83355a15 : ffffc40980d5a040 00000000
00000080 ffffc409640a3180 00000000
00000001 : nt!ExpWorkerThread+0x105
fffff90d1eac7b10 fffff804
833fec78 : ffffd681c17a8180 ffffc409
80d5a040 fffff804833559c0 00000000
00000006 : nt!PspSystemThreadStartup+0x55
fffff90d1eac7b60 00000000
00000000 : fffff90d1eac8000 fffff90d
1eac1000 0000000000000000 00000000
00000000 : nt!KiStartSystemThread+0x28
SYMBOL_NAME: NETIO!FeApplyModifiedLayerData+2c
MODULE_NAME: NETIO
IMAGE_NAME: NETIO.SYS
STACK_COMMAND: .cxr 0xfffff90d1eac6f40 ; kb
BUCKET_ID_FUNC_OFFSET: 2c
FAILURE_BUCKET_ID: AV_NETIO!FeApplyModifiedLayerData
OS_VERSION: 10.0.19041.1
BUILDLAB_STR: vb_release
OSPLATFORM_TYPE: x64
OSNAME: Windows 10
FAILURE_ID_HASH: {30594c57-1544-e0e5-206d-d31719fbe7f2}
Followup:
MachineOwner
Inside TestDriver!GetApplicationName at the offset shown (0x1d8) I call the fwpkclnt API FwpsApplyModifiedLayerData. This API is called when I hold onto a packet for a while to make changes and a policy decision. The parameters to this function are an injection handle, a buffer and a flag. Early in the driver initialization I verify the handle is valid, if not the driver wont start because this handle is crucial. Next, I do verify I have valid buffer data to work on.If not, which can happen sometimes, the driver never enters the code path which calls FwpsApplyModifiedLayerData and finally the flag is set to the recommended FWPS_CLASSIFY_FLAG_REAUTHORIZE_IF_MODIFIED_BY_OTHERS. So, the parameters I pass in when I invoke the API are valid. When the call passes on from my driver to fwpkclnt and then to NETIO.sys, a null pointer deference is seen in NETIO.sys
Section 3: Analysis Of Same Code Path On A Separate Laptop Where No Crash Is Seen
Comparison with a laptop where I am running the same driver and recent windows update
0: kd> kb
00 fffff808dee15544 : 00000000
00000001 0000000000000554 00000000
00000000
0000000000000554 : NETIO!FeApplyModifiedLayerData+0x2c => this is the location where a pointer dereference happens, same as in your case, but in my case, there is a valid pointer in rax as you see below 01 fffff800
38c92591 : ffffb48869a04010 fffff800
38c92000 ffffb48800000213 ffffffff
434f5250 : fwpkclnt!FwpsApplyModifiedLayerData0+0x14 => this offset location is
different because I am using an updated windows version 20H2
02 fffff800396fe14b : ffffb488
671999b0 00000000000002a0 00000000
00000554
ffffb4886244a3d0 : TestDriver!GetApplicationInformation +0x1d8 => You see the same offset inside my driver calling fwpkclnt. 03 fffff800
3963ee05 : ffffb4886244a3d0 ffffb488
6308a700 fffff800396fe050 00000000
0000000c : nt!IopProcessWorkItem+0xfb
04 fffff8003962af87 : 00000000
00000000 0000000000000080 ffffb488
624cd040
ffffb4886308a700 : nt!ExpWorkerThread+0xf5 05 fffff800
3976b676 : ffffe101a9c20180 ffffb488
6308a700 fffff8003962af40 00000000
00000246 : nt!PspSystemThreadStartup+0x47
06 0000000000000000 : fffff50f
9c540000 fffff50f9c539000 00000000
00000000
0000000000000000 : nt!KiStartSystemThread+0x16 0: kd> r raxrax=ffffb488693ea9f0 0: kd> db rax+38h => unlike in the memory dump where the memory evaluates to 0x00000000 + 38h in my case it evaluates to ffffb488693ea9f0 + 38h. Which is a valid memory ffffb488
693eaa28 01 00 01 00 00 00 00 00-00 00 00 00 00 00 00 00 … => The
contents of the dereference memory is highlighted in green. Only one byte is used in the
comparison operation in NETIO.SYS
ffffb488`693eaa38 00 00 00 00 00 00 00 00-af 05 01 00 00 00 00 00 …
Section 4: System Information Where The Crash Is Seen
NETIO.sys Version: 10.0.19041.1566
Edition Windows 10 Enterprise
Version 21H1