2010-03-11 10 views
14

Używam usługi Thrid Party Windows, która obsługuje niektóre zadania automatyzacji, uruchamiając skrypty i pliki wykonywalne za pomocą metody CreateProcessAsUser(). Występują problemy w systemie Windows Server 2008 ze względu na UAC i sposób obsługi LUA elewacji za pośrednictwem interfejsów API.uruchamianie procesu podwyższonego poziomu UAC z usługi nieinteraktywnej (win32/.net/powershell)

Usługa działa jako LocalSystem i nie ma włączonej opcji "Interakcja z pulpitem". Procesy są uruchamiane jako użytkownicy w grupie Administratorzy, ale nie konto administratora (które jest zwolnione z wielu ograniczeń UAC). Wszystkie domyślne ustawienia UAC.

Potrafię przekazywać dowolne polecenia lub kod typu powershell do usługi, ale nie mogę "wyrwać" się z nie-podniesionego, nieinteraktywnego procesu, który zostaje uruchomiony przez usługę.

Sedno problemu wydaje się, że jedyną (publiczną) opcją API do uruchomienia podwyższonego procesu jest ShellExecute() z czasownikiem "runas", ale o ile mogę stwierdzić, że nie można go wywołać z nieinteraktywna usługa lub otrzymujesz błędy typu "Ta operacja wymaga interaktywnej stacji okiennej".

Jedyne obejście znalazłem wymienione poniżej: http://www.eggheadcafe.com/software/aspnet/29620442/how-to-proper-use-sendinp.aspx

W Vista, oficjalny udokumentowany sposób wznieść proces używa tylko API powłoki ShellExecute (Ex) (nie CreateProcess lub CreateProcessAsUser). Twoja aplikacja musi zadzwonić pod numer ShellExecute (Ex), aby uruchomić helpera podniesiony do wywołania SendInput. Ponadto, ze względu na Sesji 0 izolacji, usługa może używać CreateProcessAsUser lub CreateProcessWithLogonW tylko (nie można używać ShellExecute (Ex)), aby określić interaktywny pulpit.

.. Myślę, że nie ma bezpośredniej drogi do odradzania podwyższonego procesu z usługi okiennej . Możemy najpierw użyć tylko CreateProcessAsUser lub CreateProcessWithLogonW, aby odradzić nieukierunkowany proces w sesji użytkownika (pulpit interaktywny). Następnie w procesie nie podniesionym może użyć ShellExecute (Ex), aby spawnować podniesiony proces dla prawdziwego zadania.

Aby to zrobić z kodu .net/PowerShell, wygląda na to, że będę musiał zrobić trochę skomplikowany P/Invoke rzeczy, aby zadzwonić CreateProcessAsUser lub CreateProcessWithLogonW od Net System.Diagnostics.ProcessStartInfo nie mieć odpowiednik lpDesktop, który mógłbym ustawić na "winsta0 \ default". I nie jestem pewien, czy LocalSystem ma nawet prawa do wywoływania CreateProcessAsUser lub CreateProcessWithLogonW.

ja również spojrzał na http://blogs.msdn.com/alejacma/archive/2007/12/20/how-to-call-createprocesswithlogonw-createprocessasuser-in-net.aspx i Process.Start with different credentials with UAC on

oparciu o to wszystko, mam dochodząc do wniosku, że nie ma prostego sposobu, aby to zrobić. Czy czegoś brakuje? To naprawdę nie wygląda na to, że powinno być tak trudne. Wydaje się, że UAC nigdy nie był zaprojektowany do obsługi nieinteraktywnych przypadków użycia.

i jeśli ludzie Microsoft skończyć czytanie tego, zauważyłem, że sposób ShellExecute wewnętrznie obsługuje elewację jest wołając do Application Information Service (AIS). Dlaczego to samo połączenie z AIS nie jest dostępne przez niektóre API Win32 lub .NET? http://msdn.microsoft.com/en-us/library/bb756945.aspx

Przepraszam, że trwało to trochę długo. Dzięki za wszelkie pomysły.

+0

Mówiąc raczej, że Server Core nie obsługuje UAC. Wydaje się, że potwierdzam moją ocenę. http://blogs.technet.com/server_core/archive/2009/01/19/user-account-control-uac-and-server-core.aspx –

+0

Zobacz mój post tutaj, który wyjaśnia, w jaki sposób, w szczególności spójrz na LinkedToken sekcja: http://brianbondy.com/blog/id/100/understanding-windows-at-a-deeper-level-sessions-window-stations-and-desktops –

Odpowiedz

16

