Запускать программу от имени пользователя, но с повышенными привилегиями - PullRequest
0 голосов
/ 31 декабря 2018

Сценарий:

Администратор установит приложение.Приложение имеет некоторые операции на уровне ядра, поэтому оно должно работать в привилегированном режиме.Но у пользователя нет учетных данных администратора для запуска приложения в режиме повышенных прав.

Итак, какова лучшая возможность решить вышеуказанный сценарий.

Решение первое (пробное): при установке приложения через администратора мы создадим администратора, в котором нам известны его имя пользователя и пароль.Поэтому, когда пользователь пытается выполнить какую-либо операцию, мы запустим приложение в режиме с повышенными правами, используя функции processstartinfo () и process.start () в c #.Но приложение запускается от имени администратора, поэтому сопоставленные диски для пользователя не видны, так как этого администратора нет в списке ACL.Таким образом, этот метод исключается.

Может ли быть решение, при котором пользователь будет повышен до уровня администратора, пока операция не будет завершена с использованием приложения c #?

Я застрял и не надеваюне найти никаких статей для чтения по этому вопросу.

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

Возможно ли это?

Может кто-нибудь помочь, пожалуйста?

Спасибо.

Ответы [ 4 ]

0 голосов
/ 10 января 2019

Что вы можете сделать, это использовать COM + Component Services .В .NET проще всего использовать ServicedComponent Enterprise Services , который имеет всевозможные обертки и служебные классы для взаимодействия со службами компонентов COM +.

Итак, вот шаги для этого:

1) Создайте библиотеку классов .NET Framework.

2) Добавьте строгое имя и подпишите его

3) Добавьте, например, такой класс (I ')мы также добавили некоторый служебный метод для диагностики вещей)

[ComVisible(true)]
public class AdminClass : ServicedComponent
{
    public int DoSomethingAsAdmin()
    {
        // test something that a normal user shouldn't see
        return Directory.GetFiles(Path.Combine(Environment.SystemDirectory, "config")).Length;
    }

    public string WindowsIdentityCurrentName => WindowsIdentity.GetCurrent().Name;
    public string CurrentProcessFilePath => Process.GetCurrentProcess().MainModule.FileName;

    // depending on how you call regsvcs, you can run as a 32 or 64 bit surrogate dllhost.exe
    public bool Is64BitProcess => Environment.Is64BitProcess;
}

4) Добавьте следующее к AssemblyInfo.cs

[assembly: ApplicationName("AdminApp")]
[assembly: SecurityRole("AdminAppUser")]
[assembly: ApplicationActivation(ActivationOption.Server)]

Для этого нужно определить приложение COM + с именем "AdminApp",добавьте к нему роль с именем «AdminAppUser» и объявите, что приложение будет работать как «сервер», что означает «вне процесса».

5) Скомпилируйте его и выполните эту команду как admin

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regsvcs.exe AdminApp.dll

или эта команда:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\regsvcs.exe AdminApp.dll

Обе команды создадут приложение COM + и разместят DLL-библиотеку .NET в суррогатном .exe (dllhost.exe).Если вы выберете первый, размещенный процесс будет работать как x64, а если вы запустите второй, размещенный процесс будет работать как x86.

Вы можете проверить результат этой регистрации, если вы запустите службы компонентов (изWindows / Run):

enter image description here

6) Щелкните правой кнопкой мыши приложение, и вы увидите целую кучу интересных вещей, которые можно настроить.Обратите внимание, что вы даже можете запустить это как службу (на вкладке «Активация») и т. Д. То, что вы должны сделать, это настроить удостоверение, которое будет запускать этот процесс, примерно так:

enter image description here

Здесь я использовал собственную учетную запись администратора.Вы не хотите, чтобы использовал любой другой встроенный выбор.

7) Теперь, когда включена защита по умолчанию, в принципе никто не может вызвать этот компонент.Поэтому нам просто нужно добавить пользователя к роли «AdminAppUser», которую мы создали ранее.Конечно, вы можете сделать это с помощью пользовательского интерфейса, как показано здесь:

enter image description here

, но вот фрагмент кода, который делает это программно (мы используем COM + объекты администрирования ):

AddUserInRole("AdminApp", "AdminAppUser", @"SMO01\simon");

....

