使用 RpcServerInqCallAttributes 检索 clientPID
Posted
技术标签:
【中文标题】使用 RpcServerInqCallAttributes 检索 clientPID【英文标题】:Retrieve clientPID using RpcServerInqCallAttributes 【发布时间】:2018-01-14 08:50:45 【问题描述】:我需要在使用 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 的内存?
【问题讨论】:
这正是PID
原样。您可以将其转换为DWORD
。真的在 Windows 中PID
是句柄。查找例如CLIENT_ID
或说PsLookupProcessByProcessId
等等。这只是win32 层将HANDLE PID
转换为DWORD
【参考方案1】:
考虑到 MSDN 多次特意说它是一个 PID 并且该值可以在客户端进程终止后重新使用,我会说它被定义为 HANDLE 是错误的,它在事实上一个PID值。既然这样就不需要释放了,只要让整个 RPC_CALL_ATTRIBUTES_V2 结构超出范围即可。
【讨论】:
【参考方案2】: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 );
【讨论】:
【参考方案3】:https://docs.microsoft.com/en-us/windows/desktop/api/rpcasync/ns-rpcasync-tagrpc_call_attributes_v2_a
客户端 ID
包含调用客户端的进程 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 是对的:它表示为 HANDLE,但需要将其强制转换为 DWORD PID 以便在后续调用中使用。
【讨论】:
以上是关于使用 RpcServerInqCallAttributes 检索 clientPID的主要内容,如果未能解决你的问题,请参考以下文章
在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?
Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)