Thursday, January 5, 2012

Debugging Minifilters: using !fltkd.filter - Part II

Happy New Year everyone! As I promised in my previous post I'll go over some of the flags !fltkd.filter has and show a couple more tricks about debugging filters. So let's start by listing the flags that are available for !fltkd.filter:
0: kd> !fltkd.filter
   filter [addr] [flags] [detail]            Dump FLT_FILTER
      where [flags] specify what information to dump:
         0x00000001 Basic filter information
         0x00000002 Filter's context registration information
         0x00000004 Filter's context usage information
         0x00000008 Filter's object usage/reference information
         0x00000010 Filter's Verifier information
         0x00000020 Filter's Port information
Let's go over each flag and discuss its output. When it comes to output please note that I have a different setup than last time (I've enabled driver verifier) and so the addresses will be different from the ones in my previous post.
  • 0x00000001 Basic filter information - this is actually the default flag so the output is the usual output that is displayed when !fltkd.filter is called for a filter.
  • 0x00000002 Filter's context registration information - this doesn't seem to show anything in addition to what the basic information shows. However, as I mentioned in my previous post, I get an error about how the PVOID type is not defined and as it happens I get that error right when displaying the field "SupportedContexts" and so possibly the extension would do something for contexts but it can't because of the error.
  • 0x00000004 Filter's context usage information - I'm not sure what this is supposed to show but it's only showing a list of the instances for the filter:
    0: kd> !fltkd.filter a0c92ac0 4
    
    FLT_FILTER: a0c92ac0 "luafv" "135000"
       InstanceList             : (a0c92af0)
          FLT_INSTANCE: a0cd0a50 "luafv" "135000"
    
  • 0x00000008 Filter's object usage/reference information - this requires verifier to be enabled and when verification is enabled for the filter it shows this (we'll get into more detail later):
    0: kd> !fltkd.filter a0c92ac0 0x8
    
    FLT_FILTER: a0c92ac0 "luafv" "135000"
       InstanceList             : (a0c92af0)
          FLT_INSTANCE: a0cd0a50 "luafv" "135000"
       Object usage/reference information: 
          References to FLT_CONTEXT                : 0 
          Allocations of FLT_CALLBACK_DATA         : 1 
          Allocations of FLT_DEFERRED_IO_WORKITEM  : 0 
          Allocations of FLT_GENERIC_WORKITEM      : 0 
          References to FLT_FILE_NAME_INFORMATION  : 0 
          Open files                               : 1 
          References to FLT_OBJECT                 : 0 
    
  • 0x00000010 Filter's Verifier information - this shows a long list of what seem to be operations but I think it's broken because they're all NULL.
  • 0x00000020 Filter's Port information - this appears to work but unfortunately I don't have a minifilter that uses communication ports handy so all I can see is this:
    0: kd> !fltkd.filter a0c92ac0 0x20
    
    FLT_FILTER: a0c92ac0 "luafv" "135000"
       InstanceList             : (a0c92af0)
          FLT_INSTANCE: a0cd0a50 "luafv" "135000"
       Client Port List         : Mutex (a0c92bec) List [a0c92c0c-a0c92c0c] mCount=0 
    
So as we can see the flags don't really add much information to this extension. In particular two things seem to be missing, more details about the VerifierExtension and the contexts. So let's take a look at what we can find out without the extension. We'll start with VerifierExtension and we'll look at the symbols that FltMgr publishes:
0: kd> dt fltmgr!*VERIFIER*
          fltmgr!_FLT_VERIFIER_EXTENSION
          fltmgr!_FLT_VERIFIER_EXTENSION_FLAGS
          fltmgr!FLT_VERIFIER_OPERATIONS
          fltmgr!_FLT_VERIFIER_OBJECT
Clearly we need to see what's in fltmgr!_FLT_VERIFIER_EXTENSION and the address we need to look at is shown in !fltkd.filter under "VerifierExtension":
0: kd> !fltkd.filter a0c92ac0

FLT_FILTER: a0c92ac0 "luafv" "135000"
   FLT_OBJECT: a0c92ac0  [02000000] Filter
….
   Client Port List         : (a0c92bec)  mCount=0 
   VerifierExtension        : a0c3add0 
…
0: kd> dt fltmgr!_FLT_VERIFIER_EXTENSION a0c3add0
   +0x000 Flags            : 0 (No matching name)
   +0x004 FilterUnload     : (null) 
   +0x008 InstanceSetup    : 0xa29b562b     long  luafv!LuafvInstanceSetup+0
   +0x00c InstanceQueryTeardown : (null) 
   +0x010 InstanceTeardownStart : (null) 
   +0x014 InstanceTeardownComplete : (null) 
   +0x018 Operations       : [50] FLT_VERIFIER_OPERATIONS
   +0x1a8 Name             : 0xa0c30ff8  "luafv"
   +0x1b0 FltVerifierObjectsLookasideList : _NPAGED_LOOKASIDE_LIST
   +0x200 List             : _TREE_ROOT
   +0x204 Lock             : 0
   +0x208 Count            : [7] 0
   +0x224 FltVerifierObjectsAllocFailures : 0n0
   +0x228 FltVerifierObjectsUnlinkFailures : 0n0
