If-Koubou

Jak korzystać z pliku wsadowego, aby skrypty PowerShell łatwiej działały

Jak korzystać z pliku wsadowego, aby skrypty PowerShell łatwiej działały (Jak)

Z kilku powodów, głównie związane z bezpieczeństwem, skrypty PowerShell nie są tak łatwe w użyciu i przenośne jak skrypty wsadowe. Możemy jednak łączyć skrypt wsadowy ze skryptami PowerShell, aby obejść te problemy. Tutaj pokażemy kilka z tych problematycznych obszarów i jak zbudować skrypt wsadowy, aby je ominąć.

Dlaczego nie mogę skopiować pliku .PS1 na inny komputer i uruchomić go?

O ile system docelowy nie został wstępnie skonfigurowany w celu umożliwienia uruchamiania dowolnych skryptów, wymaganych uprawnień i użycia właściwych ustawień, istnieje ryzyko, że napotkasz problemy podczas próby wykonania tego.

  1. PowerShell nie jest domyślnie skojarzony z rozszerzeniem .PS1.
    Wprowadziliśmy to początkowo w naszej serii PowerShell Geek School. Windows domyślnie kojarzy pliki .PS1 z Notatnikiem, zamiast wysyłać je do interpretera poleceń PowerShell. Ma to na celu zapobieganie przypadkowemu uruchamianiu złośliwych skryptów poprzez dwukrotne kliknięcie ich. Są sposoby na zmianę tego zachowania, ale prawdopodobnie nie jest to coś, co chcesz zrobić na każdym komputerze, na którym masz swoje skrypty - zwłaszcza jeśli niektóre z tych komputerów nie są twoje.
  2. PowerShell domyślnie nie pozwala na zewnętrzne wykonywanie skryptów.
    Ustawienie ExecutionPolicy w PowerShell zapobiega domyślnemu uruchamianiu zewnętrznych skryptów we wszystkich wersjach systemu Windows. W niektórych wersjach systemu Windows ustawienie domyślne nie pozwala na wykonanie skryptu. Pokazaliśmy, jak zmienić to ustawienie w Jak umożliwić wykonywanie skryptów PowerShell w systemie Windows 7. Jednak jest to również coś, czego nie chcesz robić na żadnym komputerze.
  3. Niektóre skrypty PowerShell nie będą działały bez uprawnień administratora.
    Nawet działając z kontem na poziomie administratora, nadal musisz przejść przez kontrolę konta użytkownika (UAC), aby wykonać określone czynności. Nie chcemy tego wyłączać, ale nadal jest przyjemnie, kiedy możemy sobie z tym poradzić.
  4. Niektórzy użytkownicy mogą mieć dostosowane środowiska PowerShell.
    Prawdopodobnie nie natkniesz się na to często, ale kiedy to zrobisz, możesz sprawić, że uruchamianie i rozwiązywanie problemów z twoimi skryptami będzie trochę frustrujące. Na szczęście możemy obejść to bez wprowadzania stałych zmian.

Krok 1: Kliknij dwukrotnie, aby uruchomić.

Zacznijmy od zaadresowania pierwszego problemu - powiązań plików .PS1. Nie można dwukrotnie kliknąć, aby uruchomić pliki .PS1, ale można w ten sposób wykonać plik .BAT. Tak więc, napiszemy plik wsadowy, aby wywołać skrypt PowerShell z linii poleceń dla nas.

Nie musimy więc ponownie pisać pliku wsadowego dla każdego skryptu lub za każdym razem, gdy przenosimy skrypt, użyjemy zmiennej samodopasującej do zbudowania ścieżki pliku dla skryptu PowerShell. Aby to działało, plik wsadowy musi być umieszczony w tym samym folderze, co skrypt PowerShell i mieć tę samą nazwę pliku. Jeśli więc twój skrypt PowerShell nazywa się "MyScript.ps1", będziesz chciał nazwać swój plik wsadowy "MyScript.bat" i upewnić się, że jest w tym samym folderze. Następnie umieść te linie w skrypcie wsadowym:

