plong
plong

Reputation: 1753

How do I disable privileges for a process?

Ultimately, I want to spawn a C executable from a Node app that drops all but the necessary privileges for its parent, the Node process itself. My current problem, however, is simply having one process disable all privileges for another process. Here's the program that's supposed to do that, passing in the pid on the command line:

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>

void print_privileges(HANDLE hToken)
{
    DWORD size;
    if (!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &size) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
        PTOKEN_PRIVILEGES tp = malloc(size);
        if (tp != NULL && GetTokenInformation(hToken, TokenPrivileges, tp, size, &size)) {
            size_t i;
            for (i = 0; i < tp->PrivilegeCount; ++i) {
                char name[64] = "?";
                size_t name_size = sizeof name;
                LookupPrivilegeNameA(0, &tp->Privileges[i].Luid, name, &name_size);
                PRIVILEGE_SET ps = {
                    1, PRIVILEGE_SET_ALL_NECESSARY, {
                        { { tp->Privileges[i].Luid.LowPart, tp->Privileges[i].Luid.HighPart } }
                    }
                };
                BOOL fResult;
                PrivilegeCheck(hToken, &ps, &fResult);
                printf("%-*s %s\n", 32, name, fResult ? "Enabled" : "Disabled");
            }
        }
        free(tp);
    }
}

int disable_all_privileges(DWORD pid)
{
    int ret = 1;
    const HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pid);
    if (hProcess) {
        HANDLE hToken;
        if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
            ULONG return_length;
            TOKEN_LINKED_TOKEN tlk;
            if (GetTokenInformation(hToken, TokenLinkedToken, &tlk, sizeof tlk, &return_length)) {
                CloseHandle(hToken);
                hToken = tlk.LinkedToken;
                puts("\nBefore:");
                print_privileges(hToken);
                /* Disable all privileges. */
                if (AdjustTokenPrivileges(hToken, TRUE, 0, 0, 0, 0) || GetLastError() != NOERROR) {
                    puts("\nAfter:");
                    print_privileges(hToken);
                    ret = 0;
                }
            }
            CloseHandle(hToken);
        }
    }
    return ret;
}

void print_process_info(DWORD pid)
{
    const HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnapshot != INVALID_HANDLE_VALUE) {
        PROCESSENTRY32 pe32 = { .dwSize = sizeof pe32 };
        BOOL ok;
        for (ok = Process32First(hSnapshot, &pe32); ok; ok = Process32Next(hSnapshot, &pe32))
            if (pe32.th32ProcessID == pid) {
                puts("Process info:");
                printf("dwSize: %lu\n", pe32.dwSize);
                printf("th32ProcessID: %lu\n", pe32.th32ProcessID);
                printf("cntThreads: %lu\n", pe32.cntThreads);
                printf("th32ParentProcessID: %lu\n", pe32.th32ParentProcessID);
                printf("pcPriClassBase: %ld\n", pe32.pcPriClassBase);
                wprintf(L"szExeFile: %s\n", pe32.szExeFile);
                break;
            }
        CloseHandle(hSnapshot);
    }
}

int main(int argc, char* argv[])
{
    int ret = 1;
    if (argc > 1) {
        DWORD pid;
        if (sscanf_s(argv[1], "%u", &pid) == 1) {
            print_process_info(pid);
            ret = disable_all_privileges(pid);
        }
    }
    return ret;
}