Now, we expect that there are a lot of callbacks pointers (in fact all the callbacks) because when verifier is enabled FltMgr replaces all the callbacks that minifilter can register with stubs so that it can control exactly how the filter's callback behaves. As such it needs a place to store the original function pointers for the filter and here they are, in the VerifierExtension. Incidentally, if you follow the steps outlined in my previous post on finding the callbacks for a minifilter you'll see that for a verified filter all the preOp callbacks are fltmgr!FltvPreOperation and all the postOp callbacks are fltmgr!FltvPostOperation… So know you know where the real callbacks are even for verified filters.
Once we're done with the callbacks there are few interesting things left:
  • Name - this is the name of the filter again but it's not a unicode string, it's an proper ASCII string complete with a NULL.
  • FltVerifierObjectsLookasideList - clearly a lookaside list of some kind, for some objects that are only allocated when verification is enabled.
  • List - this is probably the most interesting one.. When verification is enabled FltMgr tracks certain things (references to contexts, allocations of certain structures and so on) and they're all stored in this list (which is actually a tree, as we're about to see).
  • Lock - obviously some lock protecting the list.
  • Count - not as obvious but this seems to be where the counts for the "Filter's object usage/reference information" flag are coming from..
The rest of the fields don't seem to be interesting and I think they are meant for FltMgr internal tracking. Anyway, let's look at the List and Count in more detail:
0: kd> dt fltmgr!_FLT_VERIFIER_EXTENSION a0c3add0 List.
   +0x200 List  : 
      +0x000 Tree  : 0xcbc78fd8 _RTL_SPLAY_LINKS
0: kd> !tree 0xcbc78fd8 

TREE_ROOT: cbc78fd8 
TREE_NODE: a0ccefd8 (k1=974957b8, k2=00000000) [00010000] InTree
TREE_NODE: cbc78fd8 (k1=cbc62e40, k2=00000000) [00010000] InTree
0: kd> !pool a0ccefd8 2
Pool page a0ccefd8 region is Special pool
*a0cce000 size:   28 data: a0ccefd8 (NonPaged) *FMvj
  Pooltag FMvj : FLT_VERIFIER_OBJECT structure, Binary : fltmgr.sys
0: kd> !pool cbc78fd8 2
Pool page cbc78fd8 region is Special pool
*cbc78000 size:   28 data: cbc78fd8 (NonPaged) *FMvj
  Pooltag FMvj : FLT_VERIFIER_OBJECT structure, Binary : fltmgr.sys
So the tree is a tree of FLT_VERIFIER_OBJECT (which probably come from the FltVerifierObjectsLookasideList) and there are two things in the tree:
0: kd> !pool a0ccefd8 2
Pool page a0ccefd8 region is Special pool
*a0cce000 size:   28 data: a0ccefd8 (NonPaged) *FMvj
  Pooltag FMvj : FLT_VERIFIER_OBJECT structure, Binary : fltmgr.sys
0: kd> !pool cbc78fd8 2
Pool page cbc78fd8 region is Special pool
*cbc78000 size:   28 data: cbc78fd8 (NonPaged) *FMvj
  Pooltag FMvj : FLT_VERIFIER_OBJECT structure, Binary : fltmgr.sys
0: kd> dt a0ccefd8 fltmgr!_FLT_VERIFIER_OBJECT
   +0x000 TreeLink         : _TREE_NODE
   +0x01c Type             : 5
   +0x020 Object           : 0x974957b8 Void
   +0x024 RefCount         : 0n1
0: kd> !pool 0x974957b8 2
Pool page 974957b8 region is Nonpaged pool
*97495780 size:   b8 previous size:   30  (Allocated) *File (Protected)
  Pooltag File : File objects
0: kd> dt cbc78fd8 fltmgr!_FLT_VERIFIER_OBJECT
   +0x000 TreeLink         : _TREE_NODE
   +0x01c Type             : 1
   +0x020 Object           : 0xcbc62e40 Void
   +0x024 RefCount         : 0n1
0: kd> !pool 0xcbc62e40 2
Pool page cbc62e40 region is Special pool
*cbc62000 size:  220 data: cbc62de0 (NonPaged) *FMic
  Pooltag FMic : IRP_CTRL structure, Binary : fltmgr.sys
So as we can see the tree holds all structures tracked by FltMgr. It wasn't immediately obvious but when looking at the numbers returned with the "Filter's object usage/reference information" flag set it seems that the order in which those counts are displayed corresponds to the number that is the "Type" member of the fltmgr!_FLT_VERIFIER_OBJECT structure and that the count of each type are stored in the "Count" array in the of fltmgr!_FLT_VERIFIER_EXTENSION. So type 1 is IRP_CTRL and type 5 is FILE_OBJECT. Since I'm running on Win7 I have FileInfo running and it has more interesting stuff (like a lot of contexts and file names ):
0: kd> !fltkd.filter 94bb2da0 8

FLT_FILTER: 94bb2da0 "FileInfo" "45000"
   InstanceList             : (94bb2dd0)
      FLT_INSTANCE: 94a34dc8 "FileInfo" "45000"
      FLT_INSTANCE: 98952dc8 "FileInfo" "45000"
      FLT_INSTANCE: 99f00dc8 "FileInfo" "45000"
      FLT_INSTANCE: 9afdedc8 "FileInfo" "45000"
      FLT_INSTANCE: 9aeb0dc8 "FileInfo" "45000"
   Object usage/reference information: 
      References to FLT_CONTEXT                : 4229 
      Allocations of FLT_CALLBACK_DATA         : 0 
      Allocations of FLT_DEFERRED_IO_WORKITEM  : 0 
      Allocations of FLT_GENERIC_WORKITEM      : 0 
      References to FLT_FILE_NAME_INFORMATION  : 4224 
      Open files                               : 0 
      References to FLT_OBJECT                 : 0 
I was going to take a look at the context information that we can dig from the FLT_FILTER structure but I see this post has gotten quite long so I'll leave that for next time.

No comments:

Post a Comment