Tutorial Load device drivers with a Windows Service [C++]

W

Wave

Guest
#1
Hello everyone.

Almost 20 minutes ago from the time of writing this, I decided to post a thread which was code-related (for mixing C++ with the .NET Framework through the usage of Platform Invokation to use the Native API to terminate processes), and I decided to write up some code really quickly to make another thread now (therefore there has been no preparation).

The code within this thread is for loading a device driver from within C++ using Win32 API functions:
- OpenSCManager
- CreateService
- OpenService
- StartService
- DeleteService

Here is the C++ code:
Code:
#include <Windows.h>
#include <iostream>
using namespace std;

string driverpath32 = "c:\\username\\documents\\test32.sys", driverpath64 = "c:\\username\\documents\\test64.sys";

BOOL load_driver(string TargetDriver, string TargetServiceName, string TargetServiceDesc)
{
    SC_HANDLE ServiceManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
    if (!ServiceManager) return FALSE;
    SC_HANDLE ServiceHandle = CreateService(ServiceManager, TargetServiceName.c_str(), TargetServiceDesc.c_str(), SERVICE_START | DELETE | SERVICE_STOP, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, TargetDriver.c_str(), NULL, NULL, NULL, NULL, NULL);
    if (!ServiceHandle)
    {
        ServiceHandle = OpenService(ServiceManager, TargetServiceName.c_str(), SERVICE_START | DELETE | SERVICE_STOP);
        if (!ServiceHandle) return FALSE;
    }
    if (!StartServiceA(ServiceHandle, NULL, NULL)) return FALSE;
    CloseServiceHandle(ServiceHandle);
    CloseServiceHandle(ServiceManager);
    return TRUE;
}

BOOL delete_service(string TargetServiceName)
{
    SERVICE_STATUS ServiceStatus;
    SC_HANDLE ServiceManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
    if (!ServiceManager) return FALSE;
    SC_HANDLE ServiceHandle = OpenService(ServiceManager, TargetServiceName.c_str(), SERVICE_STOP | DELETE);
    if (!ServiceHandle) return FALSE;
    if (!ControlService(ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus)) return FALSE;
    if (!DeleteService(ServiceHandle)) return FALSE;
    CloseServiceHandle(ServiceHandle);
    CloseServiceHandle(ServiceManager);
    return TRUE;
}

int main()
{
    load_driver(driverpath64 /*or driverpath32*/, "drivername", "driver description");
    getchar();
    delete_service("drivername");
    getchar();
    return 0;
}
Make sure to change the values within driverpath32 and driverpath64 which I setup at the start of the code (therefore they are public and accessible from all the functions within the program). To make this more useful, you can handle arguments for when the program starts from within the main function (called after the CRT initialization) to direct the path for the driver which should be loaded, and so on... Customize to whatever your needs may be.

The alternate to working with the Windows Service Manager through the Win32 API would be to use the Native API function called NtLoadDriver (exported by ntdll.dll) - however to do this you'll need to perform some registry modifications; you pass in the service name as the parameter to the NTAPI function and it locates your registry modifications using this information so it knows where to find the device driver to be loaded, etc. I will mark this for a future thread.

Hopefully this is found useful by someone.

Stay safe,
Wave. ;)