Below, I am trying to disable the privileges for the same Administrator cmd window from which I am running my program (I've tried different variations of this, e.g., changing the privileges of another cmd process). As you can see from the console output, below, the first problem is that the privileges enumerated by my dispriv.exe program do not match the privileges listed by the whoami /priv command. Can someone explain exactly what's going on here? I assume that's due to some difference between user privileges versus process privileges. Do I just ignore the whoami /priv output because it does not reflect what I'm interested in, the process privileges?

The second problem is that the privileges that I thought I had successfully disabled when I first ran dispriv.exe are once again enabled when I run it again (you can see, below, that I run the program twice in a row). Why is that? Were my privilege changes somehow not "committed" in order to be persistent across runs?

The final problem is that my program does not affect the privileges displayed by whoami /priv. Specifically, SeChangeNotifyPrivilege is marked Enabled before and after I run my dispriv.exe program. Further evidence that I have an apples-and-oranges situation here. Can you help clarify what's going on?

C:\WINDOWS\system32>whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                  Description                               State
=============================== ========================================= ========
SeIncreaseQuotaPrivilege        Adjust memory quotas for a process        Disabled
SeSecurityPrivilege             Manage auditing and security log          Disabled
SeTakeOwnershipPrivilege        Take ownership of files or other objects  Disabled
SeLoadDriverPrivilege           Load and unload device drivers            Disabled
SeSystemProfilePrivilege        Profile system performance                Disabled
SeSystemtimePrivilege           Change the system time                    Disabled
SeProfileSingleProcessPrivilege Profile single process                    Disabled
SeIncreaseBasePriorityPrivilege Increase scheduling priority              Disabled
SeCreatePagefilePrivilege       Create a pagefile                         Disabled
SeBackupPrivilege               Back up files and directories             Disabled
SeRestorePrivilege              Restore files and directories             Disabled
SeShutdownPrivilege             Shut down the system                      Disabled
SeDebugPrivilege                Debug programs                            Disabled
SeSystemEnvironmentPrivilege    Modify firmware environment values        Disabled
SeChangeNotifyPrivilege         Bypass traverse checking                  Enabled
SeRemoteShutdownPrivilege       Force shutdown from a remote system       Disabled
SeUndockPrivilege               Remove computer from docking station      Disabled
SeManageVolumePrivilege         Perform volume maintenance tasks          Disabled
SeImpersonatePrivilege          Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege         Create global objects                     Enabled
SeIncreaseWorkingSetPrivilege   Increase a process working set            Disabled
SeTimeZonePrivilege             Change the time zone                      Disabled
SeCreateSymbolicLinkPrivilege   Create symbolic links                     Disabled

C:\WINDOWS\system32>tasklist /v /fo csv | findstr /i admincmd
"cmd.exe","2344","Console","9","4,168 K","Running","ENIGMA\plong","0:00:00","Administrator:  admincmd"

C:\WINDOWS\system32>\Users\plong\source\repos\Permissions\Debug\dispriv.exe 2344
Process info:
dwSize: 556
th32ProcessID: 2344
cntThreads: 2
th32ParentProcessID: 15664
pcPriClassBase: 8
szExeFile: cmd.exe

Before:
SeShutdownPrivilege              Disabled
SeChangeNotifyPrivilege          Enabled
SeUndockPrivilege                Disabled
SeIncreaseWorkingSetPrivilege    Disabled
SeTimeZonePrivilege              Disabled

After:
SeShutdownPrivilege              Disabled
SeChangeNotifyPrivilege          Disabled
SeUndockPrivilege                Disabled
SeIncreaseWorkingSetPrivilege    Disabled
SeTimeZonePrivilege              Disabled

C:\WINDOWS\system32>\Users\plong\source\repos\Permissions\Debug\dispriv.exe 2344
Process info:
dwSize: 556
th32ProcessID: 2344
cntThreads: 2
th32ParentProcessID: 15664
pcPriClassBase: 8
szExeFile: cmd.exe

Before:
SeShutdownPrivilege              Disabled
SeChangeNotifyPrivilege          Enabled
SeUndockPrivilege                Disabled
SeIncreaseWorkingSetPrivilege    Disabled
SeTimeZonePrivilege              Disabled

After:
SeShutdownPrivilege              Disabled
SeChangeNotifyPrivilege          Disabled
SeUndockPrivilege                Disabled
SeIncreaseWorkingSetPrivilege    Disabled
SeTimeZonePrivilege              Disabled

C:\WINDOWS\system32>whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                  Description                               State
=============================== ========================================= ========
SeIncreaseQuotaPrivilege        Adjust memory quotas for a process        Disabled
SeSecurityPrivilege             Manage auditing and security log          Disabled
SeTakeOwnershipPrivilege        Take ownership of files or other objects  Disabled
SeLoadDriverPrivilege           Load and unload device drivers            Disabled
SeSystemProfilePrivilege        Profile system performance                Disabled
SeSystemtimePrivilege           Change the system time                    Disabled
SeProfileSingleProcessPrivilege Profile single process                    Disabled
SeIncreaseBasePriorityPrivilege Increase scheduling priority              Disabled
SeCreatePagefilePrivilege       Create a pagefile                         Disabled
SeBackupPrivilege               Back up files and directories             Disabled
SeRestorePrivilege              Restore files and directories             Disabled
SeShutdownPrivilege             Shut down the system                      Disabled
SeDebugPrivilege                Debug programs                            Disabled
SeSystemEnvironmentPrivilege    Modify firmware environment values        Disabled
SeChangeNotifyPrivilege         Bypass traverse checking                  Enabled
SeRemoteShutdownPrivilege       Force shutdown from a remote system       Disabled
SeUndockPrivilege               Remove computer from docking station      Disabled
SeManageVolumePrivilege         Perform volume maintenance tasks          Disabled
SeImpersonatePrivilege          Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege         Create global objects                     Enabled
SeIncreaseWorkingSetPrivilege   Increase a process working set            Disabled
SeTimeZonePrivilege             Change the time zone                      Disabled
SeCreateSymbolicLinkPrivilege   Create symbolic links                     Disabled

C:\WINDOWS\system32>

Upvotes: 0

Views: 1745

Answers (2)

Drake Wu
Drake Wu

Reputation: 7170

As the comment said, you are executing your own dispriv.exe process in an elevated cmd.exe. The first whoami /priv lists the elevated privileges of cmd.exe. Then you disable the link token(not elevated) privilege of the dispriv.exe process. This will not affect the privileg of cmd.exe.

You need to use the token of cmd.exe, and use its own token instead of the linked token.(For access tokens, you can refer to How User Account Control works about standard user access token and administrator access token):

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>

void print_privileges(HANDLE hToken)
{
    DWORD size = 0;
    if (!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &size) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
        PTOKEN_PRIVILEGES tp = (PTOKEN_PRIVILEGES)malloc(size);
        if (tp != NULL && GetTokenInformation(hToken, TokenPrivileges, tp, size, &size)) {
            size_t i;
            for (i = 0; i < tp->PrivilegeCount; ++i) {
                char name[64] = "?";
                DWORD name_size = sizeof name;
                LookupPrivilegeNameA(0, &tp->Privileges[i].Luid, name, &name_size);
                PRIVILEGE_SET ps = {
                    1, PRIVILEGE_SET_ALL_NECESSARY, {
                        { { tp->Privileges[i].Luid.LowPart, tp->Privileges[i].Luid.HighPart } }
                    }
                };
                BOOL fResult;
                PrivilegeCheck(hToken, &ps, &fResult);
                printf("%-*s %s\n", 32, name, fResult ? "Enabled" : "Disabled");
            }
        }
        free(tp);
    }
}
int disable_all_privileges(DWORD pid)
{
    int ret = 1;
    const HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pid);
    if (hProcess) {
        HANDLE hToken;
        if (OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
            ULONG return_length;
            TOKEN_LINKED_TOKEN tlk;
            puts("\nBefore:");
            print_privileges(hToken);

            /* Disable all privileges. */
            if (AdjustTokenPrivileges(hToken, TRUE, 0, 0, 0, 0) || GetLastError() != NOERROR) {
                puts("\nAfter:");
                print_privileges(hToken);
                ret = 0;
            }
            CloseHandle(hToken);
        }
    }
    return ret;
}

