Domanda

Sto usando un servizio di Windows partito thrid che gestisce alcuni compiti di automazione per l'esecuzione di script ed eseguibili utilizzando CreateProcessAsUser (). Sono in esecuzione in problemi in Windows Server 2008 a causa di UAC e così l'elevazione LUA viene manipolato attraverso le API.

Il servizio viene eseguito come LocalSystem e non dispone di "interagire con il desktop" abilitato. I processi vengono eseguiti come utenti del gruppo Administrators, ma non l'account Administrator (che è esentato dalle molte limitazioni UAC). Tutte le impostazioni UAC di default in atto.

posso passare comandi arbitrari o il codice PowerShell per il servizio, ma non riesco a 'uscire' del processo non elevati, non interattivo che viene dato il via dal servizio.

Il nocciolo della questione sembra essere che l'unica opzione API (pubblico) per l'avvio di un processo di elevata è ShellExecute () con i verb 'runas', ma per quanto mi riguarda posso dire che non può essere chiamato da un il servizio non interattivo o si ottiene errori come "Questa operazione richiede una stazione finestra interattiva".

L'unica soluzione che ho trovato è menzionata qui: http://www.eggheadcafe.com/ software / aspnet / 29620442 / how-to-corretto-uso-sendinp.aspx

  

In Vista, il funzionario ha documentato modo   elevare un processo sta utilizzando solo la   shell API ShellExecute (Ex) (non   CreateProcess o CreateProcessAsUser).   Quindi, l'applicazione deve chiamare   ShellExecute (Ex) per lanciare un aiutante   elevata chiamare SendInput.   Inoltre, a causa di sessione 0   l'isolamento, un servizio può utilizzare solo   CreateProcessAsUser o   CreateProcessWithLogonW (non è possibile utilizzare   ShellExecute (Ex)) per specificare il   desktop interattivo.

     

.. Credo che non v'è alcun modo diretto per   generare un processo elevato da una   servizio di Windows. Possiamo solo utilizzare prima   CreateProcessAsUser o   CreateProcessWithLogonW a deporre le uova un   processo non elevata nella all'utente   sessione (interactive desktop). poi, nel   il processo non elevata, può utilizzare   ShellExecute (Ex) per deporre un elevato   processo per l'attività vera e propria.

Per fare questo dal codice .net / PowerShell, sembra che avrei dovuto fare un po 'elaborato P / Invoke roba da chiamare CreateProcessAsUser o CreateProcessWithLogonW dal momento che la Net System.Diagnostics.ProcessStartInfo non ha un equivalente di lpDesktop che ho potuto impostare su "winsta0 \ default". E io non sono chiare su se LocalSystem ha anche il diritto di chiamare CreateProcessAsUser o CreateProcessWithLogonW.

Ho anche guardato http: //blogs.msdn.com/alejacma/archive/2007/12/20/how-to-call-createprocesswithlogonw-createprocessasuser-in-net.aspx e Process.Start con credenziali diverse con UAC su

In base a tutto ciò, sto giungendo alla conclusione che non c'è modo semplice per fare questo. Mi sto perdendo qualcosa? Questo in realtà non sembra come dovrebbe essere così difficile. Ci si sente come UAC è stato appena mai progettato per gestire i casi di utilizzo non interattivi.

E se tutta la gente di Microsoft finiscono per la lettura di questo, ho notato che il modo in cui gestisce internamente ShellExecute elevazione è chiamando fuori per Application Information Service (AIS). Perché non è la stessa chiamata ad AIS disponibili attraverso alcuni Win32 o .NET API? http://msdn.microsoft.com/en-us/library/bb756945. aspx

Mi dispiace che correva un po 'lungo. Grazie per tutte le idee.

È stato utile?

Soluzione

