While discussing the driverscan plugin, I had mentioned that driverscan gets module information from the DRIVER_OBJECT structure. Are you wondering what the DRIVER_OBJECT structure is? This will become clear soon. In this section, you will understand the interaction between the user-mode and kernel-mode components, the role of the device driver, and its interaction with the I/O manager. Typically, a rootkit consists of a user-mode component (EXE or DLL) and a kernel mode component (device driver). The user-mode component of the rootkit communicates with the kernel-mode components, using a specific mechanism. From a forensics standpoint, it is essential to understand how these communications work and the components involved. This section will help you understand the communication mechanism and lays the foundation for the upcoming topics.
Let's try to understand what happens when a user-mode application performs input/output (I/O) operations, and how it is processed at a high level. While discussing the API call flow in Chapter 8, Code Injection and Hooking (in the Windows API call flow section), I used the example of a user-mode application performing a write operation using the WriteFile() API, which ends up calling the NtWriteFile() system service routine in the kernel executive (ntoskrnl.exe), which then directs the request to the I/O manager, whereupon the I/O manager requests the device driver to perform the I/O operation. Here, I will revisit that topic again with a little more detail and with an emphasis on the kernel-space components (mainly the device driver and the I/O manager). The following diagram illustrates the flow of the write request (other types of I/O requests, such as read, are similar; they just use different APIs):

The following points discuss the role of the device driver and the I/O manager at a high level:
- The device driver typically creates a device or multiple devices and specifies what type of operations (open, read, and write) it can handle for the device. It also specifies the address of routines that handle these operations. These routines are called dispatch routines or IRP handlers.
- After creating the device, the driver advertises that device so that it is accessible to user-mode applications.
- The user mode application can use API calls, such as CreateFile, to open handle the advertised device and perform I/O operations such as read, and write on the device using the ReadFile and WriteFile APIs. APIs, such as CreateFile, ReadWrite, and WriteFile, that are used to perform I/O operations on the file also work on a device. This is because the device is treated as a virtual file.
- When the I/O operation is performed on the advertised device by the user mode application, the request is routed to the I/O manager. The I/O manager determines the driver that handles the device and requests the driver to complete the operation by passing an IRP (I/O request packet). An IRP is a data structure that contains information on what operation to perform and the buffer required for the I/O operation.
The driver reads the IRP, verifies it, and completes the requested operation before notifying the I/O manager about the status of the operation. The I/O manager then returns the status and the data back to the user application.
At this stage, the preceding points might seem foreign to you, but don't let it discourage you: it will be clear by the time you complete this section. Next, we will look at the role of the device driver, followed by the role of the I/O manager.