Question

J'utilise une partie thrid service Windows qui gère des tâches d'automatisation par scripts en cours d'exécution et les exécutables utilisant CreateProcessAsUser (). Je suis en cours d'exécution dans des problèmes sur Windows Server 2008 en raison de l'UAC et ainsi l'élévation LUA est manipulé par les API.

Le service fonctionne en tant que LocalSystem et ne pas « interagir avec le bureau » est activée. Les processus sont en cours d'exécution en tant que les utilisateurs du groupe Administrateurs, mais pas le compte Administrateur (qui est exempté de nombreuses restrictions CCU). Tous les paramètres par défaut. UAC en place

Je peux passer des commandes arbitraires ou code powershell au service, mais je ne peux pas sembler « sortir » de la non-élevée, processus non interactif qui obtient lancé par le service.

Le nœud du problème semble être que la seule option API (public) pour le démarrage d'un processus élevé est ShellExecute () avec le verbe les «runas de, mais pour autant que je peux dire que ne peut pas être appelé à partir d'un service non interactif ou vous obtenez des erreurs comme « Cette opération nécessite une station de fenêtre interactive ».

La seule solution que j'ai trouvé est mentionné ici: http://www.eggheadcafe.com/ logiciel / aspnet / 29620442 / comment-approprié à utiliser-sendinp.aspx

  

Dans Vista, la voie officielle documentée   d'élever un processus est seulement en utilisant la   shell API ShellExecute (Ex) (non   CreateProcess ou CreateProcessAsUser).   Ainsi, votre application doit appeler   ShellExecute (Ex) pour lancer un assistant   élevée pour appeler SendInput.   En outre, en raison de la Session 0   l'isolement, un service ne peut utiliser   CreateProcessAsUser ou   CreateProcessWithLogonW (ne peut pas utiliser   ShellExecute (Ex)) pour spécifier le   bureau interactif.

     

.. Je pense qu'il n'y a aucun moyen direct de   engendrer un processus élevée à partir d'un   service de fenêtres. Nous ne pouvons utiliser d'abord   CreateProcessAsUser ou   CreateProcessWithLogonW pour frayer un   Procédé non-élevée à l'utilisateur   session (bureau interactif). Puis dans   le processus non élevée, il peut utiliser   ShellExecute (Ex) pour frayer une élévation   processus pour la tâche réelle.

Pour ce faire, de .net / code Powershell, il semble que je dois faire quelques trucs P / Invoke élaborée pour appeler CreateProcessAsUser ou CreateProcessWithLogonW depuis le .Net System.Diagnostics.ProcessStartInfo ne dispose pas d'un équivalent de lpDesktop que je pouvais mettre à « winsta0 \ default ». Et je ne suis pas certain si LocalSystem a même le droit d'appeler CreateProcessAsUser ou CreateProcessWithLogonW.

J'ai aussi regardé http: //blogs.msdn.com/alejacma/archive/2007/12/20/how-to-call-createprocesswithlogonw-createprocessasuser-in-net.aspx et Process.Start avec différentes informations d'identification avec contrôle de compte sur

Sur la base de tout cela, je suis parvenu à la conclusion qu'il n'y a aucun moyen simple de le faire. Est-ce que je manque quelque chose? Cela ne semble pas vraiment comme il devrait être si difficile. Il se sent comme tout simplement jamais été UAC conçu pour traiter les cas d'utilisation non interactifs.

Et si les Microsoft gens finissent par lire ceci, j'ai remarqué que la façon dont ShellExecute gère en interne l'élévation est en appelant à la demande Service d'information (AIS). Pourquoi est-ce même pas appel à AIS disponible via une API Win32 ou .NET? http://msdn.microsoft.com/en-us/library/bb756945. aspx

Désolé qui a couru un peu long. Merci pour toutes les idées.

Était-ce utile?

La solution