Il modo "ufficiale" per rompere l'isolamento della sessione zero è di utilizzare una combinazione di servizi di terminale API e CreateProcessAsUser() di avviare un processo all'interno di una sessione utente. Al mio vecchio lavoro, abbiamo fatto proprio questo, come abbiamo bisogno di visualizzare una finestra per l'utente da un servizio prima di installare un aggiornamento scaricato Quindi, so che funziona, su WinXP, Win2K3, Vista e Win7, almeno, ma io non aspettatevi che Win 2K8 sarebbe troppo diverso. In sostanza, il processo è la seguente:

  1. Chiamata WTSGetActiveConsoleSessionId() per ottenere la sessione di console attiva id (molto importante, in quanto la sessione interattiva è non sempre sessione 1, anche su sistemi client). Questa API restituirà anche un -1 se non v'è alcun utente attivo registrato nella sessione interattiva (cioè, connessi localmente alla macchina fisica, anziché utilizzare RDP).
  2. Far passare l'id di sessione dalla chiamata API precedente WTSQueryUserToken() per ottenere un token aperto che reprents l'utente connesso alla console.
  3. Chiamata DuplicateTokenEx() per convertire il token di rappresentazione (da WTSQueryUserToken) in un token primario.
  4. Chiamata CreateEnvironmentBlock() per creare un nuovo ambiente per il processo (facoltativo, ma se non lo fai, il processo non avrà uno).
  5. Far passare il token primario dal punto # 3 in una chiamata a CreateProccessAsUser(), insieme con la riga di comando per l'eseguibile. Se è stato creato un blocco di ambiente dal passo # 4, è necessario passare il flag CREATE_UNICODE_ENVIRONMENT così (sempre). Questo può sembrare sciocco, ma l'API non riesce terribilmente se non (con ERROR_INVALID_PARAMTER).
  6. Se è stato creato un blocco di ambiente, allora avete bisogno di chiamare DestroyEnvironmentBlock, altrimenti si genererà una perdita di memoria. Il processo è dato una copia separata del blocco di ambiente quando si lancia, così si stanno distruggendo solo i dati locali.

E voilà! Finestre fa qualche magia interno, e si vede il lancio di applicazioni. Tuttavia, anche se questo lancerà e processo interattivo da un servizio, non sono sicuro se sarà bypassare UAC (ma non mi citare su questo). In altre parole, non può lanciare come un processo con privilegi elevati a meno che il Registro di sistema o manifesta interno dice di farlo, e anche allora, si potrebbe comunque ottenere un prompt UAC. Se il token si ottiene dal punto # 3 è un token limitato, si può essere in grado di utilizzare AdjustTokenPrivileges() per ripristinare la (piena) token elevato, ma non mi citare su questo, neanche. Tuttavia, come indicato nella documentazione MSDN, si prega di notare che non è possibile "aggiungere" privilegi su un token che non dispongono già di loro (ad esempio non è possibile attivare un token utente limitato in un amministratore utilizzando AdjustTokenPrivileges; il sottostante utente dovrebbe essere un amministratore per cominciare).

E 'tecnicamente possibile fare tutto questo da Win2k avanti. Tuttavia, è davvero fattibile solo a partire con WinXP, come Win2K manca la WTSGetActiveConsoleSessionId() e WTSQueryUserToken() di API (insieme a WTSEnumerateProcesses() per Win2K Pro). È possibile duro codice 0 come l'id di sessione (dal momento che è sempre il caso in Win2K), e suppongo che si potrebbe essere in grado di ottenere il token dell'utente enumerando i processi in esecuzione e duplicare una delle loro pedine (che dovrebbe essere uno che ha SID interattivo presente). Indipendentemente da ciò, il CreateProcessAsUser() si comporterà allo stesso modo quando superato un token utente interattivo, anche se non si seleziona "interagire con il desktop" dalle impostazioni del servizio. E 'anche più sicuro di lanciare direttamente dal servizio in ogni caso, in quanto il processo non erediterà il token di accesso LocalSystem divina.

Ora, non so se il suo partito app di terze fa nulla di tutto questo quando si esegue lo script / processo, ma se si vuole farlo da un servizio, che è il modo (e con Vista o Win7, è il unico modo per superare l'isolamento sessione 0).

Altri suggerimenti

A seconda del caso d'uso, si potrebbe fare quello che faccio. Mi caccia il processo winlogon per la sessione attiva e rubare la sua token. Se non c'è nessuna sessione attiva (API restituito -1), utilizzare 1 se WINVER> = 6 altrimenti 0. Il risultato è SISTEMA sulla sessione attiva.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top