Archiv der Kategorie: Tipps

Kleine Tipps für Zwischendurch: Eine IP-Adresse als Binärzahl ausgeben

Vielleicht gibt es eine einfachere Variante, aber bei der Folgenden gefällt mit die Unmsetzung gut:

So sieht die Adresse als Binärzahl aus:

Chocolatey mit Chocolatey installieren

Laut „Der Postillon“ ist das Henne oder Ei-Problem endlich gelöst: Das Ei war zuerst da.

Ein wenig erinnert mich diese humorvolle Meldung an die Installation der Package Managers Chocolatey per Install-Package und dem Chocolatey-Provider, der aber nachträglich installiert werden muss. Dank des ForceBootstrap-Parameters ist das kein Problem.

Der Pfad von Choco.exe muss allerdings zu Fuß zur Path-Umgebungsvariablen hinzugefügt werden:

Kleine Besonderheiten beim Umgang mit einer OrderedDictionary-Collection und wie man sie löst

Nach mehr als 10 Jahren intensiver PowerShell-Nutzung komme ich immer öfter in Situationen, in die Art und Weise wie PowerShell mit (Daten-) Typen umgeht einiges an Nerven kostet und ich mehr und mehr frage, ob dies bei richtigen Skriptsprachen wie Python oder Ruby auch so ist. Ein „Fehler“ aus heutiger Sicht war sicherlich, dass das PowerShell-Team damals im Jahr 2004 das Typensystem des .NET Framework übernommen hatte, das damals selber noch ganz neu war und erst in der Version 1.1 vorlag. Aus meiner Sicht wäre es besser gewesen, wenn die PowerShell-Entwickler damals ein eigenes Typensystem implementiert und sich nur so wenig wie möglich an das .NET-Typensystem angedockt hätten. Aber diese Option gab es damals nicht.

Die „Besonderheit“, um die es in diesem Blog-Beitrag geht, wird nur auf den zweiten Blick deutlich. Ausgangspunkt ist eine Hashtable, also eine Liste von Schlüssel=Wert-Paaren. Hier ein Beispiel:

Bis zu diesem Punkt ist hoffentlich alles klar. Wir haben eine Hashtable mit drei Schlüssel-Wert-Paaren. Die Schlüssel sind „1000“, „2000“ und „3000“.

Ein Problem mit Hashtables ist, dass es keine Garantie gibt, dass die Elemente in der Folge ausgegeben werden, in der sie hinzugefügt wurden. Um dieses Problem zu umgehen, muss dem @{} nur ein [Ordered] vorangestellt werden.

Jetzt bleibt die Reihenfolge erhalten. Der Grund dafür ist ganz einfach, dass die Hashtable keine Hashtable mehr ist. Die Variable H steht jetzt für ein OrderedDictionary. Das bedeutet unter anderem, dass die Methode ContainsKey für das Abfragen eines Schlüsselwertes nicht mehr vorhanden ist. Ein Skript, dass diese Methode verwendet, muss daher angepasst werden.

Sehr viel schwerer wiegt, dass die Verwendung des Schlüsselwertes nicht mehr funktioniert.

Ein

führt zu keinem Ergebnis mehr. Ein Wert wird über die allgemeine Item()-Methode abgerufen. Aber auch hier gibt es eine „Besonderheit“. Damit der Wert als Schlüssel und nicht als Index erkannt wird, muss der vom Typ Object sein.

Ein

liefert wieder nichts. Ein

liefert den Wert „Wert 1“.

Bei solchen Klimmzügen frage ich immer, wenn ich mit meinen 10+ Jahren PowerShell-Know how ins Schwimmen komme und einiges probieren muss, um zu gewünschten Ergebnis zu kommen (allerdings komplett ohne Internet-Recherche), wie soll es ein typischer PowerShell-Anwender ohne Programmiererfahrung schaffen?

Die Lösung für die ganze „Hashtable-Problematik“ besteht für mich darin, auf das [Ordered] zu verzichten und damit zu leben, dass die Reihenfolge der Werte nicht der Reihenfolge entspricht, in der die Werte zur Hashtable hinzugefügt wurden.