static void AddUserInRole(string appName, string roleName, string userName)
{
    dynamic catalog = Activator.CreateInstance(Type.GetTypeFromProgID("COMAdmin.COMAdminCatalog"));

    // the list of collection hierarchy : https://docs.microsoft.com/en-us/windows/desktop/cossdk/com--administration-collections
    var apps = catalog.GetCollection("Applications");
    var app = GetCollectionItem(apps, appName);
    if (app == null)
        throw new Exception("Application '" + appName + "' was not found.");

    var roles = apps.GetCollection("Roles", app.Key);
    var role = GetCollectionItem(roles, roleName);
    if (role == null)
        throw new Exception("Role '" + roleName + "' was not found.");

    // UsersInRole collection
    // https://docs.microsoft.com/en-us/windows/desktop/cossdk/usersinrole
    var users = roles.GetCollection("UsersInRole", role.Key);
    var user = GetCollectionItem(users, userName);
    if (user == null)
    {
        user = users.Add();
        user.Value["User"] = userName;
        users.SaveChanges();
    }
}

static dynamic GetCollectionItem(dynamic collection, string name)
{
    collection.Populate();
    for (int i = 0; i < collection.Count; i++)
    {
        var item = collection.Item(i);
        if (item.Name == name)
            return item;
    }
    return null;
}

Результат должен быть таким:

enter image description here

8) Сейчасдля клиентского приложения использовать средства AdminApp очень просто.Не ссылайтесь на .DLL как на стандартную ссылку .NET, но используйте его как любой другой внешний COM-компонент.Вы можете сослаться на файл .TLB, который был создан regsvcs, или просто использовать магическое динамическое ключевое слово, как я продемонстрировал здесь (недостаток в том, что вы не получаете автозаполнение):

using System;
using System.Security.Principal;

namespace UserApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Is64BitProcess " + Environment.Is64BitProcess);
            Console.WriteLine("Running As " + WindowsIdentity.GetCurrent().Name);

            var type = Type.GetTypeFromProgID("AdminApp.AdminClass");
            dynamic trustedClass = Activator.CreateInstance(type);

            Console.WriteLine("Admin App Process Path: " + trustedClass.CurrentProcessFilePath);
            Console.WriteLine("Admin App Running As: " + trustedClass.WindowsIdentityCurrentName);
            Console.WriteLine("Admin App Is64BitProcess: " + trustedClass.Is64BitProcess);
            Console.WriteLine("Admin App DoSomethingAsAdmin: " + trustedClass.DoSomethingAsAdmin());
        }
    }
}

Теперь, когда вы запускаетенапример, как «simon», вы должны увидеть что-то вроде этого, оно работает:

Is64BitProcess False
Running As SMO01\simon
Admin App Process Path: C:\WINDOWS\system32\dllhost.exe
Admin App Running As: SMO01\myAdmin
Admin App Is64BitProcess: True
Admin App DoSomethingAsAdmin: 71

и когда вы запустите его, например, как «bob», который не настроен в роли, вы должны увидеть что-то вродеэто с отказом в доступе, это ожидается:

Is64BitProcess False
Running As SMO01\bob

Unhandled Exception: System.UnauthorizedAccessException: Retrieving the COM class factory for component with CLSID {0DC1F11A-A187-3B6D-9888-17E635DB0974} failed due to the following error: 80070005 Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)).
   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Activator.CreateInstance(Type type)
   at UserApp.Program.Main(String[] args) in C:\Users\simon\source\repos\TrustedSystem\UserApp\Program.cs:line 14

Обратите внимание, что мы создали доверенную систему без установки пароля в любом месте.И я только поцарапал поверхность того, что вы можете сделать с компонентом COM +.Например, вы можете экспортировать приложение в виде MSI для легкого развертывания и т. Д.

0 голосов
/ 08 января 2019

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

Я заметил, что у вас есть эти две:

  • Путь к файловой системе. Доступ к нему имеет только вошедший в систему пользователь (учетная запись администратора отсутствует).
  • Процессы приложения. ТолькоУчетная запись администратора может запускать эти процессы (вошедшему в систему пользователю будет предложено повышение прав пользователя).

Чтобы проиллюстрировать это ...

        |  File System Path   |  Application Process
User    |        OK           |          --
Admin   |        --           |          OK

Решение должно выглядеть следующим образомэто ...

        |  File System Path   |  Application Process
Service |        OK           |          OK

Если возможно, я бы сказал, что это самый простой способ, при котором вы создаете служебную учетную запись , у которой есть разрешения на выполнение обоих действий.

0 голосов
/ 10 января 2019

Вы можете попробовать создать параллельный поток с правами администратора для выполнения операций ядра.Таким образом, вся ваша программа содержится в одном исполняемом файле.

0 голосов
/ 07 января 2019

Я решил разделить программу на две части.Одна часть работает как служба, которая запускается с правами администратора, а другая - с обычными привилегиями.Связь между двумя программами может осуществляться через Ethernet или с использованием общей памяти.

...