内核模式驱动程序和IOCTL

时间:2015-08-26 00:23:02

标签: windows kernel driver ioctl

我正在尝试做什么:

  1. 用户模式应用将进程ID发送给驱动程序
  2. 驱动程序获取指定进程ID的句柄
  3. 驱动程序将打开的句柄传递给用户模式应用
  4. 我不确定这段代码是否完全正常工作。我对驱动程序很新,所以我还没有设置调试,虚拟机还没有完成下载(连接速度慢)。

    从用户模式应用程序获取进程ID应该正常工作,它应该作为ProcessId存储在PROCESS_INFO结构中。打开的句柄存储在与ProcessHandle相同的结构中,以发送回用户模式应用程序。我不确定如何将数据从内核返回到用户模式,也许有人可以简单解释一下。

    这是我的代码:

    #include <ntifs.h>
    #include <wdf.h>
    
    DRIVER_INITIALIZE DriverEntry;
    
    UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\GetSysHandle"), SymbolicLink = RTL_CONSTANT_STRING(L"\\DosDevices\\GetSysHandle");
    
    typedef struct _PROCESS_INFO
    {
        HANDLE ProcessId;
        HANDLE ProcessHandle;
    }PROCESS_INFO, *PPROCESS_INFO;
    
    BOOLEAN GetSysHandle(PPROCESS_INFO ProcessInfo)
    {
        NTSTATUS status = STATUS_ACCESS_DENIED;
        PEPROCESS eProcess = NULL;
    
        status = PsLookupProcessByProcessId(ProcessInfo->ProcessId, &eProcess);
        if ((!NT_SUCCESS(status)) || (!eProcess))
        {
            return FALSE;
        }
        status = ObOpenObjectByPointer(eProcess, 0, NULL, 0, 0, KernelMode, &ProcessInfo->ProcessHandle);
    
        if ((!NT_SUCCESS(status)) || (!ProcessInfo->ProcessHandle))
        {
            ObDereferenceObject(eProcess);
            return FALSE;
        }
    
        return TRUE;
    }
    
    void Unload(PDRIVER_OBJECT pDriverObject)
    {
        DbgPrint("# GetSysHandle driver unloaded.");
    
        IoDeleteSymbolicLink(&SymbolicLink);
        IoDeleteDevice(pDriverObject->DeviceObject);
    }
    
    NTSTATUS DriverDispatch(PDEVICE_OBJECT DeviceObject, PIRP irp)
    {
        PIO_STACK_LOCATION io;
        PPROCESS_INFO ProcessInfo;
    
        NTSTATUS status;
    
        io = IoGetCurrentIrpStackLocation(irp);
        irp->IoStatus.Information = 0;
    
        switch (io->MajorFunction)
        {
        case IRP_MJ_CREATE:
            status = STATUS_SUCCESS;
            break;
        case IRP_MJ_CLOSE:
            status = STATUS_SUCCESS;
            break;
        case IRP_MJ_READ:
            status = STATUS_SUCCESS;
            break;
        case IRP_MJ_WRITE:
    
            ProcessInfo = (PPROCESS_INFO)MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority);
    
            if (!ProcessInfo)
            {
                status = STATUS_INSUFFICIENT_RESOURCES;
                break;
            }
    
            if (!GetSysHandle(ProcessInfo))
            {
                DbgPrint("# Failed to get process handle");
                status = STATUS_UNSUCCESSFUL;
                break;
            }
    
            status = STATUS_SUCCESS;
            irp->IoStatus.Information = sizeof(PROCESS_INFO);
    
            break;
    
        default:
            status = STATUS_INVALID_DEVICE_REQUEST;
            break;
        }
    
        irp->IoStatus.Status = status;
    
        IoCompleteRequest(irp, IO_NO_INCREMENT);
        return status;
    }
    
    NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT  DriverObject, _In_ PUNICODE_STRING RegistryPath)
    {
        PDEVICE_OBJECT DeviceObject;
        ULONG i;
    
        DbgPrint("# GetSysHandle driver loaded");
    
        IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &DeviceObject);
        IoCreateSymbolicLink(&SymbolicLink, &DeviceName);
    
        for (i = 0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
        {
            DriverObject->MajorFunction[i] = DriverDispatch;
        }
    
        return STATUS_SUCCESS;
    }
    

1 个答案:

答案 0 :(得分:0)

首先(避免混淆):此代码适用于Windows和Windows驱动程序。

我在驱动程序代码中看到的最大问题是您没有在DriverEntry中注册IRP主要功能。您需要将MajorFunction的{​​{1}}参数设置为调度函数。如果不分配这些PDRIVER_OBJECT DriverObject,驱动程序将无法知道在接收命令时要调用的函数。

为此,请将MajorFunctions的案例分解为不同的调度函数。例如,switch (io->MajorFunction)将是它自己的函数,你可以像这样声明它:

IRP_MJ_WRITE

在这种情况下,我们希望发给驱动程序的所有读命令都能运行DRIVER_DISPATCH DispatchReadFunction; 函数内的任何代码。所以定义看起来有点像这样:

DispatchReadFunction

我们写完NTSTATUS DispatchReadFunction(_In_ PDEVICE_OBJECT DriverObject, _In_ PIRP Irp) { NTSTATUS status = STATUS_SUCCESS; //Do read code here return status; } 函数后,您需要将其分配到DispatchReadFunction函数中的DriverObject->MajorFunction,如下所示:

DriverEntry

最后,存根并编写您需要的其他DriverObject->MajorFunction[IRP_MJ_READ] = DispatchReadFunction;函数,确保将它们分配给IRP_MJ_ MajorFunction成员。

我的DriverObject函数看起来像这样(我删除了额外的功能):

DriverEntry

一个好的起点是here。此链接还包含一个简单的示例(驱动程序代码和应用程​​序代码),可以执行您尝试执行的操作。

祝你好运!