La façon de briser l'isolement zéro séance « officielle » est d'utiliser une combinaison de l'API de services terminaux et CreateProcessAsUser() de lancer un processus dans la session d'un utilisateur. A mon ancien emploi, nous avons fait exactement cela, car nous avions besoin pour afficher une boîte de dialogue à l'utilisateur d'un service avant d'installer une mise à jour téléchargée Donc, je sais que cela fonctionne, sur Windows XP, Win2K3, Vista et Win7 au moins, mais je ne vous attendez pas que Win 2K8 serait trop différent. Fondamentalement, le processus se déroule comme suit:

  1. Appel WTSGetActiveConsoleSessionId() pour obtenir l'identifiant de session de la console active (très important, car la session interactive est pas toujours la session 1, même sur les systèmes clients). Cette API sera également de retour -1 s'il n'y a pas d'utilisateur actif connecté à la session interactive (qui est connecté localement à la machine physique, par opposition à l'utilisation de RDP).
  2. Faites passer l'identifiant de session de l'appel API avant WTSQueryUserToken() pour obtenir un jeton ouvert qui reprents l'utilisateur connecté à la console.
  3. Appel DuplicateTokenEx() pour convertir le jeton d'emprunt d'identité (de WTSQueryUserToken) dans un jeton primaire.
  4. Appel CreateEnvironmentBlock() pour créer un nouvel environnement pour le processus (en option, mais si vous ne le faites pas, le processus a pas).
  5. Faire passer le jeton principal de l'étape 3 dans un appel à CreateProccessAsUser(), ainsi que la ligne de commande de l'exécutable. Si vous avez créé un bloc d'environnement de l'étape 4, vous devez passer le drapeau CREATE_UNICODE_ENVIRONMENT et (toujours). Cela peut sembler stupide, mais l'API échoue horriblement si vous ne le faites pas (avec ERROR_INVALID_PARAMTER).
  6. Si vous avez créé un bloc d'environnement, alors vous devez appeler DestroyEnvironmentBlock, sinon vous allez générer une fuite de mémoire. Le processus reçoit une copie séparée du bloc de l'environnement lors de son lancement, de sorte que vous ne sont en train de détruire les données locales.

Et le tour est joué! Windows ne magie interne, et vous voyez le lancement de l'application. Cependant, bien que cela va lancer et processus interactif d'un service, je ne suis pas sûr si elle contournera UAC (mais ne me citez pas cela). En d'autres termes, il ne peut pas lancer comme un processus élevé à moins que le registre ou manifeste interne dit de le faire, et même alors, vous pourrait toujours obtenir une invite UAC. Si le jeton que vous obtenez de l'étape 3 est un jeton restreint, vous pourriez être en mesure d'utiliser AdjustTokenPrivileges() pour restaurer le jeton élevé (complet), mais ne me citez pas non plus. Toutefois, comme indiqué dans la documentation MSDN, s'il vous plaît noter qu'il est impossible de « ajouter » des privilèges sur un jeton qui ne le sont pas encore (par exemple, vous ne pouvez pas transformer un jeton d'utilisateur restreint en un administrateur en utilisant AdjustTokenPrivileges, le sous-jacent utilisateur doit être administrateur pour commencer).

Il est techniquement possible de faire tout cela à partir Win2K avant. Cependant, il est vraiment possible que commencer avec Windows XP, Win2K manque de l'API et WTSGetActiveConsoleSessionId() WTSQueryUserToken() (avec WTSEnumerateProcesses() pour Win2K Pro). Vous pouvez coder en dur 0 comme l'identifiant de session (puisque c'est toujours le cas dans Win2K), et je suppose que vous pourriez être en mesure d'obtenir le jeton d'utilisateur en dénombrant les processus en cours et dupliquer un de leurs jetons (il devrait être celui qui a le SID interactive présent). Peu importe, le CreateProcessAsUser() se comportera de la même manière lorsqu'il est passé un jeton d'utilisateur interactif, même si vous ne sélectionnez pas « interagir avec le bureau » des paramètres de service. Il est également plus sûr que le lancement directement du service de toute façon, que le processus ne sera pas hériter le jeton divin d'accès LocalSystem.

Maintenant, je ne sais pas si votre application tierce que tout cela quand il exécute le script / processus, mais si vous voulez le faire d'un service, qui est de savoir comment (et avec Vista ou Win7, c'est la seule façon de surmonter la session 0 isolement).

Autres conseils

En fonction, vous pouvez faire votre cas d'utilisation ce que je fais. Je chasse le processus winlogon pour la session active et son jeton vole. S'il n'y a pas de session active (API retourne -1), utilisez 1 si WINVER> = 6 sinon 0. Il en résulte SYSTEM sur la session active.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top