PS: Ein kleiner Trick fiel mir beim Schreiben des letzten Absatzes ein: Per Typenkonvertierung in eine Hashtable verhält sich das OrderedDictionary wieder wie eine Hashtable und es gibt z.B. eine ContainsKey()-Methode.

Damit funktioniert auch der Zugriff über den Schlüssel wieder wie gewohnt:

Praxistipp: RDP per PowerShell aktivieren

Der folgende Tipp ist eher ein „Note to self“, da man ihn „tausendfach“ im Internet findet. Eventuell nicht ganz so übersichtlich wie in meinem Blog.

Auf einemn frisch installierten Windows Server ist der RDP-Zugriff von außen zunächst deaktiviert.

Das folgende kleine PowerShell-Skript aktiviert den RDP-Zugriff. Im Kern geht es darum, ein bzw. zwei Einträge in der Registry zu setzen und eine Firewall-Regel zu aktivieren. Das muss natürlich nicht unbedingt per PowerShell-Remoting umgesetzt werden. Auch für das Setzen der Firewall-Regel gibt es zahlreiche Alternativen.

Die folgende Anleitung ist daher auch nur eine von vielen. Sie funktioniert in dieser Form erst ab Windows Server 2012 aufwärts, da hier PS-Remoting von Anfang an aktiv ist. Benutzername, einbruchsicheres Kennwort und IP-Adresse bitte anpassen.

Mal eben Irfanview installieren

Ich liebe die Idee einer Paketverwaltung per Befehlszeile. Die Freiheit, an die mich nach den ersten Schritten mit Linux schnell gewöhnt habe, schätze ich auch unter Windows. Bekanntlich bringt PowerShell ab Version 5.0 einen „Paket-Manager-Manager“ mit, aber irgendwie habe ich seit Jahren das Gefühl er ist trotz einer guten Idee und einer halbwegs soliden Umsetzung „broken by design“.

Vor kurzem bin ich wieder einmal daran gescheitert das praktische Grafiktool Irfanview, das jede Menge Bildateiformate beherrscht und z.B. für das Verkleinern von Bitmaps sehr gut geeignet ist, per PowerShell zu installieren.

Eigentlich ganz einfach, doch der folgende Befehl brachte keinen Erfolg:

Es wurde lediglich das Setup-Programm für Irfanview heruntergeladen, aber offenbar nicht ausgeführt.

Vermutlich lag es daran, dass bei Windows 10 am Anfang keine Skripte ausgeführt werden dürfen. Ich habe es nach Setzen der Ausführungsrichtlinie aber nicht erneut probiert, sondern stattdessem dem Chocolatey-Paketmanager installiert:

Annschließend

Choco.exe stellt fest, dass IrfanView bereits installiert sein soll. Also noch einmal, dieses Mal mit dem beliebten f-Parameter:

Jetzt läuft es durch und etwas später befindet sich im Programme-Verzeichnis ein Verzeichnis IrfanView mit einer Programmdatei i_view64.exe.

Die Verknüpfung auf dem Desktop muss man allerdings zu Fuß anlegen. Einen PowerShell-Befehl gibt es dafür leider nicht.

