6

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;
    }
}
Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • 1
    Sadly, there's doesn't seem to be much official documentation on what the various privileges actually do, so I can't provide a reference. But what debug privilege actually does is to bypass process permissions, in the same way that backup and restore privilege allow you to bypass file permissions. So if you have debug privilege enabled, you can open any unprotected process with any valid access mask. – Harry Johnston Dec 16 '16 at 23:15
  • 1
    ... so that explains that part, and suggests that the reason you're failing to open the processes is that the ACL on the process won't let you do so. Since you can enable debug privilege, the application must be running elevated, so it *should* have access via the Administrators group. My best guess is that the ACL on the service is unusually restrictive, but I have no idea why. You can use Process Explorer to verify this; open the process in question, go to the Security tab and hit the Permissions button. You'll probably need to dig a bit to find the Show Advanced Permissions option. – Harry Johnston Dec 16 '16 at 23:20
  • I hadn't thought of checking permissions on the running service like that. Thanks. However, there product has a half-dozen services, and only two of them exhibit this problem. I'm *pretty sure* they're all configured the same, but I might learn otherwise. – Rob Kennedy Dec 16 '16 at 23:46
  • The only other possibility I can think of is the usual one: anti-virus. – Harry Johnston Dec 16 '16 at 23:47
  • The inaccessible processes have only "special permissions" allowed for members of the Administrators group, and "query limited information" isn't among them. The accessible processes also have only "special permissions" allowed for that group, but "query limited information" *is* included. So I think I may have found the smoking gun. (Now I investigate who fired it.) – Rob Kennedy Dec 19 '16 at 18:54

0 Answers0