检测是否以管理员身份运行,是否具有提升权限?

Mif*_*Fox 74 .net c# uac user-accounts windows-vista

我有一个应用程序需要检测它是否以提升的权限运行.我目前的代码设置如下:

static bool IsAdministrator()
{
    WindowsIdentity identity = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(identity);
    return principal.IsInRole (WindowsBuiltInRole.Administrator);
}
Run Code Online (Sandbox Code Playgroud)

这可以检测用户是否是管理员,但如果以没有提升的管理员身份运行则不起作用.(例如在vshost.exe中).

如何判断高程是否[已经生效或]可能

Ste*_*ven 54

试试这个:

using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Principal;

public static class UacHelper
{
    private const string uacRegistryKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
    private const string uacRegistryValue = "EnableLUA";

    private static uint STANDARD_RIGHTS_READ = 0x00020000;
    private static uint TOKEN_QUERY = 0x0008;
    private static uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);

    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength, out uint ReturnLength);

    public enum TOKEN_INFORMATION_CLASS
    {
        TokenUser = 1,
        TokenGroups,
        TokenPrivileges,
        TokenOwner,
        TokenPrimaryGroup,
        TokenDefaultDacl,
        TokenSource,
        TokenType,
        TokenImpersonationLevel,
        TokenStatistics,
        TokenRestrictedSids,
        TokenSessionId,
        TokenGroupsAndPrivileges,
        TokenSessionReference,
        TokenSandBoxInert,
        TokenAuditPolicy,
        TokenOrigin,
        TokenElevationType,
        TokenLinkedToken,
        TokenElevation,
        TokenHasRestrictions,
        TokenAccessInformation,
        TokenVirtualizationAllowed,
        TokenVirtualizationEnabled,
        TokenIntegrityLevel,
        TokenUIAccess,
        TokenMandatoryPolicy,
        TokenLogonSid,
        MaxTokenInfoClass
    }

    public enum TOKEN_ELEVATION_TYPE
    {
        TokenElevationTypeDefault = 1,
        TokenElevationTypeFull,
        TokenElevationTypeLimited
    }

    public static bool IsUacEnabled
    {
        get
        {
            RegistryKey uacKey = Registry.LocalMachine.OpenSubKey(uacRegistryKey, false);
            bool result = uacKey.GetValue(uacRegistryValue).Equals(1);
            return result;
        }
    }

    public static bool IsProcessElevated
    {
        get
        {
            if (IsUacEnabled)
            {
                IntPtr tokenHandle;
                if (!OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_READ, out tokenHandle))
                {
                    throw new ApplicationException("Could not get process token.  Win32 Error Code: " + Marshal.GetLastWin32Error());
                }

                TOKEN_ELEVATION_TYPE elevationResult = TOKEN_ELEVATION_TYPE.TokenElevationTypeDefault;

                int elevationResultSize = Marshal.SizeOf((int)elevationResult);
                uint returnedSize = 0;
                IntPtr elevationTypePtr = Marshal.AllocHGlobal(elevationResultSize);

                bool success = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevationType, elevationTypePtr, (uint)elevationResultSize, out returnedSize);
                if (success)
                {
                    elevationResult = (TOKEN_ELEVATION_TYPE)Marshal.ReadInt32(elevationTypePtr);
                    bool isProcessAdmin = elevationResult == TOKEN_ELEVATION_TYPE.TokenElevationTypeFull;
                    return isProcessAdmin;
                }
                else
                {
                    throw new ApplicationException("Unable to determine the current elevation.");
                }
            }
            else
            {
                WindowsIdentity identity = WindowsIdentity.GetCurrent();
                WindowsPrincipal principal = new WindowsPrincipal(identity);
                bool result = principal.IsInRole(WindowsBuiltInRole.Administrator);
                return result;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 如果要以本地管理员身份运行的帐户,但如果您使用域管理员,则变量isProcessAdmin返回false.但UAC在提升权限时接受域管理员是有效的(在Windows中创建文件夹,以管理员身份运行等)...我如何修改您的功能以便它也考虑到这种情况? (8认同)
  • 此代码需要以下using语句:using System.Diagnostics; 使用System.Runtime.InteropServices; 使用System.Security.Principal; 它似乎也反映在这[.](http://www.sadrobot.co.nz/2011/06/20/how-to-check-if-the-current-user-is-an-administrator-even -if-UAC-是开/) (2认同)

Jep*_*sen 30

(提出问题六年后的新答案)

免责声明:这只是在我的特定操作系统上使用我的特定用户的特定设置时发生的事情:

using System.Security.Principal;

// ...

    static bool IsElevated
    {
      get
      {
        return WindowsIdentity.GetCurrent().Owner
          .IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid);
      }
    }
Run Code Online (Sandbox Code Playgroud)

因此,当我运行"以管理员身份运行"时,属性get访问器将返回true.正常运行时(即使我的用户"是"管理员,只是没有"以管理员身份"运行此特定应用程序),它将返回false.

这似乎比许多其他答案简单得多.

我不知道是否存在失败的情况.

PS!这也似乎没问题:

    static bool IsElevated
    {
      get
      {
        var id = WindowsIdentity.GetCurrent();
        return id.Owner != id.User;
      }
    }
Run Code Online (Sandbox Code Playgroud)

  • 这不会区分"半无法"流程和适当的非流程流程:"IsElevated"可能会返回false,但流程仍可能以高完整性级别运行.真正的非升级过程具有中等完整性级别.这可能与99%的应用程序无关,但值得一提,因为像Process Hacker这样的工具可能仍然会声明这样的进程被提升.一个"半无措施"的过程不是你通常会看到的; 当某人未能正确启动未加工的子进程时,可能会发生这种情况. (2认同)

Sco*_*ain 19

以下是此答案的修改版本,其中包括正确处理资源和处理域管理员等内容.

public static class UacHelper
{
    private const string uacRegistryKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
    private const string uacRegistryValue = "EnableLUA";

    private static uint STANDARD_RIGHTS_READ = 0x00020000;
    private static uint TOKEN_QUERY = 0x0008;
    private static uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);

    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool CloseHandle(IntPtr hObject);

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength, out uint ReturnLength);

    public enum TOKEN_INFORMATION_CLASS
    {
        TokenUser = 1,
        TokenGroups,
        TokenPrivileges,
        TokenOwner,
        TokenPrimaryGroup,
        TokenDefaultDacl,
        TokenSource,
        TokenType,
        TokenImpersonationLevel,
        TokenStatistics,
        TokenRestrictedSids,
        TokenSessionId,
        TokenGroupsAndPrivileges,
        TokenSessionReference,
        TokenSandBoxInert,
        TokenAuditPolicy,
        TokenOrigin,
        TokenElevationType,
        TokenLinkedToken,
        TokenElevation,
        TokenHasRestrictions,
        TokenAccessInformation,
        TokenVirtualizationAllowed,
        TokenVirtualizationEnabled,
        TokenIntegrityLevel,
        TokenUIAccess,
        TokenMandatoryPolicy,
        TokenLogonSid,
        MaxTokenInfoClass
    }

    public enum TOKEN_ELEVATION_TYPE
    {
        TokenElevationTypeDefault = 1,
        TokenElevationTypeFull,
        TokenElevationTypeLimited
    }

    public static bool IsUacEnabled
    {
        get
        {
            using (RegistryKey uacKey = Registry.LocalMachine.OpenSubKey(uacRegistryKey, false))
            {
                bool result = uacKey.GetValue(uacRegistryValue).Equals(1);
                return result;
            }
        }
    }

    public static bool IsProcessElevated
    {
        get
        {
            if (IsUacEnabled)
            {
                IntPtr tokenHandle = IntPtr.Zero;
                if (!OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_READ, out tokenHandle))
                {
                    throw new ApplicationException("Could not get process token.  Win32 Error Code: " +
                                                   Marshal.GetLastWin32Error());
                }

                try
                {
                    TOKEN_ELEVATION_TYPE elevationResult = TOKEN_ELEVATION_TYPE.TokenElevationTypeDefault;

                    int elevationResultSize = Marshal.SizeOf(typeof(TOKEN_ELEVATION_TYPE));
                    uint returnedSize = 0;

                    IntPtr elevationTypePtr = Marshal.AllocHGlobal(elevationResultSize);
                    try
                    {
                        bool success = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevationType,
                                                           elevationTypePtr, (uint) elevationResultSize,
                                                           out returnedSize);
                        if (success)
                        {
                            elevationResult = (TOKEN_ELEVATION_TYPE) Marshal.ReadInt32(elevationTypePtr);
                            bool isProcessAdmin = elevationResult == TOKEN_ELEVATION_TYPE.TokenElevationTypeFull;
                            return isProcessAdmin;
                        }
                        else
                        {
                            throw new ApplicationException("Unable to determine the current elevation.");
                        }
                    }
                    finally
                    {
                        if (elevationTypePtr != IntPtr.Zero)
                            Marshal.FreeHGlobal(elevationTypePtr);
                    }
                }
                finally
                {
                    if (tokenHandle != IntPtr.Zero)
                        CloseHandle(tokenHandle);
                }
            }
            else
            {
                WindowsIdentity identity = WindowsIdentity.GetCurrent();
                WindowsPrincipal principal = new WindowsPrincipal(identity);
                bool result = principal.IsInRole(WindowsBuiltInRole.Administrator) 
                           || principal.IsInRole(0x200); //Domain Administrator
                return result;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @ScottChamberlain的int heightResultSize = Marshal.SizeOf(typeof(TOKEN_ELEVATION_TYPE))在32位应用程序.NET 4.0上引发了ArgumentException异常,但是intent heightResultSize = Marshal.SizeOf((int)elevationResult)有效。 (2认同)

Pre*_*gha 16

CodePlex项目UAChelper有在UserAccountControl.cpp海拔检查代码UserAccountControl::IsUserAdmin,如果过程升高,来检查是否启用UAC,然后检查.

bool UserAccountControl::IsCurrentProcessElevated::get()
{
    return GetProcessTokenElevationType() == TokenElevationTypeFull;    //elevated
}
Run Code Online (Sandbox Code Playgroud)

从功能:

int UserAccountControl::GetProcessTokenElevationType()
{
    HANDLE hToken;
    try
    {
        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
            throw gcnew Win32Exception(GetLastError());

        TOKEN_ELEVATION_TYPE elevationType;
        DWORD dwSize;
        if (!GetTokenInformation(hToken, TokenElevationType, &elevationType, sizeof(elevationType), &dwSize))
            throw gcnew Win32Exception(GetLastError());

        return elevationType;
    }
    finally
    {
        CloseHandle(hToken);
    }
}
Run Code Online (Sandbox Code Playgroud)


Raf*_*ael 9

在.net Framwork 4.5中,我找到了另一种适合我的方法.关于以下脚本,可以在这里找到(德语)

 rem --- Admintest.bat ---
 whoami /groups | find "S-1-5-32-544" > nul
 if errorlevel 1 goto ende
 echo Benutzer %username% ist lokaler Administrator.
 :ende
Run Code Online (Sandbox Code Playgroud)

在C#中它看起来像这样:

    private bool IsAdmin
    {
        get
        {
            WindowsIdentity identity = WindowsIdentity.GetCurrent();
            if (identity != null)
            {
               WindowsPrincipal principal = new WindowsPrincipal(identity);
               List<Claim> list = new List<Claim>(principal.UserClaims);
               Claim c = list.Find(p => p.Value.Contains("S-1-5-32-544"));
               if (c != null)
                  return true;
            }
            return false;
        }
    }
Run Code Online (Sandbox Code Playgroud)

但是在.net <4.5中,WindowsPrincipal该类不包含该UserClaims属性,我发现无法获取此信息.

  • 仅供参考:仅确定帐户是否为管理员,而不确定应用程序是否已提升 (3认同)

And*_*ers 5

使用TokenElevationType会工作,但如果您CheckTokenMembership()针对管理组SID进行PInvoke ,您的代码也可以在UAC关闭时在2000/XP/2003上运行,并且还将处理拒绝SID.

还有一个IsUserAnAdmin()功能可以CheckTokenMembership为您进行检查,但MSDN表示可能不会永远存在


Joh*_*ith 5

这个答案有一些问题。首先,它没有获得任何以管理员身份运行的系统进程(例如在 NT-Authority/SYSTEM 下)。下面的代码示例修复了所有问题(检测 LocalAdmins、DomainAdmins 和 LocalSystemAdmins)

如果您只想要当前进程,请替换pHandleProcess.GetCurrentProcess().Handle

注意:您必须具有一定的权限才能运行它。(每个管理进程都有它们,但需要先激活它们,服务默认激活它们)

internal static bool IsProcessElevatedEx(this IntPtr pHandle) {

        var token = IntPtr.Zero;
        if (!OpenProcessToken(pHandle, MAXIMUM_ALLOWED, ref token))
                throw new Win32Exception(Marshal.GetLastWin32Error(), "OpenProcessToken failed");

        WindowsIdentity identity = new WindowsIdentity(token);
        WindowsPrincipal principal = new WindowsPrincipal(identity);
        bool result = principal.IsInRole(WindowsBuiltInRole.Administrator)
                   || principal.IsInRole(0x200); //Domain Administrator
        CloseHandle(token);
        return result;
}
Run Code Online (Sandbox Code Playgroud)