如何确定用户是否是来自Win32的非特权应用程序的管理员?

时间:2017-11-07 08:16:24

标签: windows winapi administrator elevated-privileges

从非特权应用程序我想运行特权应用程序。但是我想在启动应用程序之前检查用户是否是管理员。

Win32提供IsUserAnAdmin()IsUserAdmin()但如果从非特权进程调用,则这两个都将返回0。这是因为它真正在做的是询问该进程是否具有管理访问权限,而不是用户是\ Administrators组的成员。

是否可以确定用户是否是来自非特权进程的管理员组的成员?

有一些类似的问题,但这不是重复。具体来说,我想知道USER是否属于组,而不是PROCESS是否继承了管理权限;如果可以使用Win32(而不是.NET)完成。

2 个答案:

答案 0 :(得分:1)

如果您拥有用户令牌的句柄(来自OpenProcessToken等),您可以执行经典的管理员检查,忽略"仅拒绝" groups:致电GetTokenInformation(..., TokenGroups, ...)并查找管理员组SID。

如果您只有用户名/ SID,则可以使用NetUserGetLocalGroupsNetLocalGroupGetMembers

答案 1 :(得分:0)

首先需要检查您的令牌TOKEN_ELEVATION_TYPE

如果您有 TokenElevationTypeDefault TokenElevationTypeFull - 您无法在此用户帐户下提升和最大化令牌。对于查询,令牌是管理员,或者您是否拥有某些权限 - 需要按原样查询当前令牌。

如果您有 TokenElevationTypeLimited - 您需要通过TokenLinkedToken查询链接令牌并检查此链接令牌而不是您当前的令牌 - 因为在提升特权应用程序之后将使用此令牌。

例如:

ULONG IsTokenAdmin(HANDLE hToken, PBOOL pbIsAdmin)
{
    ULONG cbSid = MAX_SID_SIZE;
    PSID pSid = alloca(cbSid);
    return CreateWellKnownSid(::WinBuiltinAdministratorsSid, 0, pSid, &cbSid) &&
        CheckTokenMembership(hToken, pSid, pbIsAdmin) ? NOERROR :  GetLastError();
}

ULONG IsUserAnAdminEx(PBOOL pbIsAdmin, PBOOL pbNeedElevate)
{
    ULONG dwError = NOERROR;

    HANDLE hToken;
    if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_DUPLICATE, &hToken))
    {
        ULONG cb;
        union {
            TOKEN_ELEVATION_TYPE tet;
            TOKEN_LINKED_TOKEN tlt;
        };

        if (GetTokenInformation(hToken, ::TokenElevationType, &tet, sizeof(tet), &cb))
        {
            switch (tet)
            {
            case TokenElevationTypeLimited:
                *pbNeedElevate = TRUE;
                if (GetTokenInformation(hToken, ::TokenLinkedToken, &tlt, sizeof(tlt), &cb))
                {
                    dwError = IsTokenAdmin(tlt.LinkedToken, pbIsAdmin);
                    CloseHandle(tlt.LinkedToken);
                }
                else
                {
                    dwError = GetLastError();
                }
                break;
            case TokenElevationTypeFull:
            case TokenElevationTypeDefault:
                *pbNeedElevate = FALSE;
                // only because CheckTokenMembership want an impersonation token.
                // really most query can be and must be done direct with this token
                if (DuplicateToken(hToken, ::SecurityIdentification, &tlt.LinkedToken))
                {
                    dwError = IsTokenAdmin(tlt.LinkedToken, pbIsAdmin);
                    CloseHandle(tlt.LinkedToken);
                }
                else
                {
                    GetLastError();
                }
                break;
            default:
                dwError = ERROR_GEN_FAILURE;
            }
        }
        else
        {
            dwError = GetLastError();
        }

        CloseHandle(hToken);
    }

    return dwError;
}