如何检查不是 "self" 的进程的组成员资格?

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

我正在尝试使用 this code 检查我有句柄的任意进程的安全组成员身份。但是在我下面的代码中 CheckTokenMembership 失败,错误代码为 1309,或 ERROR_NO_IMPERSONATION_TOKEN。我不确定我是否了解如何获得该模拟令牌...

那么我做错了什么?

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;
    }

}

MSDN 确实确认这是一项要求:

The token must be an impersonation token.

它还针对 NULL 句柄情况说:

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.

你可以试试这个:

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