使用命名管道获取 ProcessID 的安全方法

Safe way to get ProcessID using Named Pipes

提问人:InversionDK 提问时间:11/2/2023 更新时间:11/2/2023 访问量:37

问:

我有一个由 GUI 和服务组成的应用程序。它们在同一台计算机上运行,并通过 WCF 通过命名管道进行通信。

从服务中,我尝试获取通过命名管道调用服务的进程的进程 ID。但是,在使用 WCF 时,我很难做到这一点。

我创建了一个测试应用程序,它允许我使用没有 WCF 的命名管道(直接通过 System.IO.Pipes)来执行此操作 - 但我能弄清楚如何做到这一点的唯一方法需要我使用 SafePipeHandle.DangerousGetHandle()。

我想知道是否有人可以给我一些指导

  • 是否可以使用 WCF 或不使用 DangerousGetHandle() 来获取 PID?
  • 使用 SafePipeHandle.DangerousGetHandle() 方法可以吗?(听起来不安全)

我真的不想将 PID 作为元数据或来自 GUI 的消息的一部分发送,因为这很容易被欺骗。

我的示例服务器代码:

static void Main(string[] args)
{
using (var server = new NamedPipeServerStream("TestPipe", PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte, PipeOptions.Asynchronous))
{
    Console.WriteLine("Server waiting for connection...");
    server.WaitForConnection();

    using (StreamReader reader = new StreamReader(server))
    {
        string message;
        while ((message = reader.ReadLine()) != null)
        {
            uint clientProcessId;
            if (NativeMethods.GetNamedPipeClientProcessId(server.SafePipeHandle.DangerousGetHandle(), out clientProcessId))
            {
                Console.WriteLine($"Received: {message} from PID {clientProcessId}");
            }
            else
            {
                Console.WriteLine("Failed to get client process ID.");
            }
        }
    }

    server.Disconnect();
}
Console.WriteLine("Server disconnected...");

}

NativeMethods 只是一个包装器:

public static class NativeMethods
{
   [DllImport("kernel32.dll", SetLastError = true)]
   public static extern bool GetNamedPipeClientProcessId(IntPtr Pipe, out uint ClientProcessId);
}

任何指点将不胜感激。我已经完全没有想法了:)

C# WCF 命名管道

评论

0赞 QI You 11/3/2023
我认为您可以使用 NetNamedPipeBinding 来确定 pid。这篇文章可以帮助你WCF NetNamedPipeBinding确定客户端的进程ID

答:

0赞 Tenatus 11/2/2023 #1

我假设当服务器仍连接到管道时,管道的句柄将保持有效,因此这是对一般不安全方法的安全使用。

警告的风险是针对标记为无效/重用的句柄,但我认为您的代码根本不可能出现这种情况: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.safehandle.dangerousgethandle

评论

0赞 InversionDK 11/3/2023
我有点担心文档中的这个表述:“例如,不受信任的调用方可以查询刚刚返回的句柄上的数据,并接收完全不相关资源的信息。如果我在请求传入时验证客户端的 ProcessID(例如,通过验证进程签名或类似方法)作为服务器上的第一件事,这会让我免受这种情况的影响吗?
0赞 Tenatus 11/3/2023
我认为管道的句柄在服务器之前不会失效。Disconnect() 行。该代码从管道中获取 SafeHandle 并立即使用底层句柄,因此我认为 Windows 不可能在此过程中重用它。存放该手柄并在以后使用它会很危险。