@ECHO OFF PowerShell.exe -Command "& '% ~ dpn0.ps1'" PAUSE

Gdyby nie inne ograniczenia bezpieczeństwa, wystarczyłoby uruchomienie skryptu PowerShell z pliku wsadowego. W rzeczywistości pierwsza i ostatnia linia to głównie kwestia preferencji - to druga linia naprawdę wykonuje pracę. Oto podział:

@ECHO OFF wyłącza echo poleceń. Dzięki temu pozostałe polecenia nie będą wyświetlane na ekranie podczas działania pliku wsadowego. Linia ta jest sama ukryta za pomocą symbolu at (@) przed nią.

PowerShell.exe - Polecenie "&"% ~ dpn0.ps1 "" faktycznie uruchamia skrypt PowerShell. PowerShell.exe można oczywiście wywołać z dowolnego okna CMD lub pliku wsadowego, aby uruchomić PowerShell na zwykłej konsoli. Można go również użyć do uruchamiania poleceń bezpośrednio z pliku wsadowego, włączając parametr -Command i odpowiednie argumenty. Sposób w jaki cel ten jest kierowany na nasz plik .PS1 jest ze specjalną zmienną% ~ dpn0. Uruchom z pliku wsadowego,% ~ dpn0 ocenia literę dysku, ścieżkę folderu i nazwę pliku (bez rozszerzenia) pliku wsadowego. Ponieważ plik wsadowy i skrypt PowerShell znajdują się w tym samym folderze i mają tę samą nazwę, plik% ~ dpn0.ps1 zostanie przetłumaczony na pełną ścieżkę do pliku skryptu PowerShell.

PAUZA po prostu przerywa wykonywanie wsadowe i czeka na wprowadzenie danych przez użytkownika. Na ogół jest to przydatne na końcu plików wsadowych, dzięki czemu masz szansę przejrzenia dowolnego polecenia, zanim zniknie okno. Kiedy będziemy testować każdy krok, użyteczność tego stanie się bardziej oczywista.

Zatem podstawowy plik wsadowy jest skonfigurowany. W celach demonstracyjnych plik ten jest zapisywany jako "D: \ Script Lab \ MyScript.bat", aw tym samym folderze znajduje się plik "MyScript.ps1". Zobaczmy, co się stanie, gdy dwukrotnie klikniemy MyScript.bat.

Oczywiście skrypt PowerShell nie działał, ale można się tego spodziewać - w końcu rozwiązaliśmy tylko pierwszy z naszych czterech problemów. Jednak tutaj pokazano kilka ważnych bitów:

  1. Tytuł okna pokazuje, że skrypt wsadowy pomyślnie uruchomił PowerShell.
  2. Pierwszy wiersz danych wyjściowych pokazuje, że niestandardowy profil PowerShell jest w użyciu. Jest to potencjalny problem nr 4, wymieniony powyżej.
  3. Komunikat o błędzie pokazuje obowiązujące ograniczenia ExecutionPolicy. To nasz problem # 2.
  4. Podkreślona część komunikatu o błędzie (wykonywana natywnie przez wyjście błędów programu PowerShell) pokazuje, że skrypt wsadowy poprawnie atakował zamierzony skrypt PowerShell (D: \ Script Lab \ MyScript.ps1). Więc przynajmniej wiemy, że wiele działa poprawnie.

Profil, w tym przypadku, jest prostym, jednokreskowym skryptem używanym do tej demonstracji do generowania danych wyjściowych za każdym razem, gdy profil jest aktywny. Możesz również dostosować swój profil PowerShell, aby to zrobić, jeśli chcesz przetestować te skrypty samemu. Po prostu dodaj następujący wiersz do swojego skryptu profilu:

"Niestandardowy profil PowerShell Write-Output"!

Opcja ExecutionPolicy w systemie testowym jest ustawiona na RemoteSigned. Pozwala to na wykonywanie skryptów tworzonych lokalnie (jak skrypt profilu), blokując skrypty ze źródeł zewnętrznych, chyba że są podpisane przez zaufane instytucje. Do celów demonstracyjnych użyto następującej komendy do oznaczenia pliku MyScript.ps1 jako pochodzącego ze źródła zewnętrznego:

