October 3rd, 2024

How can I detect whether the user is running as an elevated administrator (as opposed to a natural administrator)?

When a user with administrator privileges signs in, the User Account Control (UAC) feature signs in the administrator with a so-called “split token”, in which the user operates in Clark Kent mode: Although they have latent administrator privileges, the administrative powers in the token are disabled. To exercise those administrative powers, the user must elevate their token.

A customer wanted to discourage users from running their program elevated, but they also didn’t want to scold users who were running with UAC disabled (such as on Windows Server), since those users had no opportunity to de-elevate.

The way to inspect whether your token is split, and if so whether you have the non-administrator (“limited”) version or the administrator (“full”) version is to ask for the token’s elevation type.

  Standard user Administrative user
UAC disabled TokenElevationTypeDefault TokenElevationTypeDefault
UAC enabled, not elevated TokenElevationTypeDefault TokenElevationTypeLimited
UAC enabled, elevated N/A TokenElevationTypeFull

Non-administrative users cannot split their token (there being no administrator privileges to split out), and administrative users cannot split their tokens if UAC is disabled.

If you are looking for “users who manually elevated”, then you can consult the table above and see that a token elevation type of Full exactly identifies the “Administrative user, UAC enabled, elevated” box.

bool IsManuallyElevatedViaUAC()
{
    TOKEN_ELEVATION_TYPE type;
    DWORD actual;
    if (!GetTokenInformation(
            GetCurrentProcessToken(),
            TokenElevationType,
            &type,
            sizeof(type),
            &actual)) {
        // insert your favorite error handling here
        throw_error(GetLastError());
    }
    return type == TokenElevationTypeFull;
}

We learned about Get­Current­Process­Token() a little while ago. This is a convenient pseudo-handle that refers to the current process. We ask for the current process’s token’s elevation type, and if that is Full, then we are in that box in the bottom right corner.

The helpers in the token_helpers.h header in the Windows Implementation Library (wil) turn this into a one-line function.

bool IsManuallyElevatedViaUAC()
{
    return wil::get_token_information<TOKEN_ELEVATION_TYPE>(
            GetCurrentProcessToken()) == TokenElevationTypeFull;
}
Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

6 comments

  • skSdnW 1 day ago

    The title of this post is slightly misleading because this code checks how the token was born, not if it’s elevated. You can make a Full elevated token with a lower integrity level. To actually check for elevation, you need TokenIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID.

    • Harry Johnston 5 hours ago

      What's more, if what you really want to know is whether the token has administrative privileges, checking the integrity level doesn't work either. :-)

      https://stackoverflow.com/a/30970434/886887

      Which I guess just goes to show that you need to know why you're asking in order to know what the right question is. (In this scenario, "A customer wanted to discourage users from running their program elevated", I'd argue that you probably don't need to worry too much about the...

      Read more
  • Harry Johnston 2 days ago

    The other case is when you are signed in as a standard user but elevated using explicit administrative credentials. I’m not sure what the token elevation type is in this case, it might not be as easy to detect.

    • GL

      My guess is that it’s TokenElevationTypeDefault if UAC disabled, and TokenElevationTypeFull if UAC enabled. That is, the same as when the administrator is elevated (or always-elevated).

      • GL 21 hours ago

        Re: Can you elevate with UAC disabled?

        Yes. I have UAC disabled on my daily driver computer and use 2 separate accounts and elevate by entering the credential. If the policy is set to deny elevation for limited users, there might be a problem, but I would expect one could always “runasuser” (Run as different user).

      • Neil Rashbrook 1 day ago

        If UAC is disabled, do you even get the opportunity to elevate?