I have a minifilter that monitors IRP_MJ_WRITE notifications. I’m interested to capture every file written by user-mode applications, so in my preWrite callback, I used to ignore notifications that came from System.
if (PsInitialSystemProcess == PsGetCurrentProcess())
{
goto Leave;
}
This code worked well and among other write operations, I was also able to intercept every copy-paste operation made by explorer.exe.
0: kd> k
# Child-SP RetAddr Call Site
00 fffff582`15e295f0 fffff802`53794a5d MyDriver!MyMinifilter::FilterPreWrite+0x182
01 fffff582`15e29690 fffff802`537945a0 FLTMGR!FltpPerformPreCallbacks+0x2fd
02 fffff582`15e297a0 fffff802`53794112 FLTMGR!FltpPassThroughInternal+0x90
03 fffff582`15e297d0 fffff802`53793efe FLTMGR!FltpPassThrough+0x162
04 fffff582`15e29850 fffff802`52646f79 FLTMGR!FltpDispatch+0x9e
05 fffff582`15e298b0 fffff802`52bfe5e5 nt!IofCallDriver+0x59
06 fffff582`15e298f0 fffff802`52c5bb46 nt!IopSynchronousServiceTail+0x1a5
07 fffff582`15e29990 fffff802`527e7d15 nt!NtWriteFile+0x676
08 fffff582`15e29a90 00007ff9`afd1c1c4 nt!KiSystemServiceCopyEnd+0x25
09 00000000`05b1ce98 00007ff9`ad78512d ntdll!NtWriteFile+0x14
0a 00000000`05b1cea0 00007ff9`ad7a5450 KERNELBASE!WriteFile+0xfd
0b 00000000`05b1cf10 00007ff9`ad79dd85 KERNELBASE!BaseCopyStream+0x4d28
0c 00000000`05b1e140 00007ff9`ad7e12db KERNELBASE!BasepCopyFileExW+0x7c5
0d 00000000`05b1e7c0 00007ff9`ad0fb838 KERNELBASE!CopyFile2+0xeb
0e 00000000`05b1e880 00007ff9`ad0f7073 windows_storage!CFSTransfer::_PerformCopyFileWithRetry+0xa4
0f 00000000`05b1e910 00007ff9`ad101587 windows_storage!CFSTransfer::CopyItem+0x1f3
10 00000000`05b1e970 00007ff9`ad024e53 windows_storage!CDelegatingTransfer::CopyItem+0xc7
11 00000000`05b1ea30 00007ff9`ad01664f windows_storage!CCopyOperation::_CreateDestinationOrCopyItemWithRetry+0xef
12 00000000`05b1eb00 00007ff9`acc5124f windows_storage!CCopyOperation::Do+0x10f
13 00000000`05b1ec00 00007ff9`acc4f63f windows_storage!CCopyWorkItem::_DoOperation+0x9b
14 00000000`05b1ece0 00007ff9`acc4fd3a windows_storage!CCopyWorkItem::_SetupAndPerformOp+0x2a3
15 00000000`05b1efd0 00007ff9`acc4dda8 windows_storage!CCopyWorkItem::ProcessWorkItem+0x152
16 00000000`05b1f280 00007ff9`acc55953 windows_storage!CRecursiveFolderOperation::Do+0x1a8
17 00000000`05b1f320 00007ff9`acc55476 windows_storage!CFileOperation::_EnumRootDo+0x253
18 00000000`05b1f3c0 00007ff9`acc56d0c windows_storage!CFileOperation::PrepareAndDoOperations+0x1ce
19 00000000`05b1f490 00007ff9`ae1f24e9 windows_storage!CFileOperation::PerformOperations+0x10c
1a 00000000`05b1f4f0 00007ff9`ae1f1518 SHELL32!CFSDropTargetHelper::_MoveCopyHIDA+0x269
1b 00000000`05b1f5a0 00007ff9`ae1f3077 SHELL32!CFSDropTargetHelper::_Drop+0x1e8
1c 00000000`05b1fa80 00007ff9`aeafdce5 SHELL32!CFSDropTargetHelper::s_DoDropThreadProc+0x37
1d 00000000`05b1fab0 00007ff9`af257bd4 shcore!_WrapperThreadProc+0xf5
1e 00000000`05b1fb90 00007ff9`afceced1 KERNEL32!BaseThreadInitThunk+0x14
1f 00000000`05b1fbc0 00000000`00000000 ntdll!RtlUserThreadStart+0x21
0: kd> !process -1 0
PROCESS ffffd90d7c00e400
SessionId: 1 Cid: 0eac Peb: 008cf000 ParentCid: 0e94
DirBase: 32c51002 ObjectTable: ffff958f10d58180 HandleCount: 2210.
Image: explorer.exe
Starting from windows 11 22H2 , I stopped catching explorer’s copy-paste operations, after debugging the issue it turns out that these PreWrite operations are now being carried out by a separate System thread (and not under explorer.exe context):
kd> k
# Child-SP RetAddr Call Site
00 ffff8080`d5bc65a0 fffff802`2d4b7276 MyDriver!MyMinifilter::FilterPreWrite+0x182
01 ffff8080`d5bc66a0 fffff802`2d4b6ce1 FLTMGR!FltpPerformPreCallbacksWorker+0x3a6
02 ffff8080`d5bc67b0 fffff802`2d4b5cf2 FLTMGR!FltpPassThroughInternal+0xd1
03 ffff8080`d5bc6800 fffff802`2d4b5992 FLTMGR!FltpPassThrough+0x172
04 ffff8080`d5bc6860 fffff802`29ada1f5 FLTMGR!FltpDispatch+0x142
05 ffff8080`d5bc68c0 fffff802`2a002180 nt!IofCallDriver+0x65
06 ffff8080`d5bc6900 fffff802`29a5afe2 nt!IopSynchronousServiceTail+0x1e0
07 ffff8080`d5bc69b0 fffff802`29b59c35 nt!IopQueueCopyWrite+0x32
08 ffff8080`d5bc6a00 fffff802`29a4c057 nt!ExpWorkerThread+0x155
09 ffff8080`d5bc6bf0 fffff802`29c32ea4 nt!PspSystemThreadStartup+0x57
0a ffff8080`d5bc6c40 00000000`00000000 nt!KiStartSystemThread+0x34
kd> !process -1 0
PROCESS ffff8582f3e9b040
SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 001ae000 ObjectTable: ffff9a8053e8bf00 HandleCount: 3614.
Image: System
The solution was simple, I’m now checking PFLT_CALLBACK_DATA->Thread argument to detect who actually initiated the operation (and whether or not it came from user-mode).
However I’m still curious to understand what has been changed?
Are you guys familiar with this new nt!IopQueueCopyWrite symbol? I could only find it in Win11 builds (I’m using build 25267).
Windows 10 symbols:
0: kd> x nt!IopQueue*
fffff802`5264b840 nt!IopQueueThreadIrp (void)
fffff802`526e75d4 nt!IopQueueWorkItemProlog (void)
fffff802`527158e0 nt!IopQueueIrpToFileObject (void)
Windows 11 symbols:
kd> x nt!IopQueue*
fffff802`29b81f40 nt!IopQueueInvalidateBusRelationsRequest (void)
fffff802`29ada240 nt!IopQueueThreadIrp (void)
fffff802`29ae3790 nt!IopQueueWorkItemProlog (void)
fffff802`29a159b0 nt!IopQueueIrpToFileObject (void)
fffff802`2a1b6c10 nt!IopQueueDeviceResetEvent (IopQueueDeviceResetEvent)
fffff802`29a5afb0 nt!IopQueueCopyWrite (IopQueueCopyWrite)
Why this I/O operation is performed by a System thread and not by the process that initiated it?
Thanks a lot!