【问题标题】:Retrieve clientPID using RpcServerInqCallAttributes使用 RpcServerInqCallAttributes 检索 clientPID
【发布时间】: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

标签: c++ winapi visual-c++ rpc


【解决方案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 以便在后续调用中使用。

      【讨论】:

        猜你喜欢
        • 2022-06-11
        • 2021-09-02
        • 2014-02-17
        • 2012-12-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多