6.4 I/O Requests To Layered Drivers

So far, you have understood how an I/O request is handled by a simple device controlled by a single driver. The I/O request can go through multiple layers of drivers; I/O processing for the layered drivers happens in much the same way. The following screenshot illustrates an example of how an I/O request might travel through layered drivers before reaching the hardware-based devices:

This concept is better understood with an example, so let's trigger a write operation to c:abc.txt using the following command. When this command is executed, netstat will open the handle to abc.txt and write to it:

C:Windowssystem32>netstat -an -t 60 > C:abc.txt

A point to note here is that the filename (C:abc.txt) also includes the name of the device where the file resides, that is, volume C: is the symbolic link name for the device, DeviceHarddiskVolume1 (you can verify it using the WinObj tool, as mentioned earlier). This means the write operation will be routed to the driver associated with the device DeviceHarddiskVolume1. When netstat.exe opens abc.txt, the I/O manager creates a file object (FILE_OBJECT structure) and stores the pointer to the device object inside the file object before returning the handle to netstat.exe. The following screenshot from the ProcessHacker tool displays the handle to C:abc.txt that has been opened by netstat.exe. The object address 0x85f78ce8 represents the file object:

You can examine the file object (FILE_OBJECT) using the object address as follows. From the output, you can see that the FileName field contains the name of the file, and the DeviceObject field contains the pointer to the device object (DEVICE_OBJECT):

kd> dt nt!_FILE_OBJECT 0x85f78ce8
+0x000 Type : 0n5
+0x002 Size : 0n128
+0x004 DeviceObject : 0x868e7e20 _DEVICE_OBJECT
+0x008 Vpb : 0x8688b658 _VPB
+0x00c FsContext : 0xa74fecf0 Void
[REMOVED]
+0x030 FileName : _UNICODE_STRING "abc.txt"
+0x038 CurrentByteOffset : _LARGE_INTEGER 0xe000

As mentioned earlier, from the device object, one can determine the name of the device and the associated driver. This is how the I/O manager determines which driver to pass the I/O request to. The following output displays the name of the device, HarddiskVolume1, and its associated driver, volmgr.sys. The AttachedDevice field tells you that there is an unnamed device object (868e7b28) associated with the fvevol.sys driver sitting on top of the device object HarddiskVolume1 in the device stack:

kd> !devobj 0x868e7e20
Device object (868e7e20) is for:
HarddiskVolume1 Drivervolmgr DriverObject 862e0bd8
Current Irp 00000000 RefCount 13540 Type 00000007 Flags 00201150
Vpb 8688b658 Dacl 8c7b3874 DevExt 868e7ed8 DevObjExt 868e7fc0 Dope 86928870 DevNode 86928968
ExtensionFlags (0x00000800) DOE_DEFAULT_SD_PRESENT
Characteristics (0000000000)
AttachedDevice (Upper) 868e7b28 Driverfvevol
Device queue is not busy.

To determine the layers of drivers through which the I/O request goes through, you can use the !devstack kernel debugger command and pass the device object address to display the device stack (of layered device objects) associated with a particular device object. The following output shows the device stack associated with DeviceHarddiskVolume1, which is owned by volmgr.sys. The > character in the fourth column tells you that the entry is associated with the device HarddiskVolume1 and the entries above that line are the list of drivers layered above volmgr.sys. What this means is that the I/O request will be first passed to volsnap.sys by the I/O manager. Depending on the type of request, volsnap.sys can handle the IRP request and send the request down to other drivers in the stack, which finally reaches volmgr.sys:

kd> !devstack 0x868e7e20
!DevObj !DrvObj !DevExt ObjectName
85707658 Drivervolsnap 85707710
868e78c0 Driver dyboost 868e7978
868e7b28 Driverfvevol 868e7be0
> 868e7e20 Drivervolmgr 868e7ed8 HarddiskVolume1

To view the device tree, you can use the GUI tool DeviceTree (which we mentioned earlier). The tool displays the driver on the outer edge of the tree, and their devices are indented one level. The attached devices are further intended, as shown in the following screenshot. You can compare the following screenshot with the preceding !devstack output to get an idea of how to interpret the information:

It is important to understand this layered approach, because sometimes, a rookit driver can insert or attach below or above the target device's stack to receive IRP. Using this technique, a rootkit driver can log or modify the IRP before passing it on to the legitimate driver. For example, a keylogger can log strokes by inserting a malicious driver that sits above the keyboard function driver.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.131.238