Tipp: Wie immer enorm hilfreich, um Dateien aufzuspüren: UltraSearch von JAM Software (http://www.jam-software.de)

Eine echte Registry-Suche nach Einträgen

Eine Registry-Suche per PowerShell ist zunächst ganz einfach.

Der folgende Befehl durchsucht den Schlüssel HKey_Local_Machine\Software nach Schlüsseln, deren Name das Wort „Powershell“ enthält.

Das Problem: Die Suche wird nur mit den Schlüsselnamen durchgeführt. Das Ergebnis sind daher auch nur Objekte (vom Typ Microsoft.Win32.RegistryKey), die einzelne Schlüssel repräsentieren, auch wenn die Einträge und Werte jedes Schlüssels mitausgegeben werden.

Wer jetzt denkt, so schwer kann es nicht sein, ich muss lediglich den Output des dir-Kommandos zerlegen bzw. per Where-Object abfragen, so einfach geht es leider nicht. Wie schon oben erwähnt, die Rückgabe besteht aus „nackten“ Microsoft.Win32.RegistryKey-Objekten, an die die Einträge und ihre Werte leider nicht vom Typensystem der PowerShell angehängt werden (vermutlich aus Performancegründen).

Möchte man nach Einträgen suchen, wird es zwangsläufig etwas komplizierter. Für viele leider etwas zu kompliziert. Ich bin selber am Anfang meiner „Karriere“ als PowerShell-Anwender einige Male an einer Lösung gescheitert. Zumindestens an einer, die halbwegs nachvollziehbar war und die ich selber ein paar Monate später noch verstanden habe. Mir war einfach nicht klar, wie ich damit umgehen sollte, dass ein Get-ItemProperty alle Einträge eines Reg-Schlüssels in Gestalt eines PSCustomObject-Objekts zurückgibt, an das die Einträge als Properties angehängt wurden. Die Lösung natürlich: Über die psobject-Eigenschaft.

Ich hoffe, dass die folgende Function nachvollziehbar ist.

Tipp: Über die ISO-Datei an die Versionsnummer eines Windows-Image herankommen

Wer Windows 10 über das Media Creation Tool herunterlädt, erhält eine ISO-Datei mit dem unscheinbaren Namen Windows.iso. Nicht sehr aussagekräftig. Auch wenn man davon ausgehen darf, dass dies stets die aktuelleste offizielle Windows 10-Version ist, ein paar Wochen später ist das eventuell nicht mehr so eindeutig.

Natürlich kann man die Versionsnummer, zusammen mit vielen anderen Details, abfragen. Entweder per Dism.exe oder per Get-WindowsImage aus dem Dism-Modul.

Die PowerShell muss dazu als Administrator gestartet werden. Für beide Aufrufe wurde die Iso-Datei als Laufwerk gemounted. Dazu genügt ein Doppelklick auf die Datei.

oder

In beiden Fällen ist die Build-Nummer, z.B. 16299, Teil der Ausgabe.

Ein wenig kurios ist, dass der Index einmal 1 und einmal 7 ist, aber das wird schon seine Gründe haben;)

Aus aktuellem Anlass: Spectre und Meltdown-Check per PowerShell-Modul

Man glaubt zwar immer nach den „Skandalen“ der jüngsten Vergangenheit, dass es in Bezug auf Sicherheitslücken in IT-Systemen nicht schlimmer kommen kann, aber dann kommt es doch noch schlimmer. Ein Fehler auf der Ebene der CPU (Stichwort: „Speculative Execution side-channel attacks“), der Angreifern theoretisch einen Lesezugriff auf eigentlich geschützte Bereiche des Arbeitsspeichers ermöglicht, ist für mich ein Super-GAU. Da hilft auch alles Relativieren nichts. Auch wenn sich konkrete Schadensfälle in Grenzen halten werden, da weltweit die Mehrheit der Systeme in den nächsten Tagen ein Update erhält, ist die psychologische Auswirkung mehr als bedenklich.

Wozu sich noch um Sicherheitskonzepte, Benutzerkonten, Tokens und Claims Gedanken machen, wenn die komplette Sicherheit durch ein Einfallstor ausgehebelt wird, das in Zukunft immer wieder auftreten kann. Das ergibt sich aus der enormen Komplexität moderner CPUs. Hinzu kommt, dass der Fehler offenbar schon viele Jahre existierte und offenbar erst kurzem von einem Forscherteam der TU Graz entdeckt wurde als sie gehäuft aufgetretene Angriffsszenarien näher untersuchten.

Da über die Thematik in den letzten Tagen schon sehr viel geschrieben wurde, will ich nicht auch noch meinen Senf basierend auf Halbwissen und Vermutungen dazu geben. Auf Spiegel Online habe ich eine gute Zusammenfassung gefunden:

http://www.spiegel.de/netzwelt/gadgets/spectre-und-meltdown-die-wichtigsten-antworten-zu-den-schwachstellen-in-prozessoren-a-1186193.html

Ansonsten natürlich Heise-News mit einem ausführlichen und sehr lesenswerten Artikel von Andreas Stiller, Golem.de usw.

