Запуск другого процесса с повышением прав с использованием других учетных данных пользователя - PullRequest
19 голосов
/ 26 марта 2012

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

Например, если я делаю это (без использования манифеста, требующего повышения прав):

ProcessStartInfo info = new ProcessStartInfo(path);

info.UseShellExecute = false;
info.UserName = username;
info.Password = securePwd;
info.Domain = "MyDomain";
info.Verb = "runas";

var proc = Process.Start(info);

Процесс запускается без отображения диалогового окна подтверждения UAC и завершается неудачно при попытке выполнить команду, требующую прав администратора (я просто пытаюсь записать тестовый файл в каталог Program Files).

Если я добавлю манифест в целевое приложение, которое указывает, что ему требуется повышение прав, то я получу Win32Exception, в котором будет указано, что операция требует повышения прав.

Кажется, проблема заключается в установке UseShellExecute на false (так как оба подхода работают нормально, когда это не так), но я должен установить для него значение false, чтобы запустить процесс под другой учетной записью пользователя.

Как запустить процесс с повышенными правами из процесса без прав доступа и ввести имя пользователя и пароль вручную?

РЕДАКТИРОВАНИЕ BOUNTY: Хотя от пользователя не требуется ввод учетных данных администратора, диалоговое окно контроля доступа UAC вполне приемлемо. Я не собираюсь обходить UAC здесь.

Ответы [ 5 ]

12 голосов
/ 04 апреля 2012

Я был удивлен, что нет никакого способа сделать это, пока я не нашел запись в блоге Криса Джексона:

Почему я не могу повысить свое приложение для запуска от имени администратора при использовании CreateProcessWithLogonW?

Вам нужен загрузчик. Некоторый процесс, который позволит вам выполнить переход к альтернативному пользователю, который может быть ответственным за запуск приложения requireAdministrator. Итак, вы можете создать что-то вроде этого:

enter image description here

Почему бы нам просто не создать ShellExecuteWithLogonW API? Я никогда не скажу никогда, и мы могли бы в какой-то момент. Но сегодня, варианты использования для этих API были вариантами использования, когда был альтернативный дизайн, который является превосходящим.

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

Так что решение требует ShellExecute, только оно знает, как вызвать диалоговое окно Согласие .

Это поднимает хороший вопрос: что вы уже делаете с паролем человека?

Бонусная болтовня

Нет UAC на Server Core, потому что нет окон для отображения запроса на согласие.

3 голосов
/ 28 марта 2012

От MSDN :

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

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

Кажется, проблема заключается в установке UseShellExecute на false (как подходы работают нормально, когда это не так), но я должен установить его в false, чтобы запустить процесс под другим пользователем счет.

Как вы упомянули, именно так, как указано в документации для UseShellExecute:

UseShellExecute должно быть ложным, если свойство UserName не равно Nothing или пустая строка, или InvalidOperationException будет брошено когда вызывается метод Process.Start (ProcessStartInfo).

Теперь мы знаем, что вы выполняете свою программу напрямую, а не через оболочку. Это ценная информация.

В обратном направлении по документации документы для ProcessStartInfo содержат следующее примечание по безопасности:

Этот класс содержит требование ссылки на уровне класса, которое применяется к все члены. SecurityException выдается, когда непосредственный вызывающий не имеет разрешения полного доверия. Подробнее о безопасности требования, см. Ссылка Требования .

Итак, у вас нет прав Требование ссылки . При попытке решить проблему с разрешениями вы случайно создали еще одну проблему с разрешениями.

В результате вам нужно украсить свой вызывающий метод с правом Security Demand , которое должно быть FullTrust. Вы можете сделать это декларативно или обязательно в вашем коде.

( Дополнительное чтение )

1 голос
/ 04 апреля 2012

Если вы создаете приложение установщика Windows (MSI) и обновляете его с помощью MSP, то в установщик Windows встроена поддержка именно для вашего сценария: - проверьте Исправление контроля учетных записей (UAC) .

Это работает в основном так:

  • Когда вы создаете оригинальный MSI, вы генерируете сертификат и помещаете его открытый ключ (или что-то в этом роде) в MSI.
  • Администратор целевого компьютера устанавливает MSI на компьютере.
  • Вы создаете обновление (MSP) и подписываете его сертификатом.
  • Теперь любой пользователь на целевом компьютере может установить обновление - установщик Windows проверит сертификат по открытому ключу в исходном MSI и согласится установить, если это так. Я не думаю, что вы получите приглашение UAC вообще, хотя я не уверен.
0 голосов
/ 04 апреля 2012

ProcessStartInfo.Verb="runas" только для Windows Vista и выше, поэтому вам следует запрашивать системный уровень, а не повышать уровень для XP.

Я думаю, что если вы выберете ProcessStartInfo.Verb="runas", вы не должны указывать имя пользователя и пароль.

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

0 голосов
/ 04 апреля 2012

Согласно документации MSDN:

Когда UseShellExecute имеет значение false, вы можете запускать только исполняемые файлы с помощью объекта Process.

Я заметил ваше объявление var proc = Process.Start(info);не использует Process в качестве типа класса.

Также убедитесь, что параметр path - это полный путь к исполняемому файлу.Например, "c:\\directory\\contains\\process_to_be_started\\executable.exe"

В соответствии с документацией MSDN это важно:

Свойство WorkingDirectory должно быть установлено, если указаны имя пользователя и пароль.Если свойство не задано, рабочим каталогом по умолчанию является% SYSTEMROOT% \ system32.

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

ProcessStartInfo info = new ProcessStartInfo(path);

info.UseShellExecute = false;
info.UserName = username;
info.Password = securePwd;
info.Domain = "MyDomain";
info.Verb = "runas";
info.WorkingDirectory = "c:\\directory\\contains\\process_to_be_started"

'var proc = Process.Start(info);

Process proc = Process.Start(info);
...