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

6

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. 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.

I use Windows 7 Professional SP1 (64 bit) OS and Visual Studio 2015 Community Edition for developement. Both the server (windows service) and client processes (other exe) are built in Release x64 mode only.

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:

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.

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)

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)

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).
  2. Tried to set administrator privilege to the windows service using app.manifest file (requireAdministrator attribute) but failed --> Access denied
  3. Tried using ManagementObject to get the process info properties but failed --> Object reference not set to an instance of the object
  4. Changed the logon account for the windows service as "Local System" from "Local Service" but failed

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. 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

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:

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

[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);
c#
windows
wcf
winapi
namedpipeserverstream
asked on Stack Overflow Nov 4, 2016 by Sophia S • edited Nov 4, 2016 by Sophia S

1 Answer

0

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. 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

answered on Stack Overflow Feb 6, 2018 by Prime Ape

User contributions licensed under CC BY-SA 3.0