简体   繁体   English

尝试获取客户端进程可执行文件路径时访问拒绝错误

[英]Access Denied Error while trying to get the client process executable path

I am working on a WCF service that is hosted as a windows service which uses named pipes - NamedPipeServerStream (Users privilege) to establish secured connection between server and client processes. 我正在使用作为Windows服务托管的WCF服务,该服务使用命名管道-NamedPipeServerStream (用户特权)在服务器和客户端进程之间建立安全连接。 To check the authenticity of the client process, I need to verify the digital signature of the client process executable and so I am trying to get the executable path of the client by using its process id. 为了检查客户端进程的真实性,我需要验证客户端进程可执行文件的数字签名,因此我尝试使用其进程ID获取客户端的可执行文件路径。

I use Windows 7 Professional SP1 (64 bit) OS and Visual Studio 2015 Community Edition for developement. 我使用Windows 7 Professional SP1(64位)操作系统Visual Studio 2015 Community Edition进行开发。 Both the server (windows service) and client processes (other exe) are built in Release x64 mode only. 服务器(Windows服务)和客户端进程(其他exe)都仅在Release x64模式下构建。

When some client process is connected to the server, I am trying to get the client process exe path but it is throwing "Access Denied" error in the following line of code: 当某些客户端进程连接到服务器时,我试图获取客户端进程exe路径,但在以下代码行中抛出“访问被拒绝”错误

return Process.GetProcessById(processId).MainModule.FileName;

Hence to resolve this issue, I had googled around and tried some other experimental trials as described below that too does not seem to work out. 因此,为了解决此问题,我在Google周围搜索并尝试了如下所述的其他一些实验性试验,但这些试验似乎也没有奏效。