In ein paar Wochen dürfte das Thema ohnehin wieder vergessen sein. Wer macht sich denn aktuell noch über die Bedrohungen des letzten Jahres wie „WannaCry“ und die daraus eigentlich zu ziehenden Konsequenzen Gedanken? Bis zum nächsten Störfall will man vermutlich möglichst wenig Grundsätzliches in Frage stellen.

Wer testen möchte, ob eine CPU anfällig ist für Spectre und Meltdown kann ein PowerShell-Modul von Matt Miller von der PowerShell Gallery installieren, das Microsoft seit dem 4. Januar 2018 zur Verfügung stellt. Voraussetzung ist PowerShell ab Version 5.0. Und natürlich muss die Skriptausführung möglich sein. Wer sich bislang den Luxus gönnte mit einer älteren PowerShell-Version zu arbeiten, muss das Modul als Zip-Datei direkt von der Projektseite herunterladen, „entsperren“ und dann die beiden Dateien in ein in einem Modul-Verzeichnis zuvor angelegtem Verzeichnis mit dem Namen „SpeculationControl“ kopieren.

Eine Projektseite für das Windows 10-Modul habe ich leider nicht gefunden, in der TechNet Script Gallery gibt es das Modul für Windows Server 2016 als Download:

https://gallery.technet.microsoft.com/scriptcenter/Speculation-Control-e36f0050

Das Modul lässt sich natürlich auch unter Windows 10 verwenden.

Liegt PowerShell ab version 5.0 vor, genügt ein

Das Modul wird dadurch nach %userprofile%\documents\windowspowershell\modules kopiert, so dass die PowerShell nicht als Administrator gestartet werden muss.

Anschließend wird die einzige Function wie folgt aufgerufen:

(für VMWare ist offenbar ein Patch erforderlich: https://twitter.com/lamw/status/949662333038559232)

Die Ausgabe des Befehls ist relativ technisch und mit zahlreichen Fachbegriffen versehen, man muss sie daher interpretieren können. Vereinfacht gilt, dass ein „false“ schlecht, ein „true“ gut. Hat man die aktuellen Patches (vor allem KB4056892) installiert, sollte die Mehrheit der Einstellungen einen true-Wert besitzen.

Microsoft beschreibt die Ausgaben auf der folgenden Webseite:

https://support.microsoft.com/de-de/help/4073119/protect-against-speculative-execution-side-channel-vulnerabilities-in

Das von Microsoft zur Verfügung gestellte Sicherheitsupdate hat die Nummer KB4056892. Wie es aussieht, muss es aktuell (Stand: 9/1/2018) bei Windows 10 noch direkt geladen werden:

http://www.catalog.update.microsoft.com/Search.aspx?q=KB4056892

Damit ein Virenscanner das Update nicht verhindert, gibt es unter der folgenden Adresse eine Liste mit Problemlösungen bei den einzelnen Produkten:

https://docs.google.com/spreadsheets/d/184wcDt9I9TUNFFbsAVLpzAtckQxYiuirADzf3cL42FQ/htmlview?sle=true#gid=0

Wie die Meltdown-Abfrage remote ausgefürt wird, wird unter der folgenden Adresse ausführlich beschrieben:

https://blogs.technet.microsoft.com/ralphkyttle/2018/01/05/verifying-spectre-meltdown-protections-remotely/

Mit der Schadensbegrenzung dürften die zuständigen Admins ein paar Tage beschäftigt sein. Insofern hat das neue Jahr „vielversprechend“ begonnen;)

PowerShell-Experten-Tipp: Array-Eigenschaften in Klassen

Eigenschaften in per class-Befehl definierten Klassen können einen beliebigen Datentyp besitzen, natürlich auch Array bzw. den Datentyp für ein mehrdimensionales Array mit Werten eines wiederum beliebigen Typs. Die Schreibweise für den Datentyp ist dieselbe wie bei einer Variablendeklaration, also z.B. [Double[,]] für ein zweidimensionales Array mit Double-Werten.

Das folgende Beispiel ist abstrakt und dient lediglich dazu, die Syntax zu veranschaulichen.

Ausgangspunkt ist eine Klasse M. Sie besitzt eine Property Prop1.

