c00000fd
c00000fd

Reputation: 22255

How to check group membership for a process that is not "self"?

I'm trying to use this code to check security group membership for an arbitrary process that I have a handle for. But in my code below CheckTokenMembership fails with error code 1309, or ERROR_NO_IMPERSONATION_TOKEN. I'm not sure I understand how I can get that impersonation token...

So what am I doing wrong here?

void check_membership(HANDLE hProc)
{
    HANDLE hToken;
    if(OpenProcessToken(hProc, TOKEN_QUERY, &hToken))
    {
        check_group_membership(hToken, L"Local Group", DOMAIN_ALIAS_RID_USERS);
        check_group_membership(hToken, L"Admin Group", DOMAIN_ALIAS_RID_ADMINS);
        check_group_membership(hToken, L"Domain Admin Group", DOMAIN_GROUP_RID_ADMINS);
        check_group_membership(hToken, L"Schema Admin Group", DOMAIN_GROUP_RID_SCHEMA_ADMINS);
        check_group_membership(hToken, L"Enterprise Admin Group", DOMAIN_GROUP_RID_ENTERPRISE_ADMINS);

        CloseHandle(hToken);
    }
}


void check_group_membership(HANDLE hToken, LPCTSTR pStrName, DWORD nSubauthority)
{
    BOOL bIsMember;
    SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;

    wprintf(L"Local %s: ", pStrName);

    PSID pSID = NULL; 
    if(AllocateAndInitializeSid(&NtAuthority, 2,
        SECURITY_BUILTIN_DOMAIN_RID,
        nSubauthority,
        0, 0, 0, 0, 0, 0, &pSID))
    {
        bIsMember = FALSE;
        if(CheckTokenMembership(hToken, pSID, &bIsMember))
        {
            wprintf(L"%s", bIsMember ? L"Yes" : L"No");
        }
        else
        {
            wprintf(L"<CheckErr: (%d)>", GetLastError());
        }
    }
    else
    {
        wprintf(L"<SidErr: (%d)>", GetLastError());
    }

    wprintf(L"\n");

    if(pSID)
    {
        FreeSid(pSID) == NULL);
        pSID = NULL;
    }

}

Upvotes: 1

Views: 726

Answers (1)

Anders
Anders

Reputation: 101616

MSDN does confirm that it is a requirement:

The token must be an impersonation token.

It also says for the NULL handle case:

CheckTokenMembership uses the impersonation token of the calling thread. If the thread is not impersonating, the function duplicates the thread's primary token to create an impersonation token.

You could try this:

HANDLE hImpToken;
if (DuplicateTokenEx(hToken, TOKEN_QUERY, NULL, SecurityImpersonation, TokenImpersonation, &hImpToken))
{
    CheckTokenMembership(hImpToken, ...);
    CloseHandle(hImpToken);
}

Upvotes: 3

Related Questions