Add-Content -Path 'D: \ Script Lab \ MyScript.ps1' -Value "[ZoneTransfer] 'nZoneId = 3" -Stream' Zone.Identifier '

To ustawia alternatywny strumień danych Zone.Identifier w MyScript.ps1, aby system Windows mógł myśleć, że plik pochodzi z Internetu. Można go łatwo odwrócić za pomocą następującego polecenia:

Wyczyść-treść -Path 'D: \ Script Lab \ MyScript.ps1' -Stream 'Zone.Identifier'

Krok 2: Omówienie ExecutionPolicy.

Obejście ustawienia ExecutionPolicy z CMD lub skryptu wsadowego jest w rzeczywistości dość łatwe. Po prostu modyfikujemy drugą linię skryptu, aby dodać jeszcze jeden parametr do polecenia PowerShell.exe.

PowerShell.exe - ExecutionPolicy Bypass - Komenda "&"% ~ dpn0.ps1 ""

Parametr -ExecutionPolicy może zostać użyty do zmodyfikowania metody ExecutionPolicy używanej podczas tworzenia nowej sesji PowerShell. Nie będzie to trwało dłużej niż ta sesja, więc możemy uruchamiać program PowerShell w taki sposób, ilekroć zajdzie taka potrzeba, bez osłabiania ogólnej pozycji bezpieczeństwa systemu. Teraz, gdy już to naprawiliśmy, przejdźmy do kolejnego:

Teraz, gdy skrypt został poprawnie wykonany, możemy zobaczyć, co on właściwie robi. Informuje nas, że uruchamiamy skrypt jako użytkownik z ograniczonym dostępem. Skrypt jest uruchamiany przez konto z uprawnieniami administratora, ale kontrola konta użytkownika staje na przeszkodzie. Chociaż szczegóły tego, w jaki sposób skrypt sprawdza dostęp administratora, są poza zakresem tego artykułu, oto kod, który jest używany do demonstracji:

if (([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity] :: GetCurrent ()) .IsInRole ([Security.Principal.WindowsBuiltInRole] "Administrator")) Write-Output "Działa jako administrator!" else Write-Output 'Running Limited!' Wstrzymaj

Zauważysz także, że w wyjściu skryptu są teraz dwie operacje "Wstrzymaj" - jedną ze skryptu PowerShell, a drugą z pliku wsadowego. Powód tego będzie bardziej widoczny w następnym kroku.

Krok 3: Uzyskanie dostępu administratora.

Jeśli twój skrypt nie uruchamia żadnych poleceń, które wymagają podniesienia, i jesteś pewien, że nie będziesz musiał się martwić, że jakiekolwiek niestandardowe profile przeszkadzają, możesz pominąć resztę. Jeśli jednak używasz niektórych cmdletów na poziomie administratora, potrzebujesz tego fragmentu.

Niestety, nie ma sposobu na wyzwolenie UAC do podniesienia z pliku wsadowego lub sesji CMD. Jednak PowerShell pozwala nam to zrobić w Start-Process. W przypadku użycia z "-Verb RunAs" w swoich argumentach, Start-Process spróbuje uruchomić aplikację z uprawnieniami administratora. Jeśli sesja PowerShell nie została jeszcze podniesiona, spowoduje to wyświetlenie monitu UAC. Aby użyć tego z pliku wsadowego do uruchomienia naszego skryptu, skończymy z utworzeniem dwóch procesów PowerShell - jeden do uruchomienia procesu Start i innego, uruchamianego przez Start-Process, w celu uruchomienia skryptu. Druga linia pliku wsadowego musi zostać zmieniona na:

PowerShell.exe - Polecenie "& Rozpocznij przetwarzanie PowerShell.exe -ArgumentList" -ExecutionPolicy Bypass -File ""% ~ dpn0.ps1 "" "-Verb RunAs"

Po uruchomieniu pliku wsadowego pierwszy wiersz danych wyjściowych będzie pochodził ze skryptu profilu PowerShell. Następnie pojawi się monit UAC, gdy Start-Process spróbuje uruchomić MyScript.ps1.

