CreateProcessAsUser vs ShellExecute - PullRequest
       39

CreateProcessAsUser vs ShellExecute

3 голосов
/ 29 августа 2008

Мне нужно ShellExecute что-то от имени другого пользователя, в настоящее время я запускаю вспомогательный процесс с CreateProcessAsUser, который вызывает ShellExecute, но это выглядит как слишком много взлома (неправильный родительский процесс и т. Д.). Есть ли лучше способ сделать это?

@ PabloG: ImpersonateLoggedOnUser не работает:

HANDLE hTok;
VERIFY(LogonUser("otheruser",0,"password",LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,&hTok));
VERIFY(ImpersonateLoggedOnUser(hTok));
ShellExecute(0,0,"calc.exe",0,0,SW_SHOW);
RevertToSelf();
CloseHandle(hTok);

просто запустит calc как зарегистрированный пользователь, а не "otheruser"

@ 1800 ИНФОРМАЦИЯ: CreateProcess / CreateProcessAsUser - это не то же самое, что ShellExecute, с UAC в Vista, CreateProcess бесполезен, если вы не можете контролировать, какую программу выполняет пользователь (CreateProcess вернется с ошибкой, если вы передадите ему exe-файл с манифестом, помеченным как requireAdmin)

@ Brian R. Bondy: я уже знаю эту информацию (и не поймите меня неправильно, это хорошая вещь), но она не по теме (ИМХО) Я прошу ShellExecuteAsUser, а не о запуске процессов как другой пользователь, я уже знаю, как это сделать.

Ответы [ 4 ]

9 голосов
/ 30 августа 2008

Решение действительно зависит от ваших потребностей и может быть довольно сложным (полностью благодаря Windows Vista). Вероятно, это будет за пределами вашей потребности, но это поможет другим, которые находят эту страницу с помощью поиска.

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

Относительно 1: В Windows Vista существует нечто, называемое изоляцией сеанса 0. Все сервисы работают как сеанс 0, и вы не должны иметь графический интерфейс пользователя в сеансе 0. Первый вошедший в систему пользователь регистрируется в сеансе 1. В предыдущих версиях Windows (до Vista) первый вошедший в систему пользователь также полностью запускался в сессия 0.

Вы можете запускать несколько разных процессов с разными именами пользователей в одном сеансе. Хороший документ об изоляции сеанса 0 можно найти здесь .

Поскольку мы имеем дело с вариантом 1), вам не нужен графический интерфейс. Поэтому вы можете начать процесс в сеансе 0.

Вам понадобится последовательность вызовов примерно такая: LogonUser, ExpandEnvironmentStringsForUser, GetLogonSID, LoadUserProfile, CreateEnvironmentBlock, CreateProcessAsUser.

Пример кода для этого можно найти через любую поисковую систему или через Поиск кода Google

Относительно 2: Если пользователь, которому вы хотите запустить процесс, уже вошел в систему, вы можете просто использовать: WTSEnumerateSessions и WTSQuerySessionInformation, чтобы получить идентификатор сеанса, а затем WTSQueryUserToken, чтобы получить пользовательский токен. Оттуда вы можете просто использовать токен пользователя в Win32 API CreateProcessAsUser.

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

Вы можете получить текущий сеанс через WTSGetActiveConsoleSessionId.

Относительно 3: Вы будете следовать тем же шагам, что и # 1, но, кроме того, вы будете использовать поле lpDesktop в STARTUPINFO. Установите для этого значение winsta0 \ Default. Вам также нужно будет попробовать использовать OpenDesktop Win32 API, и в случае неудачи вы можете создать CreateDesktop. Перед использованием дескрипторов станции и рабочего стола вы должны использовать SetSecurityInfo для каждого из них с SE_WINDOW_OBJECT и GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION.

Если позже рассматриваемый пользователь попытается войти в систему, он фактически увидит запущенный процесс.

Относительно 4: Это также можно сделать, но для этого требуется, чтобы у вас уже был запущенный процесс с повышенными правами. Служба, работающая как локальная системная учетная запись, работает с повышенными правами. Я мог также заставить его работать, только имея подписанный процесс authenticode, который я хотел запустить. Процесс, который вы хотите запустить, также должен иметь файл манифеста, связанный с ним с уровнем requiredExecutionLevel = "requireAdministrator"

Другие примечания:

  • Вы можете установить сеанс токена с помощью SetTokenInformation и TokenSessionId
  • Вы не можете изменить идентификатор сеанса уже запущенного процесса.
  • Весь этот процесс был бы значительно проще, если бы в уравнении не было Vista.
1 голос
/ 18 июня 2009

Если вам нужна семантика ShellExecute, вы можете указать следующее:

C:\windwos\system32\cmd.exe /k" start <your_target_to_be_ShellExecuted>" на CreateProcessAsUser и все готово.

0 голосов
/ 29 августа 2008

Почему бы вам просто не создать CreateProcessAsUser, указав процесс, который вы хотите запустить?

Вы также можете использовать SHCreateProcessAsUserW.

0 голосов
/ 29 августа 2008

Вы можете заключить ShellExecute между ImpersonateLoggedOnUser / RevertToSelf

ссылки: ImpersonateLoggedOnUser: http://msdn.microsoft.com/en-us/library/aa378612(VS.85).aspx RevertToSelf: http://msdn.microsoft.com/en-us/library/aa379317.aspx

извините, не могу гиперссылку URL с помощью "()"

...