Windows Drivers
From Ggl's wiki
Big kudos to Greg Hoglund and Jamie Butler for their works on rootkit and their book "Rootkit: Subverting the Windows Kernel" for which I learn a lot and inspired this article.
Contents |
Working environment
Basically you need the Windows DDK (actually, Download the Windows Server 2003 SP1 DDK ISO file), and to create a clean source tree (taken from Hoglund's basic_1.zip archive):
basic_1\ basic.c MAKEFILE SOURCES
basic_1 is the driver basic templace below.
SOURCES contains:
TARGETNAME=basicrk_1 TARGETPATH=OBJ TARGETTYPE=DRIVER # Choose between DRIVER, PROGRAM, EXPORT_DRIVER, DRIVER_LIBRARY, DYNLINK #TARGETLIBS= SOURCES=basic.c
MAKEFILE contains:
!INCLUDE $(NTMAKEENV)\makefile.def
Driver basic template
#include "wdm.h"
VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
{
DbgPrint("OnUnload called\n");
}
NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
DbgPrint("I loaded!");
theDriverObject->DriverUnload = OnUnload;
return STATUS_SUCCESS;
}
MSDN tells that the function protoype is:
DriverEntry is the first routine called after a driver is loaded, and is responsible for initializing the driver.
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
- Parameters
- DriverObject
- Caller-supplied pointer to a DRIVER_OBJECT structure. This is the driver's driver object.
- RegistryPath
- Pointer to a counted Unicode string specifying the path to the driver's registry key.
- Return Value
- If the routine succeeds, it must return STATUS_SUCCESS. Otherwise, it must return one of the error status values defined in ntstatus.h.
- Headers
- Declared in wdm.h. Include wdm.h or ntddk.h.
Build the driver
Ok, now start a checked (Free is meant for production release e.g. no debug) build environment (in Start > Programs > Developement Kits ...)
Go into basic_1 directory and type build. Now you have a driver in objchk_wxp_x86\i386 with the name basicrk_1.sys.
Load the driver
Fine, we have built our basic driver but now we need to load it.
There are several ways to load a driver. I describe the common: using Service Control Manager (SCM). SCM provides management capabilities to drivers e.g. automatic loading, on demand, start, stop, etc ...
There are three main steps to load a driver:
- Open the SCM
- Create the service associated with the driver
- Start the driver
Opening the SCM
For this purpose, we use the OpenSCManager() function which establishes a connection to the service control manager on the specified computer and opens the specified service control manager database.
SC_HANDLE WINAPI OpenSCManager( LPCTSTR lpMachineName, LPCTSTR lpDatabaseName, DWORD dwDesiredAccess );
So, we use this functin like that:
SC_HANDLE sh = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
Creating the service
We use the CreateService() function which creates a service object and adds it to the specified service control manager database.
SC_HANDLE WINAPI CreateService( SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPCTSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCTSTR lpBinaryPathName, LPCTSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCTSTR lpDependencies, LPCTSTR lpServiceStartName, LPCTSTR lpPassword );
We use it as the following:
SC_HANDLE rh = CreateService(
sh, DriverName, DriverName, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, aPath, NULL, NULL, NULL, NULL, NULL);
with
- DriverName
- The name of the driver. Typically a copy of a command line argument or a option.
- aPath
- A string that represents the path the driver file.
Starting the driver
Last step is is to start the service, in this case to actually load the driver.
For this purpose we use the StartService() function :
BOOL WINAPI StartService( SC_HANDLE hService, DWORD dwNumServiceArgs, LPCTSTR* lpServiceArgVectors );
In the code we call:
StartService(rh, 0, NULL)