Po kliknięciu w monit UAC pojawi się nowa instancja PowerShell. Ponieważ jest to nowa instancja, oczywiście, zobaczymy ponownie powiadomienie dotyczące profilu. Następnie działa MyScript.ps1 i widzimy, że rzeczywiście jesteśmy w podwyższonej sesji.

I tu jest powód, dla którego mamy tu dwie przerwy. Gdyby nie ten, który znajduje się w skrypcie PowerShell, nigdy nie zobaczylibyśmy wyjścia skryptu - okno PowerShell po prostu wyskakuje i znika, gdy tylko skrypt zostanie uruchomiony. Bez zatrzymania się w pliku wsadowym nie bylibyśmy w stanie stwierdzić, czy były jakieś błędy uruchamiające PowerShell.

Krok 4: Poruszanie się po niestandardowych profilach PowerShell.

Pozbądźmy się teraz tego paskudnego powiadomienia o profilu niestandardowym, dobrze? W tym przypadku nie jest to bardzo uciążliwe, ale jeśli profil PowerShell użytkownika zmienia ustawienia domyślne, zmienne lub funkcje w sposób, jakiego mógłbyś nie przewidzieć przy swoim skrypcie, mogą one być naprawdę kłopotliwe. O wiele łatwiej jest uruchomić swój skrypt bez profilu, więc nie musisz się o to martwić. Aby to zrobić, wystarczy jeszcze raz zmienić drugą linię pliku wsadowego:

PowerShell.exe -NoProfile -Command "& Rozpocznij przetwarzanie PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "" -Verb RunAs "

Dodanie parametru -NoProfile do obu wystąpień programu PowerShell uruchamianych przez skrypt oznacza, że ​​skrypt profilu użytkownika zostanie całkowicie pominięty w obu krokach, a nasz skrypt PowerShell będzie działał w dość przewidywalnym, domyślnym środowisku. Tutaj możesz zauważyć, że w żadnej z zarodkowanych powłok nie ma niestandardowego powiadomienia o profilu.

Jeśli nie potrzebujesz uprawnień administratora w skrypcie PowerShell, a pominiesz krok 3, możesz obejść się bez drugiej instancji PowerShell, a druga linia pliku wsadowego powinna wyglądać tak:

PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1" "

Dane wyjściowe będą wyglądały następująco:

(Oczywiście, w przypadku skryptów innych niż Administrator, w tym momencie można by zrobić bez pauzy końca skryptu w skrypcie PowerShell, ponieważ wszystko jest przechwytywane w tym samym oknie konsoli i będzie tam trzymane przez przerwę na końcu plik wsadowy mimo to.)

Zakończone pliki wsadowe.

W zależności od tego, czy potrzebujesz uprawnień administratora do skryptu PowerShell (i naprawdę nie powinieneś żądać ich, jeśli tego nie robisz), ostateczny plik wsadowy powinien wyglądać jak jeden z dwóch poniższych.

Bez dostępu administratora:

@ECHO OFF PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'" PAUSE

Z dostępem administracyjnym:

@ECHO OFF PowerShell.exe -NoProfile -Command "& Rozpocznij przetwarzanie PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "" -Verb RunAs "PAUSE

Pamiętaj, aby umieścić plik wsadowy w tym samym folderze, co skrypt PowerShell, dla którego chcesz go użyć, i nadaj mu tę samą nazwę. Wtedy, bez względu na to, do jakiego systemu przeniesiesz te pliki, będziesz mógł uruchomić swój skrypt PowerShell, bez konieczności obrzucania go jakimikolwiek ustawieniami bezpieczeństwa w systemie. Z pewnością możesz ręcznie wprowadzić te zmiany za każdym razem, ale to oszczędza ci kłopotów i nie będziesz musiał się martwić, że później powrócisz.

Referencje:

  • Uruchamianie skryptów PowerShell z pliku wsadowego - Blog programistyczny Daniela Schroedera
  • Sprawdzanie uprawnień administratora w PowerShell - Hej, skrypciarze! Blog