Die zweite Klasse N> besitzt eine Array-Property mit Objekten vom Typ N.

Der Eigenschaft Werte werden direkte Werte zugewiesen, das Array muss also nicht initialisiert werden.

Soll eine Klasse eine Eigenschaft besitzen, die auf einem zweidimensionalen Array basiert, wird für Schreibweise des Datentyps die bei der PowerShell allgemein übliche Schreibweise verwendet.

Außerdem muss die Property explizit per New-Object initialisiert werden, da ansonsten das Array nicht angelegt wird.

Tipp: Die Anzahl der Dimensionen liefert die rank-Eigenschaft des Array. Über die Methode GetUpperBound() erhält man die Obergrenze für eine bestimmte Dimension (0, 1 usw.).

Functions wie Functions aufrufen – über einen kleinen Umweg kein Problem

Eine der Grundideen bei der Planung und Umsetzung der PowerShell war damals, dass sie ein möglichst breites „Publikum“ ansprechen soll, und dass niemand gezwungen werden sollte vertraute Gewohnheiten und Schreibweisen beim Scripten aufgeben zu müssen.

Eine der dieser Gewohnheiten ist die bei anderen Skript- und Programmiersprachen übliche Form der Function-Definition und des Aufrufs einer Function. Demnach folgen auf den Befehl, der die Function definiert, die Parameter in runden Klammern:

Beim Aufruf der Function werden die Argumente ebenfalls in runden Klammern gesetzt:

Auch in PowerShell können Functions auf diese Weise definiert und aufgerufen werden, wenngleich dies eher eine Ausnahme ist. Die einzige Einschränkung besteht darin, dass eine Übergabe mehrerer per Komma getrennter Werte wie üblich die Übergabe eines Arrays bedeutet. Werden daher mehrere Werte übergeben, müssen diese als Array angesprochen werden.

Das folgende Beispiel ist nicht nur etwas umfangreicher, es behandelt auch einen Bereich, der im IT-Alltag eher selten vorkommt: Es geht um die Berechnung der Determinante von Vektoren mit zwei Komponenten und anderen Dingen, die etwas mit „analytischer Geometrie“ (aber eher auf dem Niveau des 11. Schuljahres) zu tun haben.

Im ersten Schritt werden lediglich zwei Klassen für Vektoren mit zwei und mit drei Komponenten definiert.

Die Klassendefinition wäre nicht erforderlich und setzt zudem PowerShell ab Version 5.0 voraus, aber mit den Klassendefinitionen wird das Beispiel insgesamt etwas besser nachvollziehbar.

Im nächsten Schritt kommen zwei Function-Definitionen zum Einsatz, über die Vektoren definiert werden:

Dass auf den param-Befehl verzichtet wird ist keine Voraussetzung, um die Function wie bei Programmiersprachen üblich aufrufen zu können. Wichtig ist lediglich, dass die Function einen Array-Parameter besitzt, dem alle Argumente übergeben werden.

Der Aufruf der Function v2 sieht wie folgt aus:

und

Mit den zweiten Vektoren wird im nächsten Schritt mit der Function det2 die Determinante der 2×2-Matrize ausgerechnet, die durch die beiden Vektoren gebildet wird. Auch diese Function wird so definiert, dass sie mit runden Klammern aufgerufen werden muss.

<# .Synopsis Determinante eines Vektors mit 2 Komponenten #>

function det2
{
param([Vektor2[]]$v)
return ($v[0].x * $v[1].y – $v[0].y * $v[1].x)
}

Beim Aufruf der Function det ist ein kleiner Umweg erforderlich: Der Rückgabewert muss einer Variablen zugewiesen werden. Ansonsten funktioniert die Multiplikation mit 0.5 oder einer anderen Zahl nicht. Warum das so ist, muss ich noch herausfinden (ich bin sicher, dass Friedrich die Antwort kennt;)

Fazit: Wer Functions bei PowerShell so verwenden möchte wie bei VBScript, JavaScript und den meisten Programmiersprachen kann dies tun. Eine Einschränkung besteht darin, dass wenn die Argumente per Komma getrennt übergeben werden soll, ein Array-Parameter benötigt wird.