A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #19727  by Blacknight
 Sat Jun 22, 2013 6:08 pm
I'm having a problem getting the driver to unload. I am setting the DriverUnload function, and my DbgPrint confirms that the unload function is being called.

Using "DriverView" I can see that the driver is still loaded, and attempting to load the driver again gives an error (StartService-ERROR_FILE_NOT_FOUND) until restart.

Driver:
Code: Select all
#include "main.h"
#include <ntddk.h> 

#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, handleDriverUnload)
#pragma alloc_text(PAGE, handleDriverUnused)
#pragma alloc_text(PAGE, handleDriverWrite)

void handleDriverUnload(PDRIVER_OBJECT pDriverObject)
{
	UNICODE_STRING usDosDeviceName;
    
    DbgPrint("[Test]: handleDriverUnload\n");
    
    RtlInitUnicodeString(&usDosDeviceName, L"\\DosDevices\\Test");
    IoDeleteSymbolicLink(&usDosDeviceName);
	IoDeleteDevice(pDriverObject->DeviceObject);
}

NTSTATUS handleDriverUnused(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
	UNREFERENCED_PARAMETER(pDeviceObject);
	UNREFERENCED_PARAMETER(pIrp);

	return STATUS_SUCCESS;
}

NTSTATUS handleDriverWrite(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
    PIO_STACK_LOCATION pIoStackIrp = NULL;
    PCHAR pWriteDataBuffer;

	UNREFERENCED_PARAMETER(pDeviceObject);

    DbgPrint("[Test]: handleDriverWrite\n");
    
    pIoStackIrp = IoGetCurrentIrpStackLocation(pIrp);
    
    if(pIoStackIrp)
    {
        pWriteDataBuffer = (PCHAR) pIrp->AssociatedIrp.SystemBuffer;
    
        if(pWriteDataBuffer)
        {
			// 
        }
    }

    return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
	NTSTATUS status = STATUS_SUCCESS;
    PDEVICE_OBJECT pDeviceObject = NULL;
    UNICODE_STRING usDriverName, usDosDeviceName;
	int funcIndex;

	UNREFERENCED_PARAMETER(pRegistryPath);

    DbgPrint("[Test]: DriverEntry\n");

    RtlInitUnicodeString(&usDriverName, L"\\Device\\Test");
    RtlInitUnicodeString(&usDosDeviceName, L"\\DosDevices\\Test"); 

    status = IoCreateDevice(pDriverObject, 
							0,
                            &usDriverName, 
                            FILE_DEVICE_UNKNOWN,
                            FILE_DEVICE_SECURE_OPEN, 
                            FALSE, 
							&pDeviceObject);

	if(NT_SUCCESS(status))
	{
		pDeviceObject->Flags = DO_BUFFERED_IO;
		pDeviceObject->Flags &= (~DO_DEVICE_INITIALIZING);

		for (funcIndex = 0; funcIndex <= IRP_MJ_MAXIMUM_FUNCTION; funcIndex++)
			pDriverObject->MajorFunction[funcIndex] = handleDriverUnused;

		pDriverObject->MajorFunction[IRP_MJ_WRITE] = handleDriverWrite;
		pDriverObject->DriverUnload = handleDriverUnload;

		IoCreateSymbolicLink(&usDosDeviceName, &usDriverName);
	}

    return status;
}
Loader:
Code: Select all
#include <Windows.h>
#include <iostream>

int main()
{
    SC_HANDLE hSCManager;
    SC_HANDLE hService;
    SERVICE_STATUS ss;

    hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
    
    if(hSCManager)
    {
		std::cout << "Create service\n";

        hService = CreateService(hSCManager, "Test", 
                                 "Test Driver", 
                                  SERVICE_START | DELETE | SERVICE_STOP, 
                                  SERVICE_KERNEL_DRIVER,
                                  SERVICE_DEMAND_START, 
                                  SERVICE_ERROR_IGNORE, 
                                  "D:\\dev\\Test.sys", 
                                  NULL, NULL, NULL, NULL, NULL);

        if(!hService)
		{
			std::cout << "OpenService\n";
            hService = OpenService(hSCManager, "Test", SERVICE_START | DELETE | SERVICE_STOP);
		}

        if(hService)
        {
            std::cout << "Start service\n";

            if(!StartService(hService, 0, NULL))
			{
				std::cout << "StartService failed - " << GetLastError() << '\n';
			}

			std::cin.sync();
			std::cin.get();

            if(!ControlService(hService, SERVICE_CONTROL_STOP, &ss))
			{
				std::cout << "ControlService failed - " << GetLastError() << '\n';

				std::cout << ss.dwCurrentState << '\n';
			}

			if(!DeleteService(hService))
			{
				std::cout << "DeleteService failed - " << GetLastError() << '\n';
			}

		    if(!CloseServiceHandle(hService))
			{
				std::cout << "CloseServiceHandle failed - " << GetLastError() << '\n';
			}
        }

        CloseServiceHandle(hSCManager);
    }
    
	std::cin.sync();
	std::cin.get();
    return 0;
}
 #19734  by EP_X0FF
 Sun Jun 23, 2013 3:05 am
Maybe you will comment your code, so everybody can understand why you doing that and this? Sense of this code, why there is no completion (it was planned, code skipped or what?), why you use this cycle for IRP MJ handlers (not a first time I see such BS in code), why we need buffered IO etc?
 #19740  by Blacknight
 Sun Jun 23, 2013 11:24 am
EP_X0FF wrote:Maybe you will comment your code, so everybody can understand why you doing that and this? Sense of this code, why there is no completion (it was planned, code skipped or what?), why you use this cycle for IRP MJ handlers (not a first time I see such BS in code), why we need buffered IO etc?
I'm just trying to load/unload a basic driver. I thought it was pretty minimal.

As for setting all the MJ handles:

Note that the above FOR loop assigns a default dispatch routine for all IRP major function codes. This assignment is good practice, because otherwise the I/O Manager completes any unrecognized IRP with STATUS_INVALID_DEVICE_REQUEST by default.

There is no particular reason that I chose buffered I/O. I was just using the IRP_MJ_WRITE to make sure it was working.
 #19744  by EP_X0FF
 Sun Jun 23, 2013 12:24 pm
Blacknight wrote:This assignment is good practice, because otherwise the I/O Manager completes any unrecognized IRP with STATUS_INVALID_DEVICE_REQUEST by default.[/url]
Yes. In fully functional driver. But in your code any IRP never completes anyway. And you have plans for other IRP handlers except IRP_MJ_CLOSE, IRP_MJ_CREATE, IRP_MJ_DEVICE_CONTROL?
 #19747  by Blacknight
 Sun Jun 23, 2013 1:16 pm
Thanks for the help. I have found the problem.

The problem was with this line:
Code: Select all
pDeviceObject->Flags = DO_BUFFERED_IO;
I was setting the Flags rather than ORing it. (1 character typo.. lol)

And this for some reason caused my driver to not unload.
Code: Select all
pDeviceObject->Flags |= DO_BUFFERED_IO;