Fail to stop kernel driver with STOP_PENDING

1k Views Asked by At

I have a kernel driver that enum and close all handles (of type "File") of files present in a specific folder, and this is the code of reference about how start to this goal. The kernel code is works very fine, but i have a small problem more specifically on moment to stop the driver. Then when execute the usermode code below STOP_PENDING is all that happens, and i'm not able close the usermode program. Already when i not execute the kernel code (to close handles), the driver can be stopped and deleted with success.

PS: The usermode code not open any handle to target folder.

Some idea about reason to this strange behavior?

To better understanding here in this forum, i will post only relevant codes usermode/kernel mode.

Usermode:

function UninstallService(sMachine, sService: string): Boolean;
var
  schm, schs: SC_Handle;
  ss: TServiceStatus;
  dwChkP: dword;
begin
  Result := False;
  schm := OpenSCManagerW(PWideChar(sMachine), nil, SC_MANAGER_CONNECT);
  if schm > 0 then
  begin
    schs := OpenServiceW(schm, PWideChar(sService), _DELETE or SERVICE_STOP or SERVICE_QUERY_STATUS);
    if schs > 0 then
    begin
      if (QueryServiceStatus(schs, ss)) then
      begin
        while (SERVICE_STOPPED <> ss.dwCurrentState) do
        begin
          ControlService(schs, SERVICE_CONTROL_STOP, ss);
          dwChkP := ss.dwCheckPoint;
          Sleep(ss.dwWaitHint);
          if (not QueryServiceStatus(schs, ss)) then
            Break;
          if (ss.dwCheckPoint < dwChkP) then
            Break;
        end;
      end;
      Result := DeleteService(schs);
      CloseServiceHandle(schs);
    end;
    CloseServiceHandle(schm);

    schm := OpenSCManagerW(PWideChar(sMachine), nil, SC_MANAGER_CONNECT);
    if schm > 0 then
    begin
      schs := OpenServiceW(schm, PWideChar(sService), _DELETE or SERVICE_STOP or SERVICE_QUERY_STATUS);
      if schs = 0 then
      begin
        if GetLastError = ERROR_SERVICE_DOES_NOT_EXIST then
        begin
          Writeln('Service not exists');
          Result := True;
        end;
      end
      else
      begin
        CloseServiceHandle(schs);
      end;
      CloseServiceHandle(schm);
    end;
  end;
end;

Kernel code:

NTSTATUS DrvProcCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return STATUS_SUCCESS;
}

NTSTATUS DrvProcClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return STATUS_SUCCESS;
}

#define NT_DEVICE_NAME L"\\Device\\MyDrv"
#define DOS_DEVICE_NAME L"\\??\\MyDrv"

void DrvProcUnload(IN PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING deviceLinkUnicodeString;
    NTSTATUS status;

    RtlInitUnicodeString(&deviceLinkUnicodeString, DOS_DEVICE_NAME);

    status = IoDeleteSymbolicLink(&deviceLinkUnicodeString);

    if (!NT_SUCCESS(status))
    {
        DbgPrint("IoDeleteSymbolicLink() error - 0x%X \n", status);
        return;
    }

    IoDeleteDevice(DriverObject->DeviceObject);

    DbgPrint("Goodbye from driver \n");
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
    UNICODE_STRING deviceNameUnicodeString;
    UNICODE_STRING deviceLinkUnicodeString;
    PDEVICE_OBJECT deviceObject = NULL;
    NTSTATUS ntStatus = STATUS_SUCCESS;

    RtlInitUnicodeString(&deviceNameUnicodeString, NT_DEVICE_NAME);

    ntStatus = IoCreateDevice(DriverObject, 0, &deviceNameUnicodeString, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &deviceObject);

    if (!NT_SUCCESS(ntStatus))
    {
        DbgPrint("IoCreateDevice() error - 0x%X \n", ntStatus);
        return ntStatus;
    }

    RtlInitUnicodeString(&deviceLinkUnicodeString, DOS_DEVICE_NAME);

    ntStatus = IoCreateSymbolicLink(&deviceLinkUnicodeString, &deviceNameUnicodeString);

    if (!NT_SUCCESS(ntStatus))
    {
        DbgPrint("IoCreateSymbolicLink() error - 0x%X \n", ntStatus);

        if (NULL != deviceObject)
        {
            IoDeleteDevice(deviceObject);
        }

        return ntStatus;
    }

    DriverObject->MajorFunction[IRP_MJ_CREATE] = DrvProcCreate;
    DriverObject->DriverUnload = DrvProcUnload;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = DrvProcClose;

    DbgPrint("Hello from driver \n");

    return ntStatus;
}

Edit:

After first comment below, ControlService returns:

1061 - ERROR_SERVICE_CANNOT_ACCEPT_CTRL, but in docs:

Drivers do not accept control codes other than SERVICE_CONTROL_STOP and SERVICE_CONTROL_INTERROGATE.


Edit 2:

I tried unload with PC Hunter ARK (a famous chinese anti rootkit) and my driver was stopped with success. The implementation of PC Hunter to unload .sys module is something like this. Why with Win32 api (ring3 - usermode) not works, someone know explain?

0

There are 0 best solutions below