确定用户是否可以使用c ++升级进程

时间:2018-05-28 08:47:54

标签: c++ windows winapi privileges

我的应用程序需要一个函数来检查当前用户是否可以提升进程(以Admin身份运行)。函数IsUserAnAdmin()只告诉我进程是否已经提升,但在我的情况下它不是。

是否还有其他选项可以确定用户是否能够提升流程(是管理员)?

2 个答案:

答案 0 :(得分:3)

要检查当前的提升状态,我们可以使用TOKEN_ELEVATION_TYPE查询当前流程的TokenElevationType

  • TokenElevationTypeFull - 我们已经提升了。
  • TokenElevationTypeLimited - 我们在有限的令牌下运行,但是有 提升的链接令牌。这通常是带有交互式的管理员帐户 登录。我们可以在相同用户下提升。
  • TokenElevationTypeDefault - 我们没有链接令牌。这里存在2
    案例:

    1. 我们已经提升(检查此用途 TokenElevation和 从TOKEN_ELEVATION查找TokenIsElevated)如果我们在内置管理员帐户下运行,则可以这样做 (DOMAIN_ALIAS_RID_ADMINS 500)未过滤,或在系统中禁用UAC。

    2. 我们不在管理员帐户下运行。我们 在这种情况下,也可以提升,但仅限于另一个帐户。 为此需要知道此帐户密码

演示代码:

inline ULONG BTE(BOOL f)
{
    return f ? 0 : GetLastError();
}

void TryElevate()
{
    WCHAR path[MAX_PATH];
    if (GetModuleFileNameW(0, path, RTL_NUMBER_OF(path)))
    {
        SHELLEXECUTEINFOW sei = { sizeof(sei), 0, 0, L"runas", path };
        ShellExecuteExW(&sei);
    }
}

ULONG CheckElevation()
{
    HANDLE hToken;
    ULONG err = BTE(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken));
    if (!err)
    {
        ULONG cb = 0, rcb = 0x20;
        union {
            PTOKEN_USER ptu;
            PVOID buf;
        };
        static volatile UCHAR guz;
        PVOID stack = alloca(guz);
        PWSTR SzSid = 0;

        //++ for display user sid only
        do 
        {
            if (cb < rcb)
            {
                cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
            }

            if (!(err = BTE(GetTokenInformation(hToken, ::TokenUser, buf, cb, &rcb))))
            {
                ConvertSidToStringSidW(ptu->User.Sid, &SzSid);
                break;
            }

        } while (err == ERROR_INSUFFICIENT_BUFFER);
        // -- for display user sid only

        union {
            TOKEN_ELEVATION te;
            TOKEN_ELEVATION_TYPE tet;
        };

        if (!(err = BTE(GetTokenInformation(hToken, ::TokenElevationType, &tet, sizeof(tet), &rcb))))
        {
            switch (tet)
            {
            case TokenElevationTypeDefault:
                if (!(err = BTE(GetTokenInformation(hToken, ::TokenElevation, &te, sizeof(te), &rcb))))
                {
                    if (te.TokenIsElevated)
                    {
                        // we are built-in admin or UAC is disabled in system
            case TokenElevationTypeFull:
                MessageBoxW(HWND_DESKTOP, L"we run elevated", SzSid, MB_ICONINFORMATION);
                break;
                    }

                    // we can not elevate under same user, but still can elevate under another admin account
                    // non admin account
                    TryElevate();
                    MessageBoxW(HWND_DESKTOP, L"Default", SzSid, MB_ICONINFORMATION);
                }

                break;


            case TokenElevationTypeLimited:
                // this mean that we have linked token, which is elevated. we can elevate under same user
                TryElevate();
                MessageBoxW(HWND_DESKTOP, L"Limited", SzSid, MB_ICONINFORMATION);
                break;

            default:
                MessageBoxW(HWND_DESKTOP, L"unknown elevation type", SzSid, MB_ICONWARNING);
                err = ERROR_GEN_FAILURE;
            }
        }

        if (SzSid) LocalFree(SzSid);

        CloseHandle(hToken);
    }

    return err;
}

和结果:

enter image description here

答案 1 :(得分:0)

利用@RbMm评论的帮助,我创建了以下函数来确定是否可以提升进程。 (没有密码)

bool IsElevationPossible()
{
    TOKEN_ELEVATION_TYPE tokenElevationType;
    DWORD size;
    if (!GetTokenInformation(
        GetCurrentProcessToken(),
        TokenElevationType,
        &tokenElevationType,
        sizeof(tokenElevationType),
        &size))
        {
        // Log Error

        return false;
    }

    return tokenElevationType == TokenElevationTypeLimited;
}