将 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;
我到处阅读,都建议使用PtrToUlong
和HANDLE
与PVOID
相同,我错了吗?请告诉我如何将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
并且数据在 UserBuffer
的 PIRP
对象中,这是一个 PVOID 抱歉,如果我仍然让您感到困惑。
如果您的客户 ID 是一个不透明的数字,您不需要将其转换为指针或从指针转换。如果您使用 I/O 请求数据包跨用户/内核空间边界传递数据,那么您可能希望将此客户端 ID 放入数据包中。
另外,你不能信任内核;它可能有一个rootkit,或者你的许可证系统的破解,以及你的许可证系统。或者某些东西可能正在窥探交换。您打算如何防御重放攻击?
如果我是你,我会调查现有许可系统的运作模式,例如 FlexLM。我所知道的它们都没有内核模式组件。您可能希望将加密签名的令牌(如 Kerberos)从用户模式许可服务器分发给受许可限制的客户端。我原则上讨厌软件许可的整个想法(我使用开源),所以这就是我的想法。祝你好运!
我想学习 Windows 驱动程序开发,但我不知道我是否错了,但我通过开发东西来学习,而且这个许可证系统具有所有网络、密码学我想实现的任何可能抱歉,如果我的方法有误以上是关于将 PVOID 转换为 ULONG 或在 windows 内核驱动程序中使用 PVOID 作为 HANDLE的主要内容,如果未能解决你的问题,请参考以下文章
将 Long/ULong 转换为带有填充零的无符号十六进制字符串
C# 是不是有办法将具有 int 字段(字节、ushort、ulong 等)的对象编写为字节数组?