Сразу скажу, что я перечитал все похожие топики, — не нужно на них ссылаться.
Такова проблема:
Нужно запустить любую программу из моего системного севиса, да так, чтобы программа запустилась не в виде системного процесса, а как процесс текущего пользователя. Того, кто в настоящий момент залогинен в системе.
В статье http://www.microsoft.com/msj/0200/logon/logon.aspx я этого найти не смог, либо чего не понял.
Сейчас процессы запускается через CreateProcess, также реализована интерактивность через OpenWindowStation и OpenDesktop, но всеравно все процессы запускаются, как системные, поэтому им недоступен пользовательский реестр и т.д...
Как запустить процесс под текущим юзером, если я не знаю его username and pass????
Re: Запуск программы под правами юзера из NT сервиса
Здравствуйте, Disappear, Вы писали:
D>Сразу скажу, что я перечитал все похожие топики, — не нужно на них ссылаться.
Видимо, все-таки, не все, потому что года полтора-два назад это уже обсуждалось. Что-то вроде "Запуск Outlook Express из службы".
D>Такова проблема: D>Нужно запустить любую программу из моего системного севиса, да так, чтобы программа запустилась не в виде системного процесса, а как процесс текущего пользователя. Того, кто в настоящий момент залогинен в системе. D>В статье http://www.microsoft.com/msj/0200/logon/logon.aspx я этого найти не смог, либо чего не понял.
D>Сейчас процессы запускается через CreateProcess, также реализована интерактивность через OpenWindowStation и OpenDesktop, но всеравно все процессы запускаются, как системные, поэтому им недоступен пользовательский реестр и т.д...
D>Как запустить процесс под текущим юзером, если я не знаю его username and pass????
Очень просто. Надо вызвать СreateProcessAsUser, указав в качестве токена токен интерактивного пользователя. Прежде чем приступить к перечислению способов получения этого токена, напомню, что в системе может быть более одного интерактивного пользователя. Поэтому прежде всего предлагаю подумать о том, как узнать, в контексте какого из интерактивных пользователей нужно запустить процесс. Именно эта часть задачи представляется мне наиболее интересной.
А токен можно получить несколькими способами:
1) [простой и надежный способ, работает на всех системах] Делается небольшая программа, которая регистируется в HKLM\Software\Microsoft\Windows\CurrentVersion\Run. При запуске программа соединяется со службой используя COM, RPC или named pipes. C одной стороны, это позволяет узнать службе о факте входа интерактивного пользователя в систему, а с другой — служба может имперсонировать соединение (CoImpersonateClient, RpcImpersonateClient, ImpersonateNamedPipeClient) и получить токен пользователя (OpenThreadToken). Tаким образом получается так называемый impersonation token, который нужно преобразовать в primary token с помощью DuplicateTokenEx, прежде чем можно будет вызвать CreateProcessAsUser.
2) [очень простой и в тоже время надежный способ, WinXP and later] WTSEnumerateSessions и WTSQueryUserToken. Таким образом получаются токены для всех интерактивных сессий в системе.
3) [вариация первого способа, Win2K and later] Написать Winlogon notification package, в котором отследить вход пользователя в систему и получить его токен.
4) [не очень надежный способ, к которому у меня персональная антипатия] Перечислить все процессы, найти процесс оболочки и получить токен этого процесса с помощью OpenProcessToken. Очевидная проблема в том, что процесса оболочки может и не существовать. Кроме того, надо аккуратно обрабатывать ситуации когда таких процессов несколько, так как они могут принадлежать как одной интерактивной сессии, так и разным.
-- Alex Fedotov
Re[2]: Запуск программы под правами юзера из NT сервиса
Здравствуйте, Alex Fedotov, Вы писали:
AF>Здравствуйте, Disappear, Вы писали:
D>>Сразу скажу, что я перечитал все похожие топики, — не нужно на них ссылаться.
AF>Видимо, все-таки, не все, потому что года полтора-два назад это уже обсуждалось. Что-то вроде "Запуск Outlook Express из службы".
D>>Такова проблема: D>>Нужно запустить любую программу из моего системного севиса, да так, чтобы программа запустилась не в виде системного процесса, а как процесс текущего пользователя. Того, кто в настоящий момент залогинен в системе. D>>В статье http://www.microsoft.com/msj/0200/logon/logon.aspx я этого найти не смог, либо чего не понял.
D>>Сейчас процессы запускается через CreateProcess, также реализована интерактивность через OpenWindowStation и OpenDesktop, но всеравно все процессы запускаются, как системные, поэтому им недоступен пользовательский реестр и т.д...
D>>Как запустить процесс под текущим юзером, если я не знаю его username and pass????
AF>Очень просто. Надо вызвать СreateProcessAsUser, указав в качестве токена токен интерактивного пользователя. Прежде чем приступить к перечислению способов получения этого токена, напомню, что в системе может быть более одного интерактивного пользователя. Поэтому прежде всего предлагаю подумать о том, как узнать, в контексте какого из интерактивных пользователей нужно запустить процесс. Именно эта часть задачи представляется мне наиболее интересной.
AF>А токен можно получить несколькими способами:
AF>1) [простой и надежный способ, работает на всех системах] Делается небольшая программа, которая регистируется в HKLM\Software\Microsoft\Windows\CurrentVersion\Run. При запуске программа соединяется со службой используя COM, RPC или named pipes. C одной стороны, это позволяет узнать службе о факте входа интерактивного пользователя в систему, а с другой — служба может имперсонировать соединение (CoImpersonateClient, RpcImpersonateClient, ImpersonateNamedPipeClient) и получить токен пользователя (OpenThreadToken). Tаким образом получается так называемый impersonation token, который нужно преобразовать в primary token с помощью DuplicateTokenEx, прежде чем можно будет вызвать CreateProcessAsUser.
AF>2) [очень простой и в тоже время надежный способ, WinXP and later] WTSEnumerateSessions и WTSQueryUserToken. Таким образом получаются токены для всех интерактивных сессий в системе.
AF>3) [вариация первого способа, Win2K and later] Написать Winlogon notification package, в котором отследить вход пользователя в систему и получить его токен.
AF>4) [не очень надежный способ, к которому у меня персональная антипатия] Перечислить все процессы, найти процесс оболочки и получить токен этого процесса с помощью OpenProcessToken. Очевидная проблема в том, что процесса оболочки может и не существовать. Кроме того, надо аккуратно обрабатывать ситуации когда таких процессов несколько, так как они могут принадлежать как одной интерактивной сессии, так и разным.
У меня COM server;
Пробую первый метод:
в теле одного из методов интерфейса, я вызываю
CoImpersonateClient()
затем получаю
OpenThreadToken(GetCurrentThread(), ...)
все ок, но когда я хочу получить primary token с помощью функции DuplicateTokenEx ничего не выходит
Здравствуйте, Disappear, Вы писали:
D>У меня COM server; D>Пробую первый метод: D>в теле одного из методов интерфейса, я вызываю D>
D>CoImpersonateClient()
D>
D>затем получаю D>
D>OpenThreadToken(GetCurrentThread(), ...)
D>
Какие access rights были запрошены в OpenThreadToken?
D>все ок, но когда я хочу получить primary token с помощью функции DuplicateTokenEx ничего не выходит D>
AF>>А код ошибки какой?
D>0x542 Either a required impersonation level was not provided, or the provided impersonation level is invalid
D>вот такой в целом код: D>
Здравствуйте, Alex Fedotov, Вы писали:
AF>Здравствуйте, Disappear, Вы писали:
D>>Здравствуйте, Alex Fedotov, Вы писали:
AF>>>Какие access rights были запрошены в OpenThreadToken?
D>>
AF>>>А код ошибки какой?
D>>0x542 Either a required impersonation level was not provided, or the provided impersonation level is invalid
D>>вот такой в целом код: D>>
AF>Интересно. Перенеси для начала CoRevertToSelf сразу после OpenThreadToken и замени SecurityImpersonation на SecurityAnonymous.
Тоже самое, только сообщение об ошибке теперь выдается по русски, видимо это какраз связано с CoRevertToSelf.
Я пробовал под WinXP и под Win2k, — толку нуль. Блин, чтож такое, я не верю, что такую простую вещь, как запуск клиенского процесса из под сервиса нельзя реализовать.
Здравствуйте, Alex Fedotov, Вы писали:
AF>Здравствуйте, Disappear, Вы писали:
D>>Может быть стоит попробовать передавать токен из клиенского процесса системному??
AF>А может просто попросить клиентский процесс запустить нужную программу?
Дело в том, что клиенский процесс — это DLL-ка, которая ставит глобальный хук, и соответственно постоянно выполняется в контексте разных процессов.
Ели она сама будет запускать процессы, это будет затормаживать другие программы. Если она запустит для этого отдельный поток, то неизвестно чем это обернется, так как DLL может влюбой момент быть выгружена из чужого процесса.
Я составил список привелегий токена текущего процесса до ипмерсонации и поле, вот что получилось:
До вызова CoImpersonateClient
enabled on/off
-----------------------------------------------------------------
SeAssignPrimaryTokenPrivilege enabled off
SeAuditPrivilege enabled on
SeBackupPrivilege enabled off
SeChangeNotifyPrivilege enabled on
SeCreatePagefilePrivilege enabled on
SeCreatePermanentPrivilege enabled on
SeCreateTokenPrivilege enabled off
SeDebugPrivilege enabled on
SeEnableDelegationPrivilege disabled off
SeImpersonatePrivilege disabled off
SeIncreaseBasePriorityPrivilege enabled on
SeIncreaseQuotaPrivilege enabled off
SeLoadDriverPrivilege enabled off
SeLockMemoryPrivilege enabled on
SeMachineAccountPrivilege disabled off
SeManageVolumePrivilege enabled off
SeProfileSingleProcessPrivilege enabled on
SeRemoteShutdownPrivilege disabled off
SeRestorePrivilege enabled off
SeSecurityPrivilege enabled off
SeShutdownPrivilege enabled off
SeSyncAgentPrivilege disabled off
SeSystemEnvironmentPrivilege enabled off
SeSystemProfilePrivilege disabled off
SeSystemtimePrivilege enabled off
SeTakeOwnershipPrivilege enabled off
SeTcbPrivilege enabled on
SeUndockPrivilege enabled off
SeUnsolicitedInputPrivilege disabled off
После вызова CoImpersonateClient (функция возвращает S_OK)
enabled on/off
-----------------------------------------------------------------
SeAssignPrimaryTokenPrivilege disabled off
SeAuditPrivilege disabled off
SeBackupPrivilege disabled off
SeChangeNotifyPrivilege disabled off
SeCreatePagefilePrivilege disabled off
SeCreatePermanentPrivilege disabled off
SeCreateTokenPrivilege disabled off
SeDebugPrivilege disabled off
SedisabledelegationPrivilege disabled off
SeImpersonatePrivilege disabled off
SeIncreaseBasePriorityPrivilege disabled off
SeIncreaseQuotaPrivilege disabled off
SeLoadDriverPrivilege disabled off
SeLockMemoryPrivilege disabled off
SeMachineAccountPrivilege disabled off
SeManageVolumePrivilege disabled off
SeProfileSingleProcessPrivilege disabled off
SeRemoteShutdownPrivilege disabled off
SeRestorePrivilege disabled off
SeSecurityPrivilege disabled off
SeShutdownPrivilege disabled off
SeSyncAgentPrivilege disabled off
SeSystemEnvironmentPrivilege disabled off
SeSystemProfilePrivilege disabled off
SeSystemtimePrivilege disabled off
SeTakeOwnershipPrivilege disabled off
SeTcbPrivilege disabled off
SeUndockPrivilege disabled off
SeUnsolicitedInputPrivilege disabled off
В моем случае COM сервер — системный сервис, а клиент — процесс запущенный под _администратором_.
Теперь я запутался еще больше.
Не понимаю, как после имперсонации может получится токен, вообще без привилегий???
Здравствуйте, Disappear, Вы писали:
AF>>И таки процесса или потока?
D>Всетаки процесса, токен потока почему-то не удалось получить до вызова CoImpersonateClient
Так и должно быть. До вызова CoImpersonateClient у потока не было своего токена. Имперсонация в том и заключается, что берется токен клиента и назначается потоку. Интересно посмотреть на токен потока после имперсонации, в частности, его impersonation level.
Здравствуйте, Alex Fedotov, Вы писали:
AF>Здравствуйте, Disappear, Вы писали:
AF>>>И таки процесса или потока?
D>>Всетаки процесса, токен потока почему-то не удалось получить до вызова CoImpersonateClient
AF>Так и должно быть. До вызова CoImpersonateClient у потока не было своего токена. Имперсонация в том и заключается, что берется токен клиента и назначается потоку. Интересно посмотреть на токен потока после имперсонации, в частности, его impersonation level.
Я посмотрел через GetTokenInformation, уровень — SecurityIdentification
Что это значит?