Check if the current user is an administrator

  • Gérald Barré

Some action requires the process to run with administrator rights. For instance, if you want to write a key in HKLM or change system settings, or write a file in Program Files. You should avoid doing that if possible, but sometimes you have to do it.

#Check if the current process run as administrator

There are multiple ways to check whether a process runs as administrator:

public bool IsCurrentProcessAdmin()
{
    using var identity = System.Security.Principal.WindowsIdentity.GetCurrent();
    var principal = new System.Security.Principal.WindowsPrincipal(identity);
    return principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
}
[DllImport("shell32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private  static extern bool IsUserAnAdmin();

static bool IsCurrentProcessAdmin()
{
    return IsUserAnAdmin();
}

These methods check if the current process is running as Administrator. They don't check whether the current user is a member of the Administrators group. Indeed, thanks to the User Account Control (UAC), an administrator can run a process without administrator privileges.

Let's understand what UAC does. Then, we'll see how to check whether the current user is a member of the Administrators group.

#User Account Control (UAC) & Access token

When you log on, Windows generates an access token. An access token contains your security information: your identity, your groups, your privileges, etc. When you start a process, the access token is associated to the process. When the process accesses a resource, Windows uses the access token to check whether the process is allowed to access the resource.

When the User Account Control (UAC) is enabled, Windows generate 2 access tokens when you log on. The administrator access token and the standard user access token. The standard user access token removes all dangerous groups and privileges from the token. By default, Windows uses the standard user access token to create a process. This prevent any application to do bad things on your machine without your consent. If you want to use the administrator access token, you need to use the context menu and select the "Run as Administrator" menu item.

Source: How User Account Control works

You can view the access token of a process using Process Explorer. In the following screenshot, the admin token is on the left, the filtered token is on the right. You can see the differences for the BUILTINS\Administrators group.

administrator token on the left, filtered token on the right

In the standard user access token, the group BUILTIN\Administrators has the flag Deny. This means this group is used to check "Deny" rules in ACL. It cannot be used for "Allow" rules. This does means the if you use the standard user access token, the process is not considered as administrator as the group is not enabled.

#Check if the current user is an administrator

Windows exposes an API to query the information of the access token (GetTokenInformation). I've written a .NET library to use this API: Meziantou.Framework.Win32.AccessToken (NuGet package, GitHub)

First, add the NuGet package to your project:

<PackageReference Include="Meziantou.Framework.Win32.AccessToken" Version="1.1.5" />

Then, you can query the access token to check if it's a filtered token:

using var token = AccessToken.OpenCurrentProcessToken(TokenAccessLevels.Query);
var isRestricted = token.GetElevationType() == TokenElevationType.Limited;

It's possible to get the administrator access token (linked token) and check if it contains the BUILTINS\Administrators group:

public static bool IsUserAdministrator()
{
    using var token = AccessToken.OpenCurrentProcessToken(TokenAccessLevels.Query);
    if (!IsAdministrator(token) && token.GetElevationType() == TokenElevationType.Limited)
    {
        using var linkedToken = token.GetLinkedToken();
        return IsAdministrator(linkedToken);
    }

    return false;

    static bool IsAdministrator(AccessToken accessToken)
    {
        var adminSid = SecurityIdentifier.FromWellKnown(WellKnownSidType.WinBuiltinAdministratorsSid);
        foreach (var group in accessToken.EnumerateGroups())
        {
            if (group.Attributes.HasFlag(GroupSidAttributes.SE_GROUP_ENABLED) && group.Sid == adminSid)
                return true;
        }

        return false;
    }
}

#Restart the process as administrator

If the current process is using the standard user access token and you need to use the administrator access token then you need to start a new process. You can indicate the new process should be started with elevated permissions by setting the Verb property of the ProcessStartInfo to runas, as follows:

var args = Environment.GetCommandLineArgs();
var psi = new ProcessStartInfo
{
    FileName = args[0],
    UseShellExecute = true,
    Verb = "runas",         // Indicate to run the process as admin
};

// Copy the arguments of the command line
foreach (var arg in args.Skip(1))
{
    psi.ArgumentList.Add(arg);
}

Process.Start(psi);  // Start the new process
Environment.Exit(0); // Terminate the current process

This will cause Windows to behave as if the process has been started from Explorer with the "Run as Administrator" menu command. This means the UAC prompt will show up and the user needs to consent.

#Use an application manifest to require administrator rights

If your application always need to be run as Administrator you can embed an application manifest in your application.

Add a new file of type "Application Manifest File". This creates a new file named app.manifest. Edit the file to add <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />:

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">

        <!-- 👇 Add this line -->
        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

The user gets the UAC prompt when they start the program.

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?Buy Me A Coffee