void print_process_info(DWORD pid)
{
    const HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnapshot != INVALID_HANDLE_VALUE) {
        PROCESSENTRY32 pe32 = { pe32.dwSize = sizeof pe32 };
        BOOL ok;
        for (ok = Process32First(hSnapshot, &pe32); ok; ok = Process32Next(hSnapshot, &pe32))
            if (pe32.th32ProcessID == pid) {
                puts("Process info:");
                printf("dwSize: %lu\n", pe32.dwSize);
                printf("th32ProcessID: %lu\n", pe32.th32ProcessID);
                printf("cntThreads: %lu\n", pe32.cntThreads);
                printf("th32ParentProcessID: %lu\n", pe32.th32ParentProcessID);
                printf("pcPriClassBase: %ld\n", pe32.pcPriClassBase);
                wprintf(L"szExeFile: %s\n", pe32.szExeFile);
                break;
            }
        CloseHandle(hSnapshot);
    }
}

int main(int argc, char* argv[])
{
    int ret = 1;
    if (argc > 1) {
        DWORD pid;
        if (sscanf_s(argv[1], "%u", &pid) == 1) {
            print_process_info(pid);
            ret = disable_all_privileges(pid);
        }
    }
    return ret;
}

Result:

C:\Users\path>whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                            Description                                                        State
========================================= ================================================================== ========
SeMachineAccountPrivilege                 Add workstations to domain                                         Disabled
SeSecurityPrivilege                       Manage auditing and security log                                   Disabled
SeTakeOwnershipPrivilege                  Take ownership of files or other objects                           Disabled
SeLoadDriverPrivilege                     Load and unload device drivers                                     Disabled
SeSystemProfilePrivilege                  Profile system performance                                         Disabled
SeSystemtimePrivilege                     Change the system time                                             Disabled
SeProfileSingleProcessPrivilege           Profile single process                                             Disabled
SeIncreaseBasePriorityPrivilege           Increase scheduling priority                                       Disabled
SeCreatePagefilePrivilege                 Create a pagefile                                                  Disabled
SeBackupPrivilege                         Back up files and directories                                      Disabled
SeRestorePrivilege                        Restore files and directories                                      Disabled
SeShutdownPrivilege                       Shut down the system                                               Disabled
SeDebugPrivilege                          Debug programs                                                     Disabled
SeSystemEnvironmentPrivilege              Modify firmware environment values                                 Disabled
SeChangeNotifyPrivilege                   Bypass traverse checking                                           Enabled
SeRemoteShutdownPrivilege                 Force shutdown from a remote system                                Disabled
SeUndockPrivilege                         Remove computer from docking station                               Disabled
SeManageVolumePrivilege                   Perform volume maintenance tasks                                   Disabled
SeImpersonatePrivilege                    Impersonate a client after authentication                          Enabled
SeCreateGlobalPrivilege                   Create global objects                                              Enabled
SeIncreaseWorkingSetPrivilege             Increase a process working set                                     Disabled
SeTimeZonePrivilege                       Change the time zone                                               Disabled
SeCreateSymbolicLinkPrivilege             Create symbolic links                                              Disabled
SeDelegateSessionUserImpersonatePrivilege Obtain an impersonation token for another user in the same session Disabled

