Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results
The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.
Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/
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!
Upcoming OSR Seminars | ||
---|---|---|
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead! | ||
Kernel Debugging | 16-20 October 2023 | Live, Online |
Developing Minifilters | 13-17 November 2023 | Live, Online |
Internals & Software Drivers | 4-8 Dec 2023 | Live, Online |
Writing WDF Drivers | 10-14 July 2023 | Live, Online |
Comments
I'm surprised you didn't see writes from the system process in Explorer, it
does not use write-through or no-buffering, so cached writes would end up
being flushed via System process even before.
Dejan.
This is the explorer thread stack in win11:
We can see it's the same stack as in win10 until
KERNELBASE!BaseCopyStream
. The change is that it callsntdll!NtCopyFileChunk
(which was added in win11 22H2) instead ofKERNELBASE!WriteFile
. We can see further in the stack the call to nt!ExQueueWorkItem and this explains the behavior we saw.I don't suppose that they have done anything sensible like poke explorer's PETHREAD into the cbd?
See https://learn.microsoft.com/en-us/windows-hardware/drivers/ifs/km-file-copy for a description of the new mechanism.