Tuesday, February 7, 2012

FastIO

In my previous posts about Stuxnet, I talked about the FileSystem Filter functionality of the Rootkit. I covered the idea of an "IO Request Packet" or IRP for short. IRPs are the general way for drivers to pass data to the lower layers in their device stacks. Filesystems often write to relatively slow backing stores (such as hard disks). To get an idea of the difference in timescale we are talking about, CPUs often operate in the microsecond domain, while hard disks operate in the millisecond domain. Due to this time scale difference, the Windows Engineers decided to provide an optimized I/O mechanism to write to such slow storage mediums. This caching mechanism is implemented in the Windows Cache Manager, and the FastIO infrastructure is the way to take advantage of it from a driver.

FastIO can be thought of as logically parallel to the IRP infrastructure in Windows, but with higher performance. Instead of waiting for each IRP to get to the disk, FastIO interacts with the Windows Cache Manager. The windows cache manager stores an in-memory cache of frequently accessed data on the disk (See chapters 9 and 10 of Windows Internals 5th edition by Mark Russinovich and David Solomon). This increases performance because on a cache lookup, the memory is hit (which has no moving parts and is fast) rather than the disk being hit (which has to seek to the correct sector, thereby incurring the cost of mechanical slowness). In addition to the disk not being hit on a read/write, FastIO also allows us to avoid the overhead incurred in synthesizing new IRPs to pass down the device stack.

The FastIO infrastructure is brought together by the FAST_IO_DISPATCH structure, which can be seen in wdm.h in the Windows Driver Development Kit. In the Rootkits book by Hoglund and Butler, they describe this structure as beginning with a size field, and containing all the function pointers for the FastIO functions supported by the driver. When attempting to call a FastIO function, the system first has to figure out whether or not the device in question supports FastIO. As a fallback, if the device does not support FastIO, an IRP is created and sent down the device stack.

I followed the Experiment in Windows Internals 4th Edition:

kd> !drvobj \filesystem\ntfs 2
Driver object (81fd0cc0) is for:
 \FileSystem\Ntfs
DriverEntry:   f847c680   Ntfs!DriverEntry
DriverStartIo: 00000000
DriverUnload:  00000000              
AddDevice:     00000000

Dispatch routines:
[00] IRP_MJ_CREATE                      f841c200              Ntfs!NtfsFsdCreate
[01] IRP_MJ_CREATE_NAMED_PIPE           804f2529          nt!IopInvalidDeviceRequest
[02] IRP_MJ_CLOSE                       f841cda5               Ntfs!NtfsFsdClose
[03] IRP_MJ_READ                        f8402687                Ntfs!NtfsFsdRead
[04] IRP_MJ_WRITE                       f8403428               Ntfs!NtfsFsdWrite
[05] IRP_MJ_QUERY_INFORMATION           f841e53f         Ntfs!NtfsFsdDispatchWait
[06] IRP_MJ_SET_INFORMATION             f84040b1             Ntfs!NtfsFsdSetInformation
[07] IRP_MJ_QUERY_EA                    f841e53f         Ntfs!NtfsFsdDispatchWait
[08] IRP_MJ_SET_EA                      f841e53f              Ntfs!NtfsFsdDispatchWait
[09] IRP_MJ_FLUSH_BUFFERS               f842da23  Ntfs!NtfsFsdFlushBuffers
[0a] IRP_MJ_QUERY_VOLUME_INFORMATION    f841d4e2          Ntfs!NtfsFsdDispatch
[0b] IRP_MJ_SET_VOLUME_INFORMATION      f841d4e2               Ntfs!NtfsFsdDispatch
[0c] IRP_MJ_DIRECTORY_CONTROL           f8422595           Ntfs!NtfsFsdDirectoryControl
[0d] IRP_MJ_FILE_SYSTEM_CONTROL         f84218d4        Ntfs!NtfsFsdFileSystemControl
[0e] IRP_MJ_DEVICE_CONTROL              f841d4e2               Ntfs!NtfsFsdDispatch
[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL     804f2529   nt!IopInvalidDeviceRequest
[10] IRP_MJ_SHUTDOWN                    f8414476      Ntfs!NtfsFsdShutdown
[11] IRP_MJ_LOCK_CONTROL                f84329e3  Ntfs!NtfsFsdLockControl
[12] IRP_MJ_CLEANUP                     f841c4da           Ntfs!NtfsFsdCleanup
[13] IRP_MJ_CREATE_MAILSLOT             804f2529               nt!IopInvalidDeviceRequest
[14] IRP_MJ_QUERY_SECURITY              f841d4e2                Ntfs!NtfsFsdDispatch
[15] IRP_MJ_SET_SECURITY                f841d4e2     Ntfs!NtfsFsdDispatch
[16] IRP_MJ_POWER                       804f2529             nt!IopInvalidDeviceRequest
[17] IRP_MJ_SYSTEM_CONTROL              804f2529               nt!IopInvalidDeviceRequest
[18] IRP_MJ_DEVICE_CHANGE               804f2529 nt!IopInvalidDeviceRequest
[19] IRP_MJ_QUERY_QUOTA                 f841e53f  Ntfs!NtfsFsdDispatchWait
[1a] IRP_MJ_SET_QUOTA                   f841e53f       Ntfs!NtfsFsdDispatchWait
[1b] IRP_MJ_PNP                         f846b3fc  Ntfs!NtfsFsdPnp

Fast I/O routines:
FastIoCheckIfPossible                   f8432bbb              Ntfs!NtfsFastIoCheckIfPossible
FastIoRead                              f841f4ce          Ntfs!NtfsCopyReadA
FastIoWrite                             f842f898          Ntfs!NtfsCopyWriteA
FastIoQueryBasicInfo                    f8424db0              Ntfs!NtfsFastQueryBasicInfo
FastIoQueryStandardInfo                 f8424c14          Ntfs!NtfsFastQueryStdInfo
FastIoLock                              f8432e66          Ntfs!NtfsFastLock
FastIoUnlockSingle                      f8432f26  Ntfs!NtfsFastUnlockSingle
FastIoUnlockAll                         f84691b9     Ntfs!NtfsFastUnlockAll
FastIoUnlockAllByKey                    f84692fd              Ntfs!NtfsFastUnlockAllByKey
AcquireFileForNtCreateSection           f841d6f4    Ntfs!NtfsAcquireForCreateSection
ReleaseFileForNtCreateSection           f841d721   Ntfs!NtfsReleaseForCreateSection
FastIoQueryNetworkOpenInfo              f842ffc6   Ntfs!NtfsFastQueryNetworkOpenInfo
AcquireForModWrite                      f846e918            Ntfs!NtfsAcquireFileForModWrite
MdlRead                                 f8430233           Ntfs!NtfsMdlReadA
MdlReadComplete                         8051e58f              nt!FsRtlMdlReadCompleteDev
PrepareMdlWrite                         f842f36d  Ntfs!NtfsPrepareMdlWriteA
MdlWriteComplete                        805f28aa               nt!FsRtlMdlWriteCompleteDev
FastIoQueryOpen                         f8424ec5 Ntfs!NtfsNetworkOpenCreate
AcquireForCcFlush                       f841d3db                Ntfs!NtfsAcquireFileForCcFlush
ReleaseForCcFlush                       f841d39c Ntfs!NtfsReleaseFileForCcFlush

As we can see in the section titled " Fast I/O routines", the NTFS drivers uses most of the FastIO functions. To learn more about the specific FastIO functions, check out:

http://www.osronline.com/article.cfm?id=166