C:\Users\path>tasklist /v /fo csv | findstr /i "Command Prompt"
"cmd.exe","11244","Console","1","4,764 K","Running","domain\user","0:00:00","Administrator: Command Prompt"

C:\Users\path>dispriv.exe 11244
Process info:
dwSize: 296
th32ProcessID: 11244
cntThreads: 1
th32ParentProcessID: 6208
pcPriClassBase: 8
szExeFile: cmd.exe

Before:
SeMachineAccountPrivilege        Disabled
SeSecurityPrivilege              Disabled
SeTakeOwnershipPrivilege         Disabled
SeLoadDriverPrivilege            Disabled
SeSystemProfilePrivilege         Disabled
SeSystemtimePrivilege            Disabled
SeProfileSingleProcessPrivilege  Disabled
SeIncreaseBasePriorityPrivilege  Disabled
SeCreatePagefilePrivilege        Disabled
SeBackupPrivilege                Disabled
SeRestorePrivilege               Disabled
SeShutdownPrivilege              Disabled
SeDebugPrivilege                 Disabled
SeSystemEnvironmentPrivilege     Disabled
SeChangeNotifyPrivilege          Enabled
SeRemoteShutdownPrivilege        Disabled
SeUndockPrivilege                Disabled
SeManageVolumePrivilege          Disabled
SeImpersonatePrivilege           Enabled
SeCreateGlobalPrivilege          Enabled
SeIncreaseWorkingSetPrivilege    Disabled
SeTimeZonePrivilege              Disabled
SeCreateSymbolicLinkPrivilege    Disabled
SeDelegateSessionUserImpersonatePrivilege Disabled

