CreateProcessAsUser vs ShellExecute

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

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

РУЧКА hTok;
ПРОВЕРКИ (LogonUser("otheruser",0,"пароль",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 вернется с ошибкой, если вы дадите ему исполняемый файл с манифестом, помеченным как requireAdmin)

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

4 ответа

Решение действительно зависит от ваших потребностей и может быть довольно сложным (полностью благодаря 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: Это также может быть сделано, но для этого требуется, чтобы вы уже запускали процесс с повышенными правами. Служба, работающая как локальная системная учетная запись, работает с повышенными правами. Я также мог заставить его работать только с подписанным аутентичным процессом, который я хотел запустить. Процесс, который вы хотите запустить, также должен иметь файл манифеста, связанный с ним с уровнем requiredExecutionLevel ="requireAdministrator"

Другие заметки:

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

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

C:\windwos\system32\cmd.exe /k" start <your_target_to_be_ShellExecuted>" в CreateProcessAsUser и вы сделали.

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

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

Вы можете обернуть 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 с "()"

Другие вопросы по тегам