In this installment, we will compile and deploy our first driver. You should have all the tools installed already.
Windows device drivers are reactive programs—all they really do is respond to events, somewhat similar to GUI programs. The kinds of events drivers recognize include:
- Loading the driver into memory and unloading it from memory
- Adding a new hardware device for which the driver is responsible
- Transitioning to a power-savings mode
- Reading and writing from a device
- Handling an interrupt arriving from a device
A driver handles these events by registering functions that Windows invokes. In this post, we will use only two of these functions, invoked when a driver is loaded and unloaded.
Type the following into your favorite code editor and save it as HelloWorldDriver.c:
DriverObject->DriverUnload = DriverUnload;
This is your first driver. Very simple indeed—all this driver does is print a couple of debugging messages when you load it and unload it. You will need a couple of build files that tell the build engine what to do with your sources. Here are the files:
File name: SOURCES
TARGETNAME = HelloWorldDriver
TARGETPATH = obj
TARGETTYPE = DRIVER
INCLUDES = %BUILD%\inc
LIBS = %BUILD%\lib
SOURCES = HelloWorldDriver.c
File name: makefile.def
To compile the driver, open the build environment for your target OS from the Windows Driver Kits start menu folder. The “checked” build is akin to Debug mode, and the “free” build is equivalent to Release mode.
All that’s left now is to compile the driver. In the WDK build environment command prompt, navigate to the directory containing your driver’s source code, the SOURCES and makefile.def files, and then run the build command. If there have been no errors, you should see a .pdb file and a .sys file created in a subdirectory.
And now—deployment time. Copy your files over to the target system (preferably a virtual machine) and run the OSR Driver Loader. Point it to your driver’s location, click “Register Service” and then “Start Service”. Your driver should be running!
If you want to see the debugger output, you need to use a utility like Sysinternals DebugView. In DebugView, hit Ctrl+K to enable kernel debug spew, and then start/stop your driver a few times. You should see load and unload messages pile up in the DebugView window.
How far is this driver of ours from being useful? From talking to actual hardware? Quite far, and I’m not sure we’ll make it that far 🙂 However, in the near future we sure are going to run some interesting code in kernel mode and in the somewhat farther future see how rootkits use drivers to hide processes and files.