将 PVOID 转换为 ULONG 或在 windows 内核驱动程序中使用 PVOID 作为 HANDLE

Posted

技术标签:

【中文标题】将 PVOID 转换为 ULONG 或在 windows 内核驱动程序中使用 PVOID 作为 HANDLE【英文标题】:Convert PVOID to ULONG or use PVOID as HANDLE in windows kernel driver 【发布时间】:2013-11-28 12:16:06 【问题描述】:

我正在尝试将 PVOID 转换为 ULONG,但它总是失败并给我错误的数据,还建议不要将指针变量类型转换为 int、ulong 或 msdn 中的其他数据类型,如 ULONG client = (ULONG) pvoidVar,但我试过了不同的技术和预定义的功能,例如:

ULONG client = PtrToUlong(pvoidVar);
ULONG client = (ULONG) PtrToUlong(pvoidVar);

发生的事情是我试图将客户端 ID 从用户模式应用程序发送到内核驱动程序,但内核驱动程序中的接收部分使其成为 PVOID Irp->UserBuffer 并且它发送我想用作 HANDLE 的进程 ID现在句柄与PVOID 相同,我想直接使用它,但它仍然不能像这样工作:

HANDLE processID = (HANDLE) Irp->UserBuffer;
HANDLE processID = Irp->UserBUffer;

我到处阅读,都建议使用PtrToUlongHANDLEPVOID 相同,我错了吗?请告诉我如何将PVOID 转换为ULONG 或如何将PVOID 用作HANDLE

编辑---

这是我的主驱动程序的代码,它不会崩溃,但输出错误

#include <ntddk.h>
#include <wdm.h>

#define DEVICE L"\\Device\\TEST"
#define DOSDEVICE L"\\DosDevices\\TEST"

VOID Unload(PDRIVER_OBJECT  DriverObject) 
    UNICODE_STRING DosDeviceName;

    DbgPrint("Driver Unloaded");

    RtlInitUnicodeString(&DosDeviceName, DOSDEVICE);
    IoDeleteSymbolicLink(&DosDeviceName);

    IoDeleteDevice(DriverObject->DeviceObject);


NTSTATUS IODispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) 
    Irp->iostatus.Status = STATUS_SUCCESS;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;


NTSTATUS IOManager(PDEVICE_OBJECT DeviceObject, PIRP Irp) 

    PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
    ULONG IRPcode = StackLocation->Parameters.DeviceIoControl.IoControlCode;

            // Here i cannot convert pvoid as ULONG if i try to do that it gives me some other value
    DbgPrint("%lu", (ULONG)Irp->AssociatedIrp.SystemBuffer);


    NTSTATUS ntStatus = STATUS_SUCCESS;
    HANDLE hProcess;
    OBJECT_ATTRIBUTES ObjectAttributes;
    CLIENT_ID ClientId;

            // Here i cannot use pvoid directly as a handle nor cast it as a handle as it fails
    ClientId.UniqueProcess = (HANDLE)Irp->AssociatedIrp.SystemBuffer;
    ClientId.UniqueThread = NULL;

    InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_INHERIT, NULL, NULL);

    ntStatus = ZwOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &ObjectAttributes, &ClientId);
    if(NT_SUCCESS(ntStatus)) 
        ZwClose(hProcess);
    

    Irp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return STATUS_SUCCESS;


NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) 
    NTSTATUS status = STATUS_SUCCESS;
    int uiIndex = 0;
    PDEVICE_OBJECT pDeviceObject = NULL;
    UNICODE_STRING DriverName, DosDeviceName;

    DbgPrint("Driver Loaded");

    RtlInitUnicodeString(&DriverName, DEVICE);
    RtlInitUnicodeString(&DosDeviceName, DOSDEVICE);

    pDriverObject->DriverUnload =  Unload;

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

    if (!NT_SUCCESS(status)) 
        DbgPrint("IoCreateDevice failed: %x", status);
        return status;
    

    status = IoCreateSymbolicLink(&DosDeviceName, &DriverName);

    if (!NT_SUCCESS(status)) 
        IoDeleteDevice(pDeviceObject);
        DbgPrint("IoCreateSymbolicLink failed");
        return status;
    

    pDriverObject->MajorFunction[IRP_MJ_CREATE] = IODispatch;
    pDriverObject->MajorFunction[IRP_MJ_CLOSE]  = IODispatch;
    pDriverObject->MajorFunction[IRP_MJ_READ]   = IODispatch;
    pDriverObject->MajorFunction[IRP_MJ_WRITE]  = IODispatch;
    pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IOManager;

    return status;


这是我的用户模式应用程序

#define SYSFILE L"C:\\TEST.sys"
#define SERVICENAME L"TEST"

BOOL GetProcessList();
VOID startServ(DWORD processID);

int _cdecl main(void) 
    GetProcessList();
    return 0;


BOOL GetProcessList() 
    HANDLE hProcessSnap;
    PROCESSENTRY32 pe32;

    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProcessSnap == INVALID_HANDLE_VALUE) 
        printf("CreateTool");
        getchar();
        return(FALSE);
    

    pe32.dwSize = sizeof(PROCESSENTRY32);

    if(!Process32First(hProcessSnap, &pe32)) 
        CloseHandle(hProcessSnap);
        printf("Process32");
        getchar();
        return(FALSE);
    

    do 
        if (wcscmp(L"test.exe", pe32.szExeFile) == 0) 
            startServ(pe32.th32ProcessID);
        

     while(Process32Next(hProcessSnap, &pe32));

    CloseHandle(hProcessSnap);
    return(TRUE);


VOID startServ(DWORD processID) 

    SC_HANDLE hSCManager;
    SC_HANDLE hService;
    SERVICE_STATUS ss;

    hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);

    printf("Load Driver\n");

    if(hSCManager)
    
        printf("Create Service\n");

        hService = CreateService(hSCManager, SERVICENAME, 
            SERVICENAME, 
            SERVICE_ALL_ACCESS, 
            SERVICE_KERNEL_DRIVER,
            SERVICE_DEMAND_START, 
            SERVICE_ERROR_IGNORE, 
            SYS_FILE, 
            NULL, NULL, NULL, NULL, NULL);

        printf("CreateService: %d\r\n", GetLastError());

        if(!hService) 
            hService = OpenService(hSCManager, SERVICENAME, SERVICE_ALL_ACCESS);
        

        printf("OpenService: %d\r\n", GetLastError());

        if(hService) 
            printf("Start Service\n");

            StartService(hService, 0, NULL);

            printf("StartService: %d\r\n", GetLastError());

            HANDLE hFile;

            hFile = CreateFile(L"\\\\.\\Global\\TEST\0", GENERIC_READ|GENERIC_WRITE, 0, NULL,
                OPEN_EXISTING, 0, NULL);

            printf("CreateFile: %d\r\n", GetLastError());

            wchar_t pid[1024];

            wsprintf(pid, L"%d", processID);

            if(hFile) 
                char ret[1024];
                DWORD bytes;

                DeviceIoControl(hFile, 4092, pid, (wcslen(pid)+1)*2, &ret, sizeof(ret), &bytes, NULL); 
                CloseHandle(hFile);
            

            printf("Press Enter to close service\r\n");
            getchar();
            ControlService(hService, SERVICE_CONTROL_STOP, &ss);

            DeleteService(hService);

            CloseServiceHandle(hService);

        

        CloseServiceHandle(hSCManager);
    


现在所有这一切都不会崩溃或损坏或给我蓝屏,但它给我驱动程序中的错误输出,但是如果我不强制转换并将它用作PVOID,那么它会给我正确的输出

【问题讨论】:

这是 32 位还是 64 位? @RogerRowland: 32 位,但我也会做 64 位 你的意思“不起作用”是什么意思?不编译?崩溃?把电脑变成会飞的白菜? “我想用作句柄的进程 ID”是什么意思,有什么意义? 我已经添加了完整的源代码,请查看它 【参考方案1】:

你错过了一个指针解引用:

HANDLE processID = *(HANDLE*)Irp->UserBuffer;

还要注意 sizeof(HANDLE) 取决于进程位数,所以最好使用固定大小的类型。对于 PID/TID 值,32 位就足够了。

更新:

您还传递了 PID 的字符串表示形式。使用二进制形式:

DeviceIoControl(hFile, 4092, &processID, sizeof(processID)

【讨论】:

请向我们展示更多您的代码:您的 IOCTL 是如何定义的以及如何发送它。 我已经添加了驱动程序和用户模式应用程序的完整源代码,请查看它,谢谢【参考方案2】:

您说您正在尝试将“客户端 ID”从用户发送到内核空间。这个实体“客户 ID”是什么?我不熟悉这个词。

如果它是一个指针,那么它(最多)在用户空间或内核空间之一中是有意义的,因此将它从一个空间传递到另一个是没有意义的;这些是单独的地址空间。 如果是ULONG,那么你就不需要做类型转换,所以你的问题是错误的。 如果您认为它既是指针又是 ulong,那么您可能会感到困惑,因为它们是不同的类型。

进程 ID 与这个问题有什么关系?它们是第四类实体,既不是您的“客户 ID”,也不是指针,也不是 ulong。

对不起,我帮不上忙;我不明白你想做什么。

我不得不说,你尝试编写 Win32 内核模式代码让我非常害怕,但看起来很困惑。也许您应该解释为什么您认为需要编写内核模式代码。您可能应该从一开始就开始:“我正在尝试制作一个能够实现...的软件系统”

【讨论】:

我正在尝试制作许可证系统并学习 Windows 驱动程序开发 clientID 是我的服务器生成的 ID,用户模式应用程序将获取它并将其发送给驱动程序,如果它现在将验证它许可证过期,然后驱动程序将终止应用程序并且不允许它启动(这就是我需要进程 ID 的原因)现在我只使用 WriteFile api 与驱动程序通信,因为还有很多东西要学习所以从接收的数据用户应用程序在 pvoid 中,因为我使用 PIRP 并且数据在 UserBufferPIRP 对象中,这是一个 PVOID 抱歉,如果我仍然让您感到困惑。 如果您的客户 ID 是一个不透明的数字,您不需要将其转换为指针或从指针转换。如果您使用 I/O 请求数据包跨用户/内核空间边界传递数据,那么您可能希望将此客户端 ID 放入数据包中。 另外,你不能信任内核;它可能有一个rootkit,或者你的许可证系统的破解,以及你的许可证系统。或者某些东西可能正在窥探交换。您打算如何防御重放攻击? 如果我是你,我会调查现有许可系统的运作模式,例如 FlexLM。我所知道的它们都没有内核模式组件。您可能希望将加密签名的令牌(如 Kerberos)从用户模式许可服务器分发给受许可限制的客户端。我原则上讨厌软件许可的整个想法(我使用开源),所以这就是我的想法。祝你好运! 我想学习 Windows 驱动程序开发,但我不知道我是否错了,但我通过开发东西来学习,而且这个许可证系统具有所有网络、密码学我想实现的任何可能抱歉,如果我的方法有误

以上是关于将 PVOID 转换为 ULONG 或在 windows 内核驱动程序中使用 PVOID 作为 HANDLE的主要内容,如果未能解决你的问题,请参考以下文章

ring0 SSDTHook 实现x64/x86

将 Long/ULong 转换为带有填充零的无符号十六进制字符串

从 HANDLE 到 ULONG C++ 的类型转换截断

C# 是不是有办法将具有 int 字段(字节、ushort、ulong 等)的对象编写为字节数组?

(转) SYSTEM_HANDLE_INFORMATION中ObjectTypeIndex的定义

inet_addr返回值一样