1: kd> !fltkd.filter 94130008 FLT_FILTER: 94130008 "luafv" "135000" FLT_OBJECT: 94130008 [02000000] Filter RundownRef : 0x0000000a (5) PointerCount : 0x00000001 PrimaryLink : [922c75a4-92cdaa24] Frame : 92cda9c8 "Frame 0" Flags : [00000006] FilteringInitiated NameProvider DriverObject : 9306bc50 FilterLink : [922c75a4-92cdaa24] PreVolumeMount : 81fbe0cc luafv!LuafvPreRedirect PostVolumeMount : 00000000 (null) FilterUnload : 00000000 (null) InstanceSetup : 81fca62b luafv!LuafvInstanceSetup InstanceQueryTeardown : 00000000 (null) InstanceTeardownStart : 00000000 (null) InstanceTeardownComplete : 00000000 (null) ActiveOpens : (941300dc) mCount=1 Communication Port List : (94130108) mCount=0 Client Port List : (94130134) mCount=0 VerifierExtension : 00000000
So the task is to find that one file that ActiveOpens is tracking for LUAFV. Before we go any further, let's see what the chain of structures looks like, starting from the FILE_OBJECT. Some of the structures are documented while others are not. I've marked the undocumented structures with a '?' at the end of the name. We don't know (or care for this post) what the other members of the structures are.
Now, we need to walk the arrows backwards so the steps we need to follow are:
- From fltmgr!_FLT_FILTER->ActiveOpens find fltmgr!FO_CONTEXT?
- From fltmgr!FO_CONTEXT? find the nt!FILE_OBJECT_CONTEXTS_HEADER? Structure
- From nt!FILE_OBJECT_CONTEXTS_HEADER? Structure find the nt!_IOP_FILE_OBJECT_EXTENSION pointing to it
- From the nt!_IOP_FILE_OBJECT_EXTENSION find the nt!_FILE_OBJECT structure that points to it
- ???
- Profit!!!!
So now we know that the structure that we've been calling fltmgr!FO_CONTEXT? is in fact called FLTMGR_FILE_OBJECT_CONTEXT. Step 1 is done and we're moving on to step 2. We also know the size isn't larger than 0x70. However, we don't know where the LIST_ENTRY is in there. The only other thing we know is that in that structure there must be a member that is of type FSRTL_PER_FILEOBJECT_CONTEXT (and we know this because that's how FILE_OBJECT contexts are implemented; see the documentation for FsRtlInsertPerFileObjectContext). Since the beginning of the _LIST_ENTRY is at address 0x93712498 and the pool block starts at 0x93712430, we can guess our LIST_ENTRY is towards the end of the structure, so we'll go back a bit and display the words. Then we'll look for something that looks like an FSRTL_PER_FILEOBJECT_CONTEXT. FSRTL_PER_FILEOBJECT_CONTEXT doesn't really contain much easily identifiable information but it does contain a LIST_ENTRY, which means we should find two words that look like kernel mode addresses next to each other. I've highlighted possible candidates and then we simply try "dl" on them (if anyone knows a better way I'd love to hear about it, please leave a comment). Of course, if you look at the number carefully you can see that it's very likely that there is a LIST_ENTRY at 93712480 if the list has only one element. But in most cases the list has more than one element so it's hard to tell at a quick glance. So we simply issue a "dl" on each candidate and hope that if they're not doubly linked lists they'll simply run into some invalid address sooner or later.1: kd> dt 941300dc _FLT_MUTEX_LIST_HEAD fltmgr!_FLT_MUTEX_LIST_HEAD +0x000 mLock : _FAST_MUTEX +0x020 mList : _LIST_ENTRY [ 0x93712498 - 0x93712498 ] +0x028 mCount : 2 +0x028 mInvalid : 0y0 1: kd> dl 0x93712498 93712498 941300fc 941300fc 0421000e 706e5043 941300fc 93712498 93712498 00000002 00000001 1: kd> !pool 0x93712498 2 Pool page 93712498 region is Nonpaged pool *93712430 size: 70 previous size: 8 (Allocated) *FMfc Pooltag FMfc : FLTMGR_FILE_OBJECT_CONTEXT structure, Binary : fltmgr.sys
It looks like we may have found our structure. Now we're starting our step 3 and we have a pointer into a structure of type nt!FILE_OBJECT_CONTEXTS_HEADER?, but since we don't know the type we don't know where the structure starts. Normally what I do is assume it starts right after the pool tag and search for that address, and if that fails search for the address at the next word boundary and so on. Let's see:1: kd> dp 0x93712498-0x60 93712438 48706345 00000000 00000000 00000000 93712448 00ac5851 45e4702b 2a5794ac 7e7ac1fe 93712458 00000000 00000047 00000068 96040c00 93712468 00000000 0034f110 001d0000 92cda9c8 93712478 94134ce8 93011008 9306b0c8 9306b0c8 93712488 938f1230 00000000 94130008 941307d8 93712498 941300fc 941300fc 0421000e 706e5043 937124a8 937395a8 937126b8 937699d8 93739ad8 1: kd> dl 92cda9c8 92cda9c8 0340f103 960409f8 960409f8 00000000 0340f103 00000000 00000000 00000000 00000000 1: kd> dl 94134ce8 94134ce8 00800005 92f05788 92f06870 92fa4998 … 1: kd> dl 9306b0c8 9306b0c8 93712480 93712480 00010006 e56c6946 93712480 9306b0c8 9306b0c8 938f1230 00000000 1: kd> !pool 9306b0c8 2 Pool page 9306b0c8 region is Nonpaged pool *9306b0a0 size: 30 previous size: 10 (Allocated) *FOCX Pooltag FOCX : File System Run Time File Object Context structure, Binary : nt!fsrtl
So actually this looks pretty good. In other cases I've found multiple random values that looked like references so I've just had to look at each one. But in this case it looks pretty clean. We expect that the pointer is in a structure that's allocated by the IO mgr, and that the structure size something about the size of nt!_IOP_FILE_OBJECT_EXTENSION. So this means we've completed step 3 and we have the nt!_IOP_FILE_OBJECT_EXTENSION structure. In our picture I've shown that in the _IOP_FILE_OBJECT_EXTENSION it is FoExtPerTypeExtension[3] that points to this structure that we just found. I've figured this out by experimenting. I simply got a FILE_OBJECT and added a context by calling FsRtlInsertPerFileObjectContext and watched which value changed. So now we know where the structure starts and we need to search a pointer to it. The pointer we would find here would be a FILE_OBJECT->FileObjectExtension so we expect the pool tag to be "File". Also, we expect the FILE_OBJECT to start 0x7c bytes before the pointer. Please note that the first two results returned by the search were invalid (!pool told me so):1: kd> db 9306b0a0 L0x20 9306b0a0 02 00 06 04 46 4f 43 58-01 00 00 00 00 00 00 00 ....FOCX........ 9306b0b0 00 00 00 00 01 00 04 20-00 00 00 00 bc b0 06 93 ....... ........ 1: kd> s -d 80000000 L?0x20000000 9306b0a8 9306ba78 9306b0a8 00000000 00000000 00000000 ................ 1: kd> !pool 9306ba78 2 Pool page 9306ba78 region is Nonpaged pool *9306ba60 size: 30 previous size: 10 (Allocated) *Io Pooltag Io : general IO allocations, Binary : nt!io
So this is it, we know now that LUAFV opens the volume using FltCreateFile (if it didn't it would be on the ActiveOpens list). For the record, this is win7:1: kd> ? 0x9306ba78-0x10 Evaluate expression: -1828275608 = 9306ba68 1: kd> s -d 80000000 L?0x20000000 9306ba68 82b80008 9306ba68 9306ba68 00000000 abcddcba h...h........... 82b8000c 9306ba68 00000000 abcddcba 00000001 h............... 94134d64 9306ba68 04530015 6661754c 00000000 h.....S.Luaf.... 1: kd> !pool 94134d64 2 Pool page 94134d64 region is Nonpaged pool *94134cc0 size: a8 previous size: 2d8 (Allocated) *File (Protected) Pooltag File : File objects 1: kd> !fileobj 0x94134d64-0x7c Device Object: 0x92f05788 \Driver\volmgr Vpb: 0x92f06870 Event signalled Access: Read Write SharedRead SharedWrite SharedDelete Flags: 0x440008 No Intermediate Buffering Handle Created Volume Open FsContext: 0x92fa4998 FsContext2: 0x97e0cbc0 CurrentByteOffset: 0 Cache Data: Section Object Pointers: 92f0cd14 Shared Cache Map: 00000000 File object extension is at 9306ba68:
1: kd> vertarget Windows 7 Kernel Version 7600 MP (2 procs) Free x86 compatible Product: WinNt, suite: TerminalServer SingleUserTS Built by: 7600.16617.x86fre.win7_gdr.100618-1621 Machine Name: Kernel base = 0x82809000 PsLoadedModuleList = 0x82951810 Debug session time: Thu Feb 17 07:44:10.641 2011 (UTC - 8:00) System Uptime: 0 days 0:02:42.733