目标进程用户模式句柄转换为内核句柄

网上很多方法都是Ring0内核进程和句柄互相转换的方法,查了一下没怎么看到说怎么将用户模式句柄转换为内核句柄的。如果内核获取到的是目标进程的句柄,拷贝到内核模式是不能直接使用的,会引发异常。

目前想到的实现思路是:

  1. 如果是伪句柄,直接返回后面再来处理。
  2. 调用ObReferenceObjectByHandle指定用户模式句柄获取任意对象的体指针 (EProcess、EThread )
  3. 调用ObOpenObjectByPointer打开指针所引用的对象,并返回对象的句柄,此时设置为内核句柄。就获取到啦。

本人是菜鸟,各位师傅如果知道其他的方法跪求指点!!!

实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
NTSTATUS ConvertKernelHandle(
IN HANDLE UserHandle,
OUT PHANDLE KernelHandle,
POBJECT_TYPE ObjectType
)
{
NTSTATUS Status = STATUS_SUCCESS;
PVOID Object = NULL; //任意对象的体指针 EProcess EThread
LONG v1 = (LONG)UserHandle;

if (KernelHandle == NULL)
{
Status = STATUS_INVALID_PARAMETER;
goto Exit;
}

if (v1 <= 0)
{
*KernelHandle = UserHandle;
Status = STATUS_SUCCESS;
goto Exit;
}

Status = ObReferenceObjectByHandle(
UserHandle,
0,
ObjectType,
UserMode,
&Object,
NULL
);

if (Status != STATUS_SUCCESS)
{
goto Exit;
}

Status = ObOpenObjectByPointer(
Object,
OBJ_KERNEL_HANDLE,
0,
0,
NULL,
KernelMode,
KernelHandle
);

if (*KernelHandle == UserHandle) {
Status = STATUS_UNSUCCESSFUL;
}

Exit:
if (Object != NULL) {
ObDereferenceObject(Object);
}

return Status;
}

伪句柄转换为真实句柄,可以调用复制对象句柄的DuplicateHandle

1
2
3
4
5
6
7
8
9
BOOL DuplicateHandle(
[in] HANDLE hSourceProcessHandle,
[in] HANDLE hSourceHandle,
[in] HANDLE hTargetProcessHandle,
[out] LPHANDLE lpTargetHandle,
[in] DWORD dwDesiredAccess,
[in] BOOL bInheritHandle,
[in] DWORD dwOptions
);

微软官方在对此函数的解释中,说明了如果 hSourceHandle 是伪句柄, 会将其转换为进程或线程的实际句柄。

参考

ObOpenObjectByPointer 函数 (ntifs.h) - Windows drivers | Microsoft Learn

ObReferenceObjectByHandle 函数 (wdm.h) - Windows drivers | Microsoft Learn

DuplicateHandle 函数 (handleapi.h) - Win32 apps | Microsoft Learn

伪句柄转换为真正的句柄 - 沉疴 - 博客园 (cnblogs.com)