Определить, работает ли от имени администратора с повышенными привилегиями или без них? - PullRequest
70 голосов
/ 03 августа 2009

У меня есть приложение, которое должно определить, работает ли оно с повышенными привилегиями или нет. В настоящее время у меня установлен код, подобный этому:

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

Это работает, чтобы определить, является ли пользователь администратором или нет, но не работает, если работает от имени администратора без повышения прав. (Например, в vshost.exe).

Как я могу определить, возможно ли повышение [уже действует или] возможно ?

Ответы [ 9 ]

51 голосов
/ 21 декабря 2010

Попробуйте это:

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;
            }
        }
    }
}
25 голосов
/ 06 августа 2015

(новый ответ шесть лет после того, как вопрос был задан)

Отказ от ответственности: это просто то, что работало на моей конкретной ОС с моими конкретными настройками с моим конкретным пользователем:

using System.Security.Principal;

// ...

    static bool IsElevated
    {
      get
      {
        return WindowsIdentity.GetCurrent().Owner
          .IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid);
      }
    }

Поэтому, когда я запускаю этот «Запуск от имени администратора», свойство get accessor возвращает true. При нормальной работе (даже если мой пользователь «является» администратором, но не запускает это конкретное приложение «как администратор»), он возвращает false.

Это кажется намного проще, чем многие другие ответы.

Понятия не имею, есть ли случаи, когда это не удается.

PS! Это тоже кажется нормальным:

    static bool IsElevated
    {
      get
      {
        var id = WindowsIdentity.GetCurrent();
        return id.Owner != id.User;
      }
    }
17 голосов
/ 05 июля 2013

Вот модифицированная версия этого ответа , включающая такие вещи, как правильное распределение ресурсов и обработка администраторов домена.

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;
            }
        }
    }
}
15 голосов
/ 03 августа 2009

В проекте CodePlex UAChelper есть код, который проверяет повышение прав в UserAccountControl.cpp UserAccountControl::IsUserAdmin, который проверяет, включен ли UAC, а затем проверяет, повышен ли процесс.

bool UserAccountControl::IsCurrentProcessElevated::get()
{
    return GetProcessTokenElevationType() == TokenElevationTypeFull;    //elevated
}

из функции:

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);
    }
}
8 голосов
/ 22 июля 2014

В .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

В 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;
        }
    }

Но в .net <4.5 класс <code>WindowsPrincipal не содержит свойства UserClaims и я не нашел способа получить эту информацию.

5 голосов
/ 05 августа 2009

Использование TokenElevationType будет работать, но если вы нажмете CheckTokenMembership() против SID группы администраторов, ваш код также будет работать, когда UAC выключен и на 2000 / XP / 2003, а также будет обрабатывать SID запрета.

Существует также функция IsUserAnAdmin(), которая проверяет CheckTokenMembership, но MSDN говорит, что она может отсутствовать вечно

1 голос
/ 09 марта 2019

Этот ответ имеет несколько проблем. Во-первых, он не получает никаких системных процессов, которые запускаются от имени администратора (например, в NT-Authority / SYSTEM). Пример кода ниже устраняет все проблемы (обнаруживает, LocalAdmins, DomainAdmins и LocalSystemAdmins)

Если вы просто хотите текущий процесс, замените pHandle на Process.GetCurrentProcess().Handle

Примечание: У вас должны быть определенные привилегии для его запуска. (Каждый AdminProcess имеет их, но сначала необходимо активировать их, службы активируют их по умолчанию)

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;
}
1 голос
/ 08 июля 2018

Использование UACHelper пакета nuget: https://www.nuget.org/packages/UACHelper/

if (UACHelper.IsElevated)
    // something
else
    // something else

Существует множество других свойств, которые можно использовать для определения того, является ли пользователь на самом деле администратором или процесс выполняется под виртуализацией UAC, или владелец рабочего стола является владельцем процесса. (Запустить как с ограниченной учетной записи)

Проверьте прочитайте меня для получения дополнительной информации.

0 голосов
/ 14 января 2015

Я думаю, что есть еще одна проблема. Я проверил предоставленные вами решения и должен сказать, что при установке Windows 7 и вошел в систему как администратор, проверка не работает. Windows никогда не возвращает информацию о том, что процесс выполняется в режиме с повышенными правами. Итак, последовательность:

if (IsUacEnabled)
    return IsProcessInElevatedMode();
return IsUserAdmin();

не возвращает истину, когда зарегистрирован как Администратор, но процесс имеет все привилегии для выполнения системных операций (например, остановка системных служб). Рабочая последовательность:

if (IsUserAdmin())
    return true;

if (IsUacEnabled)
    return IsProcessInElevatedMode();

return false;

Сначала необходимо проверить, запущен ли процесс в контексте администратора. Дополнительная информация:

IsUacEnabled() - checks if the UAC has been enabled in the system (Windows)
IsProcessInElevatedMode() - checks if the process is run in an elevated mode
IsUserAdmin() - checks if the current user has an Administrtor role

Все эти методы были описаны в предыдущих постах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...