9Sep
Om verschillende redenen zijn meestal beveiligingsgerelateerde PowerShell-scripts niet zo gemakkelijk draagbaar en bruikbaar als batch-scripts. We kunnen echter een batch-script bundelen met onze PowerShell-scripts om deze problemen te omzeilen. Hier laten we u een paar van die probleemgebieden zien en hoe u een batchtypen kunt bouwen om ze te omzeilen.
Waarom kan ik mijn. PS1-bestand niet kopiëren naar een andere computer en het uitvoeren?
Tenzij het doelsysteem vooraf is geconfigureerd voor het uitvoeren van willekeurige scripts, met de vereiste rechten en het gebruiken van de juiste instellingen, is de kans groot dat u een aantal problemen tegenkomt wanneer u dit probeert.
- PowerShell is standaard niet gekoppeld aan de. PS1-bestandsextensie.
We brachten dit oorspronkelijk naar voren in onze PowerShell Geek School-serie. Windows koppelt. PS1-bestanden standaard aan Kladblok in plaats van deze naar de PowerShell-opdrachtinterpreter te verzenden. Dit is om onbedoelde uitvoering van kwaadwillende scripts te voorkomen door er eenvoudig op te dubbelklikken. Er zijn manieren waarop je dit gedrag kunt veranderen, maar het is waarschijnlijk niet iets dat je wilt doen op elke computer waar je je scripts naartoe draagt - vooral als sommige van die computers niet van jezelf zijn. - PowerShell staat standaard geen externe scriptuitvoering toe.
De uitvoering ExecutionPolicy in PowerShell voorkomt standaard uitvoering van externe scripts in alle versies van Windows. In sommige Windows-versies staat de standaard helemaal geen uitvoering van scripts toe. We hebben u laten zien hoe u deze instelling kunt wijzigen in Hoe u de uitvoering van PowerShell-scripts op Windows 7 kunt toestaan. Dit is echter ook iets dat u niet op elke computer wilt doen. - Sommige PowerShell-scripts zullen niet werken zonder beheerdersrechten.
Zelfs als u werkt met een account op beheerdersniveau, moet u nog steeds Gebruikersaccountbeheer( UAC) doorlopen om bepaalde acties uit te voeren. We willen dit niet uitschakelen, maar het is nog steeds leuk als we het een beetje gemakkelijker kunnen maken om ermee om te gaan. - Sommige gebruikers hebben mogelijk aangepaste PowerShell-omgevingen.
Je zult dit waarschijnlijk niet vaak tegenkomen, maar als je dit doet, kan het draaien en probleemoplossing van je scripts een beetje frustrerend zijn. Gelukkig kunnen we dit omzeilen zonder ook maar enige permanente wijzigingen aan te brengen.
Stap 1: Dubbelklik om uit te voeren.
Laten we beginnen met het aanpakken van het eerste probleem -. PS1 bestandsassociaties. U kunt niet dubbelklikken om. PS1-bestanden uit te voeren, maar u kunt op die manier een. bat-bestand uitvoeren. We zullen dus een batchbestand schrijven om het PowerShell-script vanaf de opdrachtregel voor ons te bellen.
Dus we hoeven het batchbestand niet opnieuw te schrijven voor elk script, of elke keer dat we een script verplaatsen, maakt het gebruik van een zelfverwijzende variabele om het bestandspad voor het PowerShell-script te bouwen. Om dit te laten werken, moet het batchbestand in dezelfde map worden geplaatst als uw PowerShell-script en dezelfde bestandsnaam hebben. Dus als uw PowerShell-script 'MyScript.ps1' wordt genoemd, moet u uw batchbestand 'MyScript.bat' een naam geven en ervoor zorgen dat het zich in dezelfde map bevindt. Plaats vervolgens deze regels in het batch-script:
@ECHO OFF PowerShell.exe -Command "& '% ~ dpn0.ps1'" PAUSEAls de andere beveiligingsbeperkingen niet aanwezig waren, zou dat echt allemaal zijnhet duurt om een PowerShell-script vanuit een batchbestand uit te voeren. In feite zijn de eerste en laatste regels hoofdzakelijk een kwestie van voorkeur - het is de tweede regel die het werk echt doet. Dit is de uitsplitsing:
@ECHO OFF schakelt opdrachtuitwisseling uit. Hierdoor blijven alleen uw andere opdrachten op het scherm zichtbaar wanneer het batchbestand wordt uitgevoerd. Deze lijn is zelf verborgen door het gebruik van het symbool at( @) ervoor.
PowerShell.exe -Command "&'% ~ Dpn0.ps1' " voert feitelijk het PowerShell-script uit. PowerShell.exe kan natuurlijk worden gebeld vanuit elk CMD-venster of batchbestand om PowerShell te starten naar een kale console zoals gebruikelijk. U kunt het ook gebruiken om opdrachten rechtstreeks uit een batchbestand uit te voeren, door de -Command-parameter en de juiste argumenten op te nemen. De manier waarop dit wordt gebruikt om ons. PS1-bestand te targeten, is met de speciale variabele% ~ dpn0.Uitvoeren van een batchbestand,% ~ dpn0 evalueert naar de stationsletter, het mappad en de bestandsnaam( zonder extensie) van het batchbestand. Omdat het batchbestand en PowerShell-script zich in dezelfde map bevinden en dezelfde naam hebben, vertaalt% ~ dpn0.ps1 naar het volledige pad naar het PowerShell-script.
PAUZE pauzeert gewoon de batchuitvoering en wacht op gebruikersinvoer. Dit is over het algemeen handig om aan het einde van uw batchbestanden te hebben, zodat u de mogelijkheid hebt om de uitvoer van een opdracht te beoordelen voordat het venster verdwijnt. Terwijl we elke stap van het testen doorlopen, zal het nut hiervan duidelijker worden.
Het basisbatchbestand is dus ingesteld. Voor demonstratiedoeleinden wordt dit bestand opgeslagen als "D: \ Script Lab \ MyScript.bat" en staat er een "MyScript.ps1" in dezelfde map. Laten we eens kijken wat er gebeurt als we dubbelklikken op MyScript.bat.
Natuurlijk is het PowerShell-script niet uitgevoerd, maar dat is te verwachten - we hebben tenslotte alleen de eerste van onze vier problemen aangepakt. Er zijn echter enkele belangrijke bits hier getoond:
- De venstertitel laat zien dat het batchtype met succes PowerShell heeft gestart.
- De eerste regel uitvoer geeft aan dat een aangepast PowerShell-profiel in gebruik is. Dit is potentieel probleem # 4, hierboven vermeld.
- De foutboodschap toont ExecutionPolicy-beperkingen die van kracht zijn. Dat is ons probleem # 2.
- Het onderstreepte gedeelte van het foutbericht( dat native wordt uitgevoerd door de uitvoer van PowerShell) toont dat het batchty script het beoogde PowerShell-script correct had gericht( D: \ Script Lab \ MyScript.ps1).Dus we weten in ieder geval dat veel goed werkt.
Het profiel is in dit geval een eenvoudig script met één regel dat voor deze demonstratie wordt gebruikt om uitvoer te genereren wanneer het profiel actief is. U kunt ook uw eigen PowerShell-profiel aanpassen om dit te doen, als u deze scripts zelf wilt testen. Voeg eenvoudig de volgende regel toe aan uw profielscript:
Write-Output 'Eigen PowerShell-profiel van kracht!'De ExecutionPolicy op het testsysteem hier is ingesteld op RemoteSigned. Hierdoor kunnen scripts lokaal worden gemaakt( zoals het profielscript), terwijl scripts van externe bronnen worden geblokkeerd, tenzij ze zijn ondertekend door een vertrouwde instantie. Voor demonstratiedoeleinden werd de volgende opdracht gebruikt om MyScript.ps1 te markeren als afkomstig van een externe bron:
Add-Content -Path 'D: \ Script Lab \ MyScript.ps1' -Value "[ZoneTransfer]` nZoneId = 3 "-Stream 'Zone. Identifier'Hiermee wordt de alternatieve gegevensstroom Zone. Identifier ingesteld op MyScript.ps1, zodat Windows denkt dat het bestand afkomstig is van internet. Het kan eenvoudig worden omgekeerd met de volgende opdracht:
Clear-Content -Path 'D: \ Script Lab \ MyScript.ps1' -Stream 'Zone. Identifier'Stap 2: Kennismaking met ExecutionPolicy.
Het is vrij eenvoudig om de ExecutionPolicy-instelling te doorlopen, van CMD of een batch-script. We wijzigen gewoon de tweede regel van het script om nog een parameter toe te voegen aan de opdracht PowerShell.exe.
PowerShell.exe -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'"De parameter -ExecutionPolicy kan worden gebruikt om de uitvoeringPolicy aan te passen die wordt gebruikt wanneer u een nieuwe PowerShell-sessie maakt. Dit zal na die sessie niet blijven bestaan, zodat we PowerShell zo kunnen uitvoeren wanneer we dat nodig hebben zonder de algemene beveiligingshouding van het systeem te verzwakken. Nu we dat hebben opgelost, laten we er nog een schepje bovenop doen:
Nu het script correct is uitgevoerd, kunnen we zien wat het eigenlijk doet. Het laat ons weten dat we het script uitvoeren als een beperkte gebruiker. Het script wordt in feite uitgevoerd door een account met beheerdersrechten, maar gebruikersaccountbeheer staat in de weg. Hoewel details over hoe het script controleert of beheerderstoegang buiten het bereik van dit artikel valt, hier is de code die wordt gebruikt voor demonstratie:
if( ([Security. Principal. WindowsPrincipal] [Security. Principal. WindowsIdentity]: : GetCurrent() ). IsInRole( [Security. Principal. WindowsBuiltInRole] "Administrator")){ Write-Output 'Running as Administrator!'} Else{ Write-Output 'Running Limited!') PauzerenU zult ook merken dat er nu twee"Pauzeer" -bewerkingen in de scriptuitvoer - een uit het PowerShell-script en een uit het batchbestand. De reden hiervoor zal in de volgende stap duidelijker worden.
Stap 3: beheerderstoegang krijgen.
Als uw script geen opdrachten uitvoert die een hoogte vereisen, en u bent er vrij zeker van dat u zich geen zorgen hoeft te maken dat iemands aangepaste profielen in de weg zitten, kunt u de rest hiervan overslaan. Als je echter een paar cmdlets op beheerdersniveau gebruikt, heb je dit stuk nodig.
Helaas is er geen manier om UAC te activeren voor elevatie vanuit een batchbestand of CMD-sessie. PowerShell staat ons echter wel toe om dit te doen met Start-Process. Bij gebruik in combinatie met "-Verb RunAs" probeert Start-Process een toepassing met beheerdersrechten te starten. Als de PowerShell-sessie nog niet is verhoogd, wordt er een UAC-prompt geactiveerd. Om dit vanuit het batchbestand te gebruiken voor het starten van ons script, zullen we uiteindelijk twee PowerShell-processen opstarten - een om Start-Process af te vuren en een andere, gestart door Start-Process, om het script uit te voeren. De tweede regel van het batchbestand moet hier worden gewijzigd:
PowerShell.exe -Command "&{ Start-Process PowerShell.exe -ArgumentList '-ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "' -VerbRunAs} "Wanneer het batchbestand wordt uitgevoerd, is de eerste regel van de uitvoer die wordt weergegeven in het PowerShell-profielscript. Dan zal er een UAC-prompt verschijnen wanneer Start-Process MyScript.ps1 probeert te starten.
Nadat u door de UAC-prompt hebt geklikt, wordt een nieuwe PowerShell-instantie gemaakt. Omdat dit een nieuwe instantie is, zien we natuurlijk opnieuw het profielscript. Vervolgens wordt MyScript.ps1 uitgevoerd en we zien dat we inderdaad in een verhoogde sessie zitten.
En er is de reden dat we hier ook twee pauzes hebben. Als dat niet het geval is in het PowerShell-script, zien we nooit de uitvoer van het script: het PowerShell-venster verschijnt gewoon en verdwijnt zodra het script is voltooid. En zonder de pauze in het batchbestand kunnen we niet zien of er fouten zijn opgetreden bij het starten van PowerShell.
Stap 4: aangepaste PowerShell-profielen verkennen.
Laten we ons nu van die vervelende aangepaste profielbekendheid ontdoen, nietwaar? Hier is het nauwelijks hinderlijk, maar als het PowerShell-profiel van een gebruiker de standaardinstellingen, variabelen of functies wijzigt op manieren die je misschien niet hebt verwacht met je script, kunnen ze erg lastig zijn. Het is veel eenvoudiger om uw script zonder het profiel uit te voeren, zodat u zich hier geen zorgen over hoeft te maken. Hiervoor moeten we de tweede regel van het batchbestand nog een keer wijzigen:
PowerShell.exe -NoProfile -Command "&{ Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File" "% ~ dpn0.ps1 "" '-Verb RunAs} "Als u de parameter -NoProfile toevoegt aan beide exemplaren van PowerShell die door het script zijn gestart, betekent dit dat het profielscript van de gebruiker in beide stappen volledig wordt omzeild en ons PowerShell-script wordt uitgevoerd ineen redelijk voorspelbare, standaardomgeving. Hier kunt u zien dat er geen aangepast profielbericht is in beide uitgezette shells.
Als u geen beheerdersrechten in uw PowerShell-script nodig hebt en stap 3 hebt overgeslagen, kunt u het doen zonder de tweede PowerShell-instantie en de tweede regel van uw batchbestand moet er als volgt uitzien:
PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'"De uitvoer ziet er dan als volgt uit:
( Natuurlijk, voor niet-beheerdersscripts zou je kunnen doen zonder een einde-script-pauze in je PowerShell-scriptop dit punt ook, omdat alles in hetzelfde consolevenster wordt vastgelegd en daar toch door de pauze aan het einde van het batchbestand wordt bewaard.)
Voltooide batchbestanden.
Afhankelijk van het feit of u beheerdersbevoegdheden nodig heeft voor uw PowerShell-script( en u zou het eigenlijk niet moeten vragen als u dit niet doet), zou het uiteindelijke batchbestand eruit moeten zien als een van de onderstaande twee.
Zonder beheerdersrechten:
@ECHO OFF PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'" PAUSEMet beheerdersrechten:
@ECHO OFF PowerShell.exe -NoProfile -Command "&{Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""% ~ dpn0.ps1 ""' -Verb RunAs} "PAUSEVergeet niet om het batchbestand in dezelfde map te plaatsen als het PowerShell-script dat u wiltom het te gebruiken voor, en geef het dezelfde naam. Vervolgens, ongeacht het systeem waar u deze bestanden naartoe kunt nemen, kunt u uw PowerShell-script uitvoeren zonder dat u zich hoeft bezig te houden met de beveiligingsinstellingen op het systeem. Je zou die veranderingen zeker elke keer handmatig kunnen doen, maar dit bespaart je problemen en je hoeft je geen zorgen te maken over het later terugdraaien van de wijzigingen.
Referenties:
- PowerShell-scripts uitvoeren vanuit een batchbestand - Daniel Schroeder's programmeerblog
- Controleren op beheerdersmachtigingen in PowerShell - Hey, Scripting Guy! Blog