Why do I need to acquire the debug privilege to use OpenProcess with minimal permissions when running as an admin?

1.7k views Asked by At

One of my programs attempts to call OpenProcess on another of my programs, which is a service. The first program is running either as the local Administrator account or as another member of the Administrators group, and the service is running as the SYSTEM user.

I've found that in at least one environment (but not all) the call to OpenProcess fails with ERROR_ACCESS_DENIED. Furthermore, I've found that if I use AdjustTokenPrivileges to acquire the SE_DEBUG_NAME privilege, then OpenProcess succeeds. I've reproduced the behavior using the program below. The environment where it fails is running Windows 8.1, but off hand I don't know what the successful systems are running.

The only permission the program requests is PROCESS_QUERY_LIMITED_INFORMATION (because it eventually calls QueryFullProcessImageName). Nothing I've read suggests that debug privileges are required for that, only for more "intrusive" access like PROCESS_VM_READ or PROCESS_ALL_ACCESS, which I'm not interested in.

I've read about protected processes, and even though the service I'm targeting isn't designated as a protected process, documentation says that PROCESS_QUERY_LIMITED_INFORMATION isn't among the permissions that are forbidden from being granted for protected processes anyway.

Why would the original call to OpenProcess fail, and why does the debugging privilege make a difference?

#include <Windows.h>
#include <iostream>
#include <sstream>
#include <string>

int main(int argc, char* argv[])
{
    std::istringstream pid_s(argv[1]);
    DWORD pid;
    pid_s >> pid;
    bool debug = !!argv[2];

    if (debug) {
        TOKEN_PRIVILEGES NewState;
        NewState.PrivilegeCount = 1;
        if (!LookupPrivilegeValue(nullptr, SE_DEBUG_NAME, &NewState.Privileges[0].Luid)) {
            std::clog << "Could not acquire debug-privilege name: " << GetLastError() << "\n";
            return EXIT_FAILURE;
        }

        HANDLE token;
        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) {
            std::clog << "Could not acquire process token: " << GetLastError() << "\n";
            return EXIT_FAILURE;
        }

        NewState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        if (!AdjustTokenPrivileges(token, FALSE, &NewState, sizeof(NewState), nullptr, nullptr)) {
            std::clog << "Could not enable debug privilege: " << GetLastError() << "\n";
            return EXIT_FAILURE;
        }
        std::clog << "Acquired debug privilege\n";
    } else {
        std::clog << "Not acquiring debug privilege\n";
    }

    HANDLE proc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, pid);
    if (proc) {
        std::clog << "Acquired process handle\n";
        CloseHandle(proc);
        return EXIT_SUCCESS;
    } else {
        std::clog << "Failed to acquire process handle: " << GetLastError();
        return EXIT_FAILURE;
    }
}
0

There are 0 answers