I observed one problem…
An av-anti software with a minifilter.
It will get fsd driver’s dispatch table,So it get the FsdRead func address.’
It will call NtCreateFile(…file_open_no_intermedia…),and call fsd driver’s FsdRead(skip all filter).
But,when it call FsdRead,the call stack is:
Child-SP RetAddr Call Site
fffff88003897ec0 fffff800
03ea2439 fastfat!FatFsdRead(struct _VOLUME_DEVICE_OBJECT * VolumeDeviceObject = 0xfffffa801a40f6f0, struct _IRP * Irp = 0xfffffa80
1c913480)+0x2e [e:\winddk\7600.16385.1\src\filesys\fastfat\win7\read.c @ 164]
fffff88003897f50 fffff800
0411589f nt!IoPageRead+0x2a9
fffff88003897fe0 fffff800
04115999 nt!MiPfExecuteReadList+0xff
fffff88003898040 fffff800
03e69473 nt!MmPrefetchForCacheManager+0xb5
fffff88003898090 fffff800
04166e90 nt!CcFetchDataForRead+0xd3
fffff880038980f0 fffff880
05b7d0c7 nt!CcCopyRead+0x180
fffff880038981b0 fffff880
05b37e63 fastfat!FatCommonRead(struct _IRP_CONTEXT * IrpContext = 0xfffffa8019966c30, struct _IRP * Irp = 0xfffffa80
1c6d9010)+0x1297 [e:\winddk\7600.16385.1\src\filesys\fastfat\win7\read.c @ 1372]
fffff88003898340 fffff880
04e7794c fastfat!FatFsdRead(struct _VOLUME_DEVICE_OBJECT * VolumeDeviceObject = 0xfffffa801a40f6f0, struct _IRP * Irp = 0xfffffa80
1c6d9010)+0x1e3 [e:\winddk\7600.16385.1\src\filesys\fastfat\win7\read.c @ 243]
fffff880038983d0 fffff880
04e74f76 TSSysKit64+0x894c
fffff880038984f0 fffff880
04e7097a TSSysKit64+0x5f76
fffff880038986b0 fffff800
04187e4a TSSysKit64+0x197a
fffff88003898850 fffff800
0419c36c nt!IopSynchronousServiceTail+0xfa
fffff880038988c0 fffff800
0419c406 nt!IopXxxControlFile+0xc49
fffff88003898a00 fffff800
03e790d3 nt!NtDeviceIoControlFile+0x56
fffff88003898a70 00000000
74aa2e09 nt!KiSystemServiceCopyEnd+0x13
0000000005dbeef8 00000000
74aa2944 wow64cpu!CpupSyscallStub+0x9
0000000005dbef00 00000000
74b1d286 wow64cpu!DeviceIoctlFileFault+0x31
0000000005dbefc0 00000000
74b1c69e wow64!RunCpuSimulation+0xa
0000000005dbf010 00000000
770398ec wow64!Wow64LdrpInitialize+0x42a
0000000005dbf560 00000000
76ffa36e ntdll! ?? ::FNODOBFM::string'+0x22b74 00000000
05dbf5d0 00000000`00000000 ntdll!LdrInitializeThunk+0xe
My question is:
why nt!IoPageRead call fastfat!FatFsdRead directly?why it will skip all filter?
In my mind,the cached read will issue the paging IO,and the Paging read will call the filter stack and fsd,right?
The not exhaustive list of possible scenarios are as follows
-
the AV driver/minifilter calls IoCreateFileSpecifyDeviceObjectHint with a DeviceObject hint set to the bottom of the FSD stack, the created file object is used by the Memory Manager to back data section, in that case the IO Manager skips all attached device objects ( including minifilters ) when dispatching paging IO ( this happens in a call to IoGetRelatedDeviceObject when preparing an IRP for paging IO )
-
the data section is backed by a file object opened with IoCreateFileSpecifyDeviceObjectHint as described above by somebody else ( not the AV driver/minifilter ), the Memory Manager issues paging read requests to a file object which was used to initialise structures supporting file mapping ( i.e. data section ) and this file object might not be the file object used by the AV driver/minifilter for cached data IO
-
the FilterManager failed to attach a minifilter device object to the FSD stack
oh shit…the av-anti software(TSSysKit64)…just call FsdCreate directly!
kd> k
Child-SP RetAddr Call Site
fffff88003924a60 fffff880
05af3d27 fastfat!FatCommonCreate+0x23b5 [e:\winddk\7600.16385.1\src\filesys\fastfat\win7\create.c @ 1750]
fffff88003925040 fffff800
041cf2bb fastfat!FatFsdCreate+0xb7 [e:\winddk\7600.16385.1\src\filesys\fastfat\win7\create.c @ 322]
fffff88003925090 fffff800
041cadde nt!IopParseDevice+0x14e2
fffff880039251f0 fffff800
041cb8c6 nt!ObpLookupObjectName+0x784
fffff880039252f0 fffff880
053a66c0 nt!ObOpenObjectByName+0x306
fffff880039253c0 fffff880
053a5e77 TSSysKit64+0x26c0
fffff88003925460 fffff880
053aab74 TSSysKit64+0x1e77
fffff880039254f0 fffff880
053a597a TSSysKit64+0x6b74
fffff880039256b0 fffff800
041d8e4a TSSysKit64+0x197a
fffff88003925850 fffff800
041ed36c nt!IopSynchronousServiceTail+0xfa
fffff880039258c0 fffff800
041ed406 nt!IopXxxControlFile+0xc49
fffff88003925a00 fffff800
03eca0d3 nt!NtDeviceIoControlFile+0x56
fffff88003925a70 00000000
74882e09 nt!KiSystemServiceCopyEnd+0x13
0000000004dde9f8 00000000
74882944 wow64cpu!CpupSyscallStub+0x9
0000000004ddea00 00000000
748fd286 wow64cpu!DeviceIoctlFileFault+0x31
0000000004ddeac0 00000000
748fc69e wow64!RunCpuSimulation+0xa
0000000004ddeb10 00000000
76e198ec wow64!Wow64LdrpInitialize+0x42a
0000000004ddf060 00000000
76dda36e ntdll! ?? ::FNODOBFM::string'+0x22b74 00000000
04ddf0d0 00000000`00000000 ntdll!LdrInitializeThunk+0xe
kd> dt _FILE_OBJECT 0xfffffa80196a2880 ntdll!_FILE_OBJECT +0x000 Type : 5 +0x002 Size : 0xd8 +0x008 DeviceObject : 0xfffffa80
19c1fcd0 _DEVICE_OBJECT
+0x010 Vpb : 0xfffffa8019805990 _VPB +0x018 FsContext : 0xfffff8a0
00622320 Void
+0x020 FsContext2 : 0xfffff8a006788cb0 Void +0x028 SectionObjectPointer : 0xfffffa80
1a214710 _SECTION_OBJECT_POINTERS
+0x030 PrivateCacheMap : (null)
+0x038 FinalStatus : 0
+0x040 RelatedFileObject : (null)
+0x048 LockOperation : 0 ‘’
+0x049 DeletePending : 0 ‘’
+0x04a ReadAccess : 0 ‘’
+0x04b WriteAccess : 0 ‘’
+0x04c DeleteAccess : 0 ‘’
+0x04d SharedRead : 0 ‘’
+0x04e SharedWrite : 0 ‘’
+0x04f SharedDelete : 0 ‘’
+0x050 Flags : 0x42
+0x058 FileName : _UNICODE_STRING “\test\test.docx”
+0x068 CurrentByteOffset : _LARGE_INTEGER 0x0
+0x070 Waiters : 0
+0x074 Busy : 0
+0x078 LastLock : (null)
+0x080 Lock : _KEVENT
+0x098 Event : _KEVENT
+0x0b0 CompletionContext : (null)
+0x0b8 IrpListLock : 0
+0x0c0 IrpList : _LIST_ENTRY [0xfffffa80196a2940 - 0xfffffa80
196a2940]
+0x0d0 FileObjectExtension : 0xfffffa80`192bd4c0 Void
kd> dt _VPB 0xfffffa8019805990 ntdll!_VPB +0x000 Type : 0xa +0x002 Size : 0x60 +0x004 Flags : 1 +0x006 VolumeLabelLength : 6 +0x008 DeviceObject : 0xfffffa80
1aaa1970 _DEVICE_OBJECT
+0x010 RealDevice : 0xfffffa80`19c1fcd0 _DEVICE_OBJECT
+0x018 SerialNumber : 0xaa43f7f
+0x01c ReferenceCount : 0x10
+0x020 VolumeLabel : [32] “???”
kd> !devstack 0xfffffa80`1aaa1970
!DevObj !DrvObj !DevExt ObjectName
fffffa801aab09a0 \FileSystem\FltMgr fffffa801aab0af0
fffffa801aaa1970 \FileSystem\fastfatfffffa801aaa1ac0
kd> !devstack 0xfffffa80`19c1fcd0
!DevObj !DrvObj !DevExt ObjectName
fffffa8019c27340 \Driver\volsnap fffffa8019c27490
fffffa8019c25770 \Driver\rdyboost fffffa8019c258c0
fffffa8019c25b70 \Driver\fvevol fffffa8019c25cc0
fffffa8019c1fcd0 \Driver\volmgr fffffa8019c1fe20 HarddiskVolume2
!DevNode fffffa8019c1f290 :
DeviceInst is “STORAGE\Volume{cba9e03f-c52f-11e7-8054-806e6f6e6963}#0000000000010000”
ServiceName is “volsnap”
Nope. The AV driver uses a call to ObOpenObjectByName and it provides a TopDeviceObjectHint as a parameter. This is analogues to calling IoCreateFileSpecifyDeviceObjectHint which also calls ObOpenObjectByName with OpenPacket->TopDeviceObjectHint. For unknown reasons the AV developer decided to use an undocumented ObOpenObjectByName instead of IoCreateFileSpecifyDeviceObjectHint which is effectively a wrapper for ObOpenObjectByName. IoCreateFileSpecifyDeviceObjectHint verifies input parameters and calls ObOpenObjectByName.
This case is the first scenario in the above list, just replace IoCreateFileSpecifyDeviceObjectHint with ObOpenObjectByName