Experimental Trials 实验性试验

  1. Tried to get the client process handle with query access privilege but failed --> Always returns 0 and last Win32 error as 5 ( Access Denied ) 试图获取具有查询访问权限的客户端进程句柄,但失败->始终返回0,最后一个Win32错误为5( 拒绝访问

OpenProcess(ProcessAccessFlags.PROCESS_QUERY_INFORMATION, false, processId);

  1. Tried to get the client process handle with limited query access privilege but failed --> Always returns 0 and last Win32 error as 5 ( Access Denied ) 试图获取具有有限查询访问权限的客户端进程句柄,但失败->始终返回0,最后一个Win32错误为5( 访问被拒绝

OpenProcess(ProcessAccessFlags.PROCESS_QUERY_LIMITED_INFORMATION, false, processId);

  1. Set the SeDebugPrivilege and proceeded to get the client process handle with limited query privilege but failed --> SeDebugPrivilege is enabled but still returning 0 for process handle and last Win32 error as 5 ( Access Denied ). 设置SeDebugPrivilege并继续获取具有有限查询特权的客户端进程句柄,但是失败->启用了SeDebugPrivilege,但仍为进程句柄返回0,最后一次Win32错误返回5( 访问被拒绝 )。
  2. Tried to set administrator privilege to the windows service using app.manifest file (requireAdministrator attribute) but failed --> Access denied 试图使用app.manifest文件(requireAdministrator属性)将管理员权限设置为Windows服务,但失败-> 访问被拒绝
  3. Tried using ManagementObject to get the process info properties but failed --> Object reference not set to an instance of the object 尝试使用ManagementObject获取流程信息属性,但失败->对象引用未设置为该对象的实例
  4. Changed the logon account for the windows service as "Local System" from "Local Service" but failed Windows服务的登录帐户从“本地服务”更改为“本地系统”,但失败

However, I tried all the above methods in a sample windows console application which is working fine without any errors and the same is not working in the windows service. 但是,我在一个示例Windows控制台应用程序中尝试了所有上述方法,该应用程序运行正常,没有任何错误,并且在Windows服务中也无法正常运行。 Also I tried to convert the console application into a dll and referred it in the server to get the client process info but failed --> again Access denied 我也尝试将控制台应用程序转换为dll并在服务器中引用它以获取客户端进程信息,但失败->再次访问被拒绝

I am completely clueless about what is happening and how to resolve it. 我对正在发生的事情以及如何解决它一无所知。 Your suggestions would be really helpful. 您的建议将非常有帮助。

EDIT : Please find the code snippet for OpenProcess and the ProcessAccessFlags as below: 编辑:请找到如下所示的OpenProcess和ProcessAccessFlags的代码片段:

public static string GetProcessExecutablePath(int processId)
{
    try
    {
        string exePath = string.Empty;
        //If running on Vista or later use the new function
        if (Environment.OSVersion.Version.Major >= 6)
        {
            return GetProcessExecutablePathAboveVista(processId);
        }
        return Process.GetProcessById(processId).MainModule.FileName;
    }
    catch (Exception ex)
    {
        return "Exception in GetProcessExecutablePath(): " + ex.Message + ": " + ex.InnerException;
    }
}    

private static string GetProcessExecutablePathAboveVista(int processId)
{
    var buffer = new StringBuilder(1024);
    IntPtr hprocess = NativeMethods.OpenProcess(NativeMethods.ProcessAccessFlags.PROCESS_QUERY_LIMITED_INFORMATION,
                                      false, processId);
    if (hprocess != IntPtr.Zero)
    {
        try
        {
            int size = buffer.Capacity;
            if (NativeMethods.QueryFullProcessImageName(hprocess, 0, buffer, out size))
            {
                return buffer.ToString();
            }
            else
            {
                return "Failed in QueryFullProcessImageName(): " + Marshal.GetLastWin32Error();;
            }
        }
        catch (Exception ex)
        {
            return "Exception in: " + ex.Message;
        }
        finally
        {
            NativeMethods.CloseHandle(hprocess);
        }
    }
    else
    {
        return "Handle is Zero: " + Marshal.GetLastWin32Error();
    }
}

NativeMethods.cs NativeMethods.cs

[Flags]
public enum ProcessAccessFlags
{
    PROCESS_TERMINATE = 0x0001,
    PROCESS_CREATE_THREAD = 0x0002,
    PROCESS_VM_OPERATION = 0x0008,
    PROCESS_VM_READ = 0x0010,
    PROCESS_VM_WRITE = 0x0020,
    PROCESS_DUP_HANDLE = 0x0040,
    PROCESS_CREATE_PROCESS = 0x0080,
    PROCESS_SET_QUOTA = 0x0100,
    PROCESS_SET_INFORMATION = 0x0200,
    PROCESS_QUERY_INFORMATION = 0x0400,
    PROCESS_SUSPEND_RESUME = 0x0800,
    PROCESS_QUERY_LIMITED_INFORMATION = 0x1000,
    SYNCHRONIZE = 0x100000,
    DELETE = 0x00010000,
    READ_CONTROL = 0x00020000,
    WRITE_DAC = 0x00040000,
    WRITE_OWNER = 0x00080000,
    STANDARD_RIGHTS_REQUIRED = 0x000F0000,
    PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF
}

[DllImport("Kernel32.dll", EntryPoint = "OpenProcess", SetLastError = true)]
public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, int dwProcessId);

[DllImport("Kernel32.dll", EntryPoint = "QueryFullProcessImageName", SetLastError = true)]
public static extern bool QueryFullProcessImageName(IntPtr hprocess, int dwFlags, StringBuilder lpExeName, out int size);

[DllImport("Kernel32.dll", EntryPoint = "CloseHandle", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hHandle);

For Windows starting from Vista to get process image file name by pid you may use NtQuerySystemInformation(SystemProcessInformation, ...) to obtain array of SYSTEM_PROCESS_INFORMATION structures for each process. 对于从Vista开始的Windows,通过pid获取进程映像文件名,可以使用NtQuerySystemInformation(SystemProcessInformation, ...)为每个进程获取SYSTEM_PROCESS_INFORMATION结构的数组。 This structure has PVOID UniqueProcessId to find pid you're looking for and UNICODE_STRING ImageName to get image file name, see https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms724509(v=vs.85).aspx https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/process.htm 此结构具有PVOID UniqueProcessId以查找您要查找的pid和UNICODE_STRING ImageName以获取图像文件名,请参阅https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms724509(v=vs.85 ).aspx https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/process.htm

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM