使用系统api ZwOpenProcess打开句柄

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
HANDLE PidToHandle(ULONG PID)
{
if (!PID)return NULL;
HANDLE hProcessHandle;
OBJECT_ATTRIBUTES obj;
CLIENT_ID clientid;

clientid.UniqueProcess = PID;
clientid.UniqueThread = 0;

// 属性初始化
InitializeObjectAttributes(&obj, 0, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);

NTSTATUS status = ZwOpenProcess(&hProcessHandle, PROCESS_ALL_ACCESS, &obj, &clientid);
if (status == STATUS_SUCCESS)
{
DbgPrint("[*] 已打开 \n");
ZwClose(&hProcessHandle);
return hProcessHandle;
}

return 0;
}

使用自定义函数打开进程句柄

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
NTSTATUS KernelOpenProcessHandle(
HANDLE pid,
PHANDLE pHandle
)
{
PEPROCESS process;
NTSTATUS status = PsLookupProcessByProcessId(pid, &process);
if (!NT_SUCCESS(status))
return status;

status = ObOpenObjectByPointer(
process,
OBJ_KERNEL_HANDLE,
NULL,
PROCESS_ALL_ACCESS,
*PsProcessType,
KernelMode,
pHandle
);

ObDereferenceObject(process);
return status;
}

使用系统api ZwOpenProcess打开句柄后将句柄传递给应用层

✅ 示例流程:

用户层:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
typedef struct {
ULONG pid;
} OPEN_PROC_INPUT;

typedef struct {
HANDLE hProcess;
} OPEN_PROC_OUTPUT;

OPEN_PROC_INPUT input = { .pid = 1234 };
OPEN_PROC_OUTPUT output = { 0 };

DeviceIoControl(
hDevice,
IOCTL_OPEN_TARGET_PROCESS,
&input,
sizeof(input),
&output,
sizeof(output),
&bytesReturned,
NULL
);

// output.hProcess 就是你从内核返回的句柄(如果你允许返回到用户层)

⚠️ 如果你要将内核打开的句柄传回用户层使用,还要注意:这个句柄必须是 用户可访问的句柄,不能加 OBJ_KERNEL_HANDLE 标志。


内核驱动中:

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
case IOCTL_OPEN_TARGET_PROCESS:
{
POPEN_PROC_INPUT in = Irp->AssociatedIrp.SystemBuffer;
POPEN_PROC_OUTPUT out = Irp->AssociatedIrp.SystemBuffer;

HANDLE userHandle = NULL;
OBJECT_ATTRIBUTES objAttr;
CLIENT_ID clientId = { 0 };
clientId.UniqueProcess = (HANDLE)in->pid;
clientId.UniqueThread = 0;

InitializeObjectAttributes(&objAttr, NULL, 0, NULL, NULL);

NTSTATUS status = ZwOpenProcess(
&userHandle,
PROCESS_ALL_ACCESS,
&objAttr,
&clientId
);

out->hProcess = userHandle;
Irp->IoStatus.Information = sizeof(OPEN_PROC_OUTPUT);
Irp->IoStatus.Status = status;
break;
}

🧠 小总结:

做法 是否可行 说明
用户层直接调用 KernelOpenProcessHandle 自定义函数,非系统导出
用户层通过 IOCTL 调用驱动函数 推荐做法
用户层用系统 API(如 OpenProcess 系统支持
内核打开句柄返回用户层使用 ⚠️ 可以,但注意句柄权限和安全性