Search code examples
javawinapijnaopenprocess

OpenProcess() fails for some users with access denied


I'm using Java JNA in order to access a process' memory on Windows. My code looks like this:

static WinNT.HANDLE openProcessHandle(int processId)
{
    val processAccessRights = PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_TERMINATE
            | PROCESS_NAME_NATIVE | PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION;
    val processHandle = Kernel32.INSTANCE.OpenProcess(processAccessRights, false, processId);
    if (processHandle == null)
    {
        val lastError = Native.getLastError();
        val formatMessageFromLastErrorCode = Kernel32Util.formatMessageFromLastErrorCode(lastError);
        val message = "OpenProcess() failed to open process id "
                + processId + ": " + formatMessageFromLastErrorCode;
        throw new IllegalStateException(message);
    }

    return processHandle;
}

I'm already not using PROCESS_ALL_ACCESS due to the problems it causes.

According to this answer, I also need to enable the debug privilege for my process. However, despite calling this code successfully (e.g. all return values indicate success) before OpenProcess(), some users still get the error message OpenProcess() failed to open process id xxxx: Access denied. My application is not running as administrator. Why does it work for me and most users without administrator rights but not all users? What exactly causes this inconsistency? I would prefer to understand and tackle this problem specifically rather than making all users run my software as administrator since my software generally doesn't need those extra rights.


Solution

  • I authored the answer you cited in 2017, and learned last year that I had missed something key. I probably should edit that older answer to update it, but I'd forgotten about it. See this answer for a corrected version of the code that I'll be editing into the previous one you cited.

    The API for AdjustTokenPrivileges() is somewhat broken in that it will give a false indication of success:

    If the function succeeds, the return value is nonzero. To determine whether the function adjusted all of the specified privileges, call GetLastError, which returns one of ... ERROR_SUCCESS ... ERROR_NOT_ALL_ASSIGNED.

    Given you are attempting to adjust the privileges with a non-admin user, you are not able to actually do so, and the other users will not be able to OpenProcess() for other users' processes. I don't think there is a workaround other than running your program with the necessary administrative power (SE_DEBUG_PRIVILEGE), which must be assigned by an administrator at some point.

    It is likely you are still getting a misleading indication of success, but need to check GetLastError() to see if it actually worked.