"Oficjalnym" sposobem na przerwanie izolacji sesji zerowej jest użycie kombinacji usług terminalowych API i CreateProcessAsUser() w celu uruchomienia procesu w sesji użytkownika. W mojej starej pracy właśnie to zrobiliśmy, ponieważ musieliśmy wyświetlić okno dialogowe do użytkownika z usługi przed zainstalowaniem pobranej aktualizacji. Tak, wiem, że to działa, przynajmniej na WinXP, Win2K3, Vista i Win7, ale ja nie oczekuj, że Win 2K8 będzie zbyt różne. Zasadniczo, proces przebiega następująco:

  1. połączeń WTSGetActiveConsoleSessionId() aby uzyskać aktywny identyfikator sesji konsoli (bardzo ważne, ponieważ sesja interaktywna jest NIE zawsze sesja 1, nawet na systemach klienckich). Ten interfejs API również zwróci wartość -1, jeśli w sesji interaktywnej nie jest zalogowany żaden aktywny użytkownik (to znaczy zalogowany lokalnie na komputerze fizycznym, w przeciwieństwie do korzystania z protokołu RDP).
  2. Przepuścić identyfikator sesji z poprzedniego wywołania API do WTSQueryUserToken(), aby uzyskać otwarty token, który odświeża użytkownika zalogowanego do konsoli.
  3. połączeń DuplicateTokenEx() przekonwertować token personifikacji (od WTSQueryUserToken) do pierwotnej tokena.
  4. połączeń CreateEnvironmentBlock() stworzyć nowe środowisko dla procesu (opcjonalnie, ale jeśli nie, proces nie będzie miał jeden).
  5. Przekaż główny token z kroku 3 do wywołania CreateProccessAsUser() wraz z wierszem polecenia dla pliku wykonywalnego. Jeśli utworzyłeś blok środowiska z kroku 4, musisz również podać flagę CREATE_UNICODE_ENVIRONMENT (zawsze). To może wydawać się głupie, ale API nie działa strasznie, jeśli nie (z ERROR_INVALID_PARAMTER).
  6. Jeśli utworzyłeś blok środowiska, musisz zadzwonić pod numer DestroyEnvironmentBlock, w przeciwnym razie wygenerujesz wyciek pamięci. Po uruchomieniu procesu otrzymuje się osobną kopię bloku środowiska, więc niszczymy tylko lokalne dane.

i voila! Windows robi trochę wewnętrznej magii i widzisz uruchomienie aplikacji. Jednak mimo tego, że uruchomi się i interaktywny proces z usługi, nie jestem pewien, czy to obejmie UAC (ale nie cytuj mnie na ten temat). Innymi słowy, nie może być uruchamiany jako proces zaawansowany, chyba że rejestr lub wewnętrzny manifest mówi, aby to zrobić, a nawet wtedy, nadal będzie można uzyskać monit UAC. Jeśli token z kroku 3 jest tokenem ograniczonym, możesz użyć AdjustTokenPrivileges(), aby przywrócić podniesiony (pełny) token, ale nie cytuj mnie też na tym. Jednak, jak stwierdzono w dokumentach MSDN, należy pamiętać, że nie jest możliwe "dodawanie" uprawnień do tokena, który ich jeszcze nie ma (np. Nie można zamienić tokenu ograniczonego użytkownika na administratora przy użyciu AdjustTokenPrivileges; użytkownik musiałby być administratorem, od którego należy zacząć).

Jest to technicznie możliwe, aby zrobić to wszystko z Win2K do przodu. Jednak naprawdę jest to możliwe tylko od wersji WinXP, ponieważ Win2K nie ma interfejsów API WTSGetActiveConsoleSessionId() i WTSQueryUserToken() (wraz z WTSEnumerateProcesses() dla Win2K Pro). Możesz utrudnić kod 0 jako identyfikator sesji (ponieważ tak jest zawsze w Win2K), i przypuszczam, że możesz uzyskać token użytkownika, wyliczając działające procesy i duplikując jeden z ich tokenów (powinien to być taki, który ma interaktywny SID obecny).Niezależnie od tego, CreateProcessAsUser() zachowa się w taki sam sposób, gdy zostanie przekazany interaktywny token użytkownika, nawet jeśli nie wybierzesz opcji "Interakcja z pulpitem" w ustawieniach usługi. Jest to również bezpieczniejsze niż uruchamianie bezpośrednio z usługi, ponieważ proces ten nie odziedziczy godnego dostępu tokenów LocalSystem.

Teraz nie wiem, czy twoja aplikacja innej firmy robi to podczas uruchamiania skryptu/procesu, ale jeśli chcesz to zrobić z usługi, tak (w przypadku Vista lub Win7 to jedyny sposób na pokonanie izolacji sesji 0).

+3

Nie ma potrzeby wywoływania 'DuplicateTokenEx'. 'CreateProcessAsUser' uruchomiłby proces z tokenem uzyskanym z' WTSQueryUserToken'. Twoja odpowiedź jest dość szczegółowa, ale nie odpowiada "Jak rozpocząć podniesiony proces z usługi?" (UAC włączony) " – Ajay

+1

Rzeczywiście tak nie jest. W ten sposób otrzymasz ograniczony token. – Joshua

+0

Jest kilka rzeczy do zapamiętania: 1) Jak @Ajay wspomina 'WTSQueryUserToken' zwraca już token podstawowy, więc możesz pominąć krok 3. 2) Przy włączonym UAC, po kroku 2 musisz uzyskać tzw. Token połączony. , które robisz, wywołując 'GetTokenInformation' z klasą informacyjną' TokenLinkedToken', ale tylko jeśli zapytanie 'TokenElevationType' mówi, że elewacja jest ograniczona. 3) Jeśli nie utworzysz bloku środowiska, nowy proces będzie miał środowisko procesu tworzenia, który jest twoją usługą –

1

W zależności od przypadku użycia można zrobić to, co robię. Wyszukuję proces winlogon dla aktywnej sesji i kradnę jej token. Jeśli nie ma aktywnej sesji (API zwróciło -1), użyj 1, jeśli WINVER> = 6 w przeciwnym razie 0. To spowoduje SYSTEM w aktywnej sesji.

Powiązane problemy