After:
SeMachineAccountPrivilege        Disabled
SeSecurityPrivilege              Disabled
SeTakeOwnershipPrivilege         Disabled
SeLoadDriverPrivilege            Disabled
SeSystemProfilePrivilege         Disabled
SeSystemtimePrivilege            Disabled
SeProfileSingleProcessPrivilege  Disabled
SeIncreaseBasePriorityPrivilege  Disabled
SeCreatePagefilePrivilege        Disabled
SeBackupPrivilege                Disabled
SeRestorePrivilege               Disabled
SeShutdownPrivilege              Disabled
SeDebugPrivilege                 Disabled
SeSystemEnvironmentPrivilege     Disabled
SeChangeNotifyPrivilege          Disabled
SeRemoteShutdownPrivilege        Disabled
SeUndockPrivilege                Disabled
SeManageVolumePrivilege          Disabled
SeImpersonatePrivilege           Disabled
SeCreateGlobalPrivilege          Disabled
SeIncreaseWorkingSetPrivilege    Disabled
SeTimeZonePrivilege              Disabled
SeCreateSymbolicLinkPrivilege    Disabled
SeDelegateSessionUserImpersonatePrivilege Disabled

C:\Users\path>whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                            Description                                                        State
========================================= ================================================================== ========
SeMachineAccountPrivilege                 Add workstations to domain                                         Disabled
SeSecurityPrivilege                       Manage auditing and security log                                   Disabled
SeTakeOwnershipPrivilege                  Take ownership of files or other objects                           Disabled
SeLoadDriverPrivilege                     Load and unload device drivers                                     Disabled
SeSystemProfilePrivilege                  Profile system performance                                         Disabled
SeSystemtimePrivilege                     Change the system time                                             Disabled
SeProfileSingleProcessPrivilege           Profile single process                                             Disabled
SeIncreaseBasePriorityPrivilege           Increase scheduling priority                                       Disabled
SeCreatePagefilePrivilege                 Create a pagefile                                                  Disabled
SeBackupPrivilege                         Back up files and directories                                      Disabled
SeRestorePrivilege                        Restore files and directories                                      Disabled
SeShutdownPrivilege                       Shut down the system                                               Disabled
SeDebugPrivilege                          Debug programs                                                     Disabled
SeSystemEnvironmentPrivilege              Modify firmware environment values                                 Disabled
SeChangeNotifyPrivilege                   Bypass traverse checking                                           Disabled
SeRemoteShutdownPrivilege                 Force shutdown from a remote system                                Disabled
SeUndockPrivilege                         Remove computer from docking station                               Disabled
SeManageVolumePrivilege                   Perform volume maintenance tasks                                   Disabled
SeImpersonatePrivilege                    Impersonate a client after authentication                          Disabled
SeCreateGlobalPrivilege                   Create global objects                                              Disabled
SeIncreaseWorkingSetPrivilege             Increase a process working set                                     Disabled
SeTimeZonePrivilege                       Change the time zone                                               Disabled
SeCreateSymbolicLinkPrivilege             Create symbolic links                                              Disabled
SeDelegateSessionUserImpersonatePrivilege Obtain an impersonation token for another user in the same session Disabled

C:\Users\path>

Upvotes: 1

SoronelHaetir
SoronelHaetir

Reputation: 15164

Take a look at the CreateRestrictedToken and CreateProcessAsUser functions.

The first allows you to create an access token that is a restricted version of an existing token (most likely obtained via GetCurrentProcessToken or GetCurrentThreadToken and the second allows you to create a process using a specified access token (rather than the current process' existing primary access token). Note that if you use a thread token you may need to use DuplicateHandle to convert an impersonation token into a primary access token.

Upvotes: 1

Related Questions