|You are here:|
A device driver (a.k.a. driver) is a program that operates or control a device attached to a computer. Without drivers, the hardware you connect to your computer—for example, a video card or a printer—won't work properly.
Applications in Windows communicate with drivers by sending I/O Request Packets (IRPs).
System-Defined Data Structures
Below are links to some of the kernel system-defined data structures:
Find driver objects
Several techniques enable to find a driver object with WinDbg:
Given the hypothesis that WinDbg has alerted that the following kernel driver has been loaded:
ModLoad: f7b0d000 f7b0e780 FileWriter.sys
The below command will find the address of the driver object Filewriter:
kd> !drvobj FileWriter Driver object (827e3698) is for: Loading symbols for f7b0d000 FileWriter.sys -> FileWriter.sys *** ERROR: Module load completed but symbols could not be loaded for FileWriter.sys \Driver\FileWriter Driver Extension List: (id , addr) Device Object list: 826eb030
Identify the device object to find the driver object
You can also idenfity the device object and use it to find the driver object:
kd> !devobj ProcHelper Device object (85e2c7e8) is for: ProcHelper*** ERROR: Module load completed but symbols could not be loaded for Lab10-03.sys \Driver\Process Helper DriverObject 85d8a030 Current Irp 00000000 RefCount 1 Type 00000022 Flags 00000040 Dacl e1001474 DevExt 00000000 DevObjExt 85e2c8a0 ExtensionFlags (0000000000) Characteristics (0x00000100) FILE_DEVICE_SECURE_OPEN Device queue is not busy.
Analyze driver object structure
The driver object structure can be displayed with the following command in WinDbg:
kd> dt nt!_DRIVER_OBJECT 85d8a030 +0x000 Type : 0n4 +0x002 Size : 0n168 +0x004 DeviceObject : 0x85e2c7e8 _DEVICE_OBJECT +0x008 Flags : 0x12 +0x00c DriverStart : 0xf7cf2000 Void +0x010 DriverSize : 0xe00 +0x014 DriverSection : 0x86146f28 Void +0x018 DriverExtension : 0x85d8a0d8 _DRIVER_EXTENSION +0x01c DriverName : _UNICODE_STRING "\Driver\Process Helper" +0x024 HardwareDatabase : 0x80670ae0 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM" +0x028 FastIoDispatch : (null) +0x02c DriverInit : 0xf7cf27cd long +0 +0x030 DriverStartIo : (null) +0x034 DriverUnload : 0xf7cf262a void +0 +0x038 MajorFunction :  0xf7cf2606 long +0
Sections you would like to analyze are:
- DriverInit: code executed when the driver is loaded
- DriverUnload: code executed when the driver is unloaded
- MajorFunction: often where the most interesting driver code resides
Below is an example of the major function dump in WinDbg (notice that we display 1C DWORD because this is the size allowed by Windows XP for the major function):
kd> dd 85d8a030+0x38 L1C 85d8a068 f7cf2606 804f354a f7cf2606 804f354a 85d8a078 804f354a 804f354a 804f354a 804f354a 85d8a088 804f354a 804f354a 804f354a 804f354a 85d8a098 804f354a 804f354a f7cf2666 804f354a 85d8a0a8 804f354a 804f354a 804f354a 804f354a 85d8a0b8 804f354a 804f354a 804f354a 804f354a 85d8a0c8 804f354a 804f354a 804f354a 804f354a
To view what an entry means, just issue:
kd> ln 804f354a (804f354a) nt!IopInvalidDeviceRequest | (804f3580) nt!IopGetDeviceAttachmentBase Exact matches: nt!IopInvalidDeviceRequest (<no parameter info>)
We can see that most of the entries of the major table are pointers to the default dispatch function nt!IopInvalidDeviceRequest which handles invalid requests that this driver doesn't handle.
Loading a driver
To load a driver, you can use OSR Driver Loader.
Debug a kernel driver
To be able to debug a kernel driver, you will need to set up a specific environment. You can refer to this page to see the different options.
In our example, we will use 2 virtual machines (debuggee and debugger) running Windows 7, with VMware installed on a Linux Debian physical host. Both VMs will communicate via Serial Port 2.
Once you're debugging environment is prepared, proceed as follows:
- On the Debugger (1st VM)
- Start WinDbg
- Press and fill in the fields as follows: Baud rate = 115200, Port = com2 (depends on the Serial Port number configured in VMware)
- Enable verbose output ( + + )
- Break: >
- Enter the following command to break when your driver ( in my example) is loaded:
kd> sxe ld challenge.sys kd> g
- On the Debuggee (2nd VM)
- Start OSR Loader
- Set up driver path
- Click on Register service
- Click on Start service
- At this stage, the debuggee should freeze and the debugger should show that the driver has been loaded
ModLoad: 99600000 99895000 challenge.sys nt!DbgLoadImageSymbols+0x47: 82a2a578 cc int 3
- Now, on the debugger
- Dump the PE header for the loaded module with the below command (replace with the name of your driver). We are interested in the entry point address.
kd> !dh challenge File Type: EXECUTABLE IMAGE FILE HEADER VALUES 14C machine (i386) 6 number of sections 55B81359 time date stamp Wed Jul 29 01:42:17 2015 0 file pointer to symbol table 0 number of symbols E0 size of optional header 102 characteristics Executable 32 bit word machine OPTIONAL HEADER VALUES 10B magic # 9.00 linker version 28E600 size of code 2200 size of initialized data 0 size of uninitialized data 29203E address of entry point 1000 base of code [REMOVED]
- Add the address of entry point to the base of the image to get the breakpoint address:
kd> bp challenge+29203E Loading symbols for 99600000 challenge.sys -> challenge.sys *** ERROR: Module load completed but symbols could not be loaded for challenge.sys
- Resume the debugger and hit the breakpoint:
kd> g Breakpoint 0 hit challenge+0x29203e: 9989203e 8bff mov edi,edi
This category has only the following subcategory.