使用 RpcServerInqCallAttributes 检索 clientPID

Retrieve clientPID using RpcServerInqCallAttributes

本文关键字:clientPID 检索 RpcServerInqCallAttributes 使用      更新时间:2023-10-16

我需要在使用ncalrpc协议的RPC回调中检索客户端进程ID。MSDN建议使用具有RPC_CALL_ATTRIBUTES_V2结构的RpcServerInqCallAttributes。文档说进程 ID 作为句柄返回

https://msdn.microsoft.com/en-us/library/windows/desktop/aa378501(v=vs.85).aspx

我无法理解。它是指向具有进程 ID 的 DWORD 还是进程句柄,我可以在其中使用 GetProcessId API 获取 PID?

同样在这两种情况下,谁关闭句柄或删除分配给 DWORD 的内存?

ClientPID是调用客户端的进程 ID。

它指向DWORD吗?

是进程句柄吗?

我可以使用 GetProcessId API 获取 PID 吗?

不,这是 PID 值本身。您可以执行类型转换以用于OpenProcess调用 -(ULONG)(ULONG_PTR)RpcCallAttributes.ClientPID

谁关闭句柄或删除分配给 DWORD 的内存?

它不得关闭(此句柄永远不需要关闭)或释放(这不是指针)

进程和线程 ID - 实际上是特殊句柄表 (PspCidTable中的句柄。 它本机表示为句柄。 本机 (NTDLL) API 和内核模式 API 始终使用进程和线程 ID 作为句柄。 查找CLIENT_ID

typedef struct _CLIENT_ID {
   HANDLE UniqueProcess;
   HANDLE UniqueThread;
 } CLIENT_ID;

此活动用于不同的本机 API,例如ZwOpenProcess所有内核模式 API 都使用它作为句柄,例如 -PsLookupProcessByProcessId

只需将 Win32 层截断HANDLE UniqueProcess;即可DWORD UniqueProcess

因此,如果您想在 Win32 调用OpenProcess中使用RPC_CALL_ATTRIBUTES_V2结构中的ClientPID- 您只需将其转换为DWORD. 例如:

RPC_CALL_ATTRIBUTES_V2_W RpcCallAttributes = {
RPC_CALL_ATTRIBUTES_VERSION, RPC_QUERY_CLIENT_PID
};
if (RPC_S_OK == RpcServerInqCallAttributes(0, &RpcCallAttributes))
{
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 
(ULONG)(ULONG_PTR)RpcCallAttributes.ClientPID);
}

如果使用本机 API - 类型转换不需要。

例如
RPC_CALL_ATTRIBUTES_V2_W RpcCallAttributes = {
RPC_CALL_ATTRIBUTES_VERSION, RPC_QUERY_CLIENT_PID
};
if (RPC_S_OK == RpcServerInqCallAttributes(0, &RpcCallAttributes))
{
HANDLE hProcess;
static OBJECT_ATTRIBUTES zoa = { sizeof(zoa) };
CLIENT_ID cid = { RpcCallAttributes.ClientPID };
ZwOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &zoa, &cid );
}

鉴于 MSDN 多次特意说它是一个 PID,并且在客户端进程终止后可以重用该值,我会说它被定义为句柄是错误的,它实际上是一个 PID 值。在这种情况下,它不需要解除分配,只需让整个RPC_CALL_ATTRIBUTES_V2结构超出范围即可。

https://learn.microsoft.com/en-us/windows/desktop/api/rpcasync/ns-rpcasync-tagrpc_call_attributes_v2_a

客户端PID

包含调用客户端的进程 ID 的句柄。此字段 仅 ncalrpc 协议序列支持,并已填充 仅当在 Flags 参数中指定RPC_QUERY_CLIENT_PID时。

我发现这是作为PID工作,而不是HANDLE。那是:

HANDLE hproc = (HANDLE)ClientPID.ClientPID;
NtQueryProcessInformation ( hproc ...) 

失败,但

cpid = (DWORD)(DWORD_PTR)ClientPID.ClientPID;
hcproc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, FALSE, cpid);

成功。

所以MSDN是对的:它被表示为一个句柄,但它需要强制转换为DWORD PID才能在后续调用中使用。