File system filters can be inserted into the device stack for all drives, or a specific drive, using the “\\DosDevices\\X:\\” device name, where X is the drive letter for the desired device. These file filters use a slightly different insertion technique than network filters. Whereas a network filter can use IoAttachDevice to attach to “\\Device\\Tcp”, “\\Device\\Udp” or “\\Device\\RawIP”, file filters must use IoAttachDeviceToDeviceStack to guarantee proper insertion.
Note that older versions of the DDK have a serious flaw in the IoAttachDeviceToDeviceStack function that can lead to a system crash. As such, you should use the newer IoAttachDeviceToDevice StackSafe function whenever possible. For the purposes of this book, using the older function reduces the likelihood of an “unknown external function” link error, so the code uses the older function (although the newer function is included as well). Simply comment out the older function and add the newer function when compiling with a newer DDK. Figure 7-1 shows file system filters.
Under normal circumstances, file system filters would be attached to all mounted drives. This requires the filter to keep track of which new device was attached to which driver stack. To help keep track, devices have the capability to set aside room for a device extension. The device extension is a user-specified data structure that is passed along with I/O request packets. Creating a device extension data structure with a “PDEVICE_OBJECT AttachedToDeviceObject” member can resolve the difficulty of determining which driver is attached to which device, but because the rootkit will only monitor drive C, there is no requirement for a device extension.
Another consideration of file filtering is fast I/O. The file system relies upon fast I/O as well as conventional I/O request packets. Fast I/O is specifically designed for rapid synchronous I/O on cached files and must be configured in file system filters. As a minimum, the rootkit provides pass-through functions for 21 of the fast I/O dispatch routines defined in ntddk.h. All of the fast I/O pass-through functions implemented in Ghost funnel the active file object through the function filterFastIo, which can be used to monitor fast I/O file activity.