Archiv für die Kategorie ‘Powershell’

Exchange 2010 Verteilergruppe auch extern erreichbar machen

8 Juni 2013

Um eine allgemeine Adresse mail@domain.de mehreren Benutzern zugänglich zu machen, kann man eine Verteilergruppe im Exchange einrichten. Diese bekommt einfach den passenden Aias mail.

Damit diese Adresse auch von extern erreichbar ist, muss man allerdings noch bei den Nachrichtenübermittlungseinstellungen der Verteilergruppe bei “Einschränkungen für die Nachrichtenübermittlung” den Punkt “Authentifizierung aller Absender anfordern” ausschalten.

Per Powershell gehts mittels

set-DistributionGroup –identity "mail"
-RequireSenderAuthenticationEnabled $false

Datei- und Verzeichnisdatum mittels Powershell manipulieren

6 Mai 2013

Für bestimmte Aktionen kann es hilfreich sein, die Uhrzeit einer Datei manuell zu setzen. Auch hier hilft Powershell.

Man hat z. B. im Verzeichnis C:\TEMP die Datei TEST.TXT. Zuerst setzt man das gewünschte Datum bzw. die Uhrzeit in einer Variablen:

$dt = get-date 1.5.2013-10:00

$dt gibt dann

Mittwoch, 1. Mai 2013 12:00:00

aus. Bei der Angabe der Uhrzeit ist immer UTC-Zeit angesagt. Im Winter wird also eine Stunde, im Sommer werden zwei Stunden dazugerechnet.

Um nun das Datum der letzten Änderung bei der Datei TEST.TXT zu setzen kommt das .NET-Framework zu Hilfe:

[System.IO.File]::SetLastWriteTime("TEST.TXT", $dt)

oder man kann auch das Datum des TEMP-Verzeichnis setzen

[System.IO.Directory]::SetLastWriteTime("C:\TEMP", $dt)

Neben SetLastWriteTime gibt es noch SetLastAccessTime oder SetCreationTime.

So nun viel Spaß beim Versuch, solche Dinge nachzuvollziehen…

Microsoft SQL Server per Powershell Cmdlets ansprechen

25 April 2013

Wenn man einen Microsoft SQL Server mittels Powershell ansprechen möchte, so gibt es nun eine ganz einfache Möglichkeit dies zu tun.

Dazu benötigt man nur:

ENU\x64\SQLSysClrTypes.msi
ENU\x64\SharedManagementObjects.msi
ENU\x64\PowerShellTools.msi

und installiert diese in genau dieser Reihenfolge. Die Dateien sind zu finden im “Microsoft® SQL Server® 2012 SP1 Feature Pack” unter http://www.microsoft.com/en-us/download/details.aspx?id=35580. Und wer es braucht, findet dort auch noch passende Versionen für 32-Bit.

Hier die Links zum direkt Anklicken für die 64-Bit Versionen:

http://download.microsoft.com/download/4/B/1/4B1E9B0E-A4F3-4715-B417-31C82302A70A/ENU/x64/SQLSysClrTypes.msi

http://download.microsoft.com/download/4/B/1/4B1E9B0E-A4F3-4715-B417-31C82302A70A/ENU/x64/SharedManagementObjects.msi

http://download.microsoft.com/download/4/B/1/4B1E9B0E-A4F3-4715-B417-31C82302A70A/ENU/x64/PowerShellTools.msi

IIS Webseite lässt sich nicht starten und meldet: “Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess verwendet wird.”

22 März 2013

Auf einem SBS 2003 ließ sich die die “Virtual Server Administration Website” nicht mehr starten. Der Browser meldete es wäre keine Verbindung zu http://fqdn:1024/VirtualServer/VSWebApp.exe?view=1 möglich.

Der IIS zeigte bei Websites unter Status:

Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess verwendet wird.

Schön wenn von Prozessen die Rede ist aber eigentlich die Ports gemeint sind. Wer also über diese Meldung stolpert, sollte sich anschauen, welcher Port und welcher SSL-Port verwendet wird.

Der Hintergrund ist: Der Port wird von einem anderen Dienst verwendet, aber welcher wäre das? Es gibt zwei Möglichkeiten, entweder man schaltet den anderen Dienst ab oder man vergibt einen neuen Port. Um den anderen Dienst zu ermitteln, verwendet man am einfachsten Powershell und gibt in einer Adminkonsole ein:

netstat –anb | select-string –Context 1 –Simplematch ":1024", ":1025"

wobei natürlich :1024 und :1025 durch die Ports ersetzt werden, die beim IIS unter Port und SSL-Port genannt sind.

Anschließend werden einem die Prozesse aufgeführt, welche die betreffenden Ports benutzen. Damit wird schnell klar, was Sache ist und welche Lösung die bessere ist.

Auf der Suche nach Powershell ISE, Ereignisanzeige

18 März 2013

Wer auf einem einfachen Windows 8 Rechner auf der Suche der Powershell ISE ist, der wundert sich, wo diese versteckt ist. Wenn man im Kachelstartmenü einfach Powershell eingibt, erscheint nur die Powershell Eingabeaufforderung. Wo ist der Rest?

Er ist da und gut versteckt! Für die Powershell ISE könnte man direkt %windir%\system32\WindowsPowerShell\v1.0\Powershell_ISE.exe aufrufen. Aber es gibt noch eine weitere Variante.

Bei aktiver Startseite, öffnet man die Charms-Leiste, klickt auf Einstellungen und noch auf Kacheln. Hier ändert man den Schalter Verwaltungstools anzeigen von Nein auf Ja. Danach findet man die Powershell ISE. Eine Alternative stellt die Tastenkombination WIN+I und dann die Eingabetaste dar.

Insgesamt werden durch die Änderung des Schalters diese Tools freigeschaltet:

Aufgabenplanung
Computerverwaltung
Datenträgerbereinigung
Dienste
Ereignisanzeige
iSCSI-Initiator
Komponentendienste
Laufwerke defragmentieren und optimieren
Leistungsüberwachung
ODBC-Datenquellen (32-Bit)
ODBC-Datenquellen (64-Bit)
Ressourcenmonitor
Systeminformationen
Systemkonfiguration
Windows PowerShell (x86)
Windows PowerShell SE (x86)
Windows PowerShell SE
Windows-Firewall mit erweiterter Sicherheit
Windows-Speicherdiagnose

Wie gesagt, sind alle sowieso da aber durch die Änderung des Schalters, werden Sie auf der Startseite auch eingeblendet.

Man kann die aktuelle Einstellung auch über die Registrierung abfragen. Mittels

REG QUERY HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced

erhält man unter anderem den Eintrag StartMenuAdminTools angezeigt, ist dieser 0×1 werden die Verwaltungstools angezeigt, bei 0×0 nicht. Leider bringt eine Änderung des Registry-Eintrags nichts, auch wenn man einen Neustart probiert.

Windows Driverstore mittels Powershell auslesen

12 Februar 2013

Seit Windows Vista gibt es den sogenannten Windows Driverstore. Im Windows Driverstore sind alle Treiber welche Windows mitbringt verzeichnet. http://msdn.microsoft.com/en-us/library/windows/hardware/ff544868(v=vs.85).aspx

Man kann die enthaltenen Treiber mittels DISM auslesen (als Admin):

dism /online /get-drivers /all /format:Table

Dabei bekommt man eine Liste wie diese

Tool zur Abbildverwaltung für die Bereitstellung
Version: 6.1.7600.16385

Abbildversion: 6.1.7600.16385

Liste aller Treiber wird aus dem Treiberspeicher abgerufen…

Treiberpaketauflistung:

———————————- | ———————————- | ————– | ———————- | —
——————————————————– | ———- | —————-
Veröffentlichter Name              | Originaldateiname                  | Windows-intern | Klassenname            | Anb
ietername                                                | Datum      | Version
———————————- | ———————————- | ————– | ———————- | —
——————————————————– | ———- | —————-
1394.inf                           | 1394.inf                           | Ja             | 1394                   | Mic
rosoft                                                   | 21.06.2006 | 6.1.7601.17514
61883.inf                          | 61883.inf                          | Ja             | 61883                  | Mic
rosoft                                                   | 21.06.2006 | 6.1.7600.16385
acpi.inf                           | acpi.inf                           | Ja             | System                 | Mic
rosoft                                                   | 21.06.2006 | 6.1.7601.17514
acpipmi.inf                        | acpipmi.inf                        | Ja             | System                 | Mic
rosoft                                                   | 21.06.2006 | 6.1.7601.17514
adp94xx.inf                        | adp94xx.inf                        | Ja             | SCSIAdapter            | Ada
ptec                                                     | 11.11.2008 | 1.6.6.4
adpahci.inf                        | adpahci.inf                        | Ja             | SCSIAdapter            | Ada
ptec                                                     | 27.04.2007 | 1.6.6.2
adpu320.inf                        | adpu320.inf                        | Ja             | SCSIAdapter            | Ada
ptec                                                     | 25.01.2007 | 7.2.0.0

sieht nicht schön aus, aber hat Gehalt.

Ok, aber wir bewegen uns in der Powershell-Welt, wie siehts da aus? Leider bringt erst Windows 8 DISM-Cmdlets mit. Aber mittels Piping kann man DISM zur Mitarbeit überreden:

$ds=dism /online /get-drivers /all /format:Table

ließt zunächst die ganze Tabelle in die Variable $ds ein. Die spannenden Teile bekommt man mittels

$ds[14..($ds-length-4)]

ausgegeben.

Mittels dieser Zeile bekommt man alles schön brav als Powershell-Objekte präsentiert:

$di=$ds[14..($ds.length-4)]|foreach {$f=$_.Split("|"); new-object -typename psobject -Property  @{PublishedName=$f[0];OriginalFileName=$f[1];Inbox=$f[2];ClassName=$f[3];ProviderName=$f[4];Date=Get-Date($f[5]);Version=$f[6]} }

Nun kann man die üblichen Powershell-Spielchen bringen wie z. B. die Ausgabe in einer Tabelle:

$di | out-gridview

Hier eine Übersicht der einzelnen Treiber je Klasse:

$di | group -property Classname | select count, name

Oder Ausgabe aller Druckertreiber:

$di | where {$_.Classname -eq "Printer"}

Oder die Druckertreiber eines Herstellers wie HP:

$di | where {$_.Classname -eq "Printer" -and $_.Providername -match "HP"}

Was zur Ausgabe

Date             : 29.10.2010 00:00:00
Version          : 61.109.9.8874
PublishedName    : oem5.inf
OriginalFileName : hpcu109u.inf
ProviderName     : HP
ClassName        : Printer
Inbox            : Nein

Date             : 21.06.2006 00:00:00
Version          : 6.1.7600.16385
PublishedName    : prnhp002.inf
OriginalFileName : prnhp002.inf
ProviderName     : HP
ClassName        : Printer
Inbox            : Ja

Date             : 21.06.2006 00:00:00
Version          : 6.1.7600.16385
PublishedName    : prnhp003.inf
OriginalFileName : prnhp003.inf
ProviderName     : HP
ClassName        : Printer
Inbox            : Ja

Date             : 21.06.2006 00:00:00
Version          : 6.1.7600.16385
PublishedName    : prnhp004.inf
OriginalFileName : prnhp004.inf
ProviderName     : HP
ClassName        : Printer
Inbox            : Ja

Date             : 21.06.2006 00:00:00
Version          : 6.1.7600.16385
PublishedName    : prnhp005.inf
OriginalFileName : prnhp005.inf
ProviderName     : HP
ClassName        : Printer
Inbox            : Ja

hat.

Moment hier tauchen nur fünf Treiber auf? Komisch oder?

Aber kein Problem es gibt einen weiteren DISM-Befehl der weitere Infos zutage fördert:

dism /online /get-driverinfo /driver:prnhp005.inf

Mittels diesem erhält man weitere Treiberinformationen:

Tool zur Abbildverwaltung für die Bereitstellung
Version: 6.1.7600.16385

Abbildversion: 6.1.7600.16385

Treiberpaketinformationen:

Veröffentlichter Name : prnhp005.inf
Treiberspeicherpfad : C:\Windows\System32\DriverStore\FileRepository\prnhp005.inf_amd64_neutral_914d6c300207814f\prnhp00
5.inf
Klassenname : Printer
Klassenbeschreibung : Drucker
Klassen-GUID : {4D36E979-E325-11CE-BFC1-08002BE10318}
Datum : 21.06.2006
Version : 6.1.7600.16385
Für den Start erforderlich : Nein

Treiber für Architektur : amd64

    Hersteller : HP
    Beschreibung : HP Photosmart C309a series
    Architektur : amd64
    Hardware-ID : HPPhotosmart_C309a_s277D
    Dienstname :
    Kompatible IDs : HP_Photosmart_C309a_series
    Ausschluss-IDs :

    Hersteller : HP
    Beschreibung : HP Photosmart C309a series BT
    Architektur : amd64
    Hardware-ID : HPPhotosmart_C309a_sA58A
    Dienstname :
    Kompatible IDs : HP_Photosmart_C309a_series_BT
    Ausschluss-IDs :

    Hersteller : HP
    Beschreibung : HP Officejet Pro 8000 A809 Series
    Architektur : amd64
    Hardware-ID : HPOfficejet_Pro_8000e3dd
    Dienstname :
    Kompatible IDs : HP_Officejet_Pro_8000_A809_Series
    Ausschluss-IDs :

    Hersteller : HP
    Beschreibung : HP Officejet Pro 8500 A909n Series
    Architektur : amd64
    Hardware-ID : HPOfficejet_Pro_8500e33c
    Dienstname :
    Kompatible IDs : HP_Officejet_Pro_8500_A909n_Series
    Ausschluss-IDs :

    Hersteller : HP
    Beschreibung : HP Officejet Pro 8500 A909g Series
    Architektur : amd64
    Hardware-ID : HPOfficejet_Pro_8500e5fc
    Dienstname :
    Kompatible IDs : HP_Officejet_Pro_8500_A909g_Series
    Ausschluss-IDs :

    Hersteller : HP
    Beschreibung : HP Officejet Pro 8500 A909a Series
    Architektur : amd64
    Hardware-ID : HPOfficejet_Pro_8500e77c
    Dienstname :
    Kompatible IDs : HP_Officejet_Pro_8500_A909a_Series
    Ausschluss-IDs :

    Hersteller : HP
    Beschreibung : HP Officejet Pro 8500 A909n Series BT
    Architektur : amd64
    Hardware-ID : HPOfficejet_Pro_85007188
    Dienstname :
    Kompatible IDs : HP_Officejet_Pro_8500_A909n_Series_BT
    Ausschluss-IDs :

    Hersteller : HP
    Beschreibung : HP Officejet Pro 8500 A909g Series BT
    Architektur : amd64
    Hardware-ID : HPOfficejet_Pro_8500ed8b
    Dienstname :
    Kompatible IDs : HP_Officejet_Pro_8500_A909g_Series_BT
    Ausschluss-IDs :

    Hersteller : HP
    Beschreibung : HP Officejet Pro 8500 A909a Series BT
    Architektur : amd64
    Hardware-ID : HPOfficejet_Pro_8500658b
    Dienstname :
    Kompatible IDs : HP_Officejet_Pro_8500_A909a_Series_BT
    Ausschluss-IDs :

    Hersteller : HP
    Beschreibung : HP Officejet 6500 E709n Series
    Architektur : amd64
    Hardware-ID : HPOfficejet_6500_E70e4a2
    Dienstname :
    Kompatible IDs : HP_Officejet_6500_E709n_Series
    Ausschluss-IDs :

    Hersteller : HP
    Beschreibung : HP Officejet 6500 E709a Series
    Architektur : amd64
    Hardware-ID : HPOfficejet_6500_E70e0e2
    Dienstname :
    Kompatible IDs : HP_Officejet_6500_E709a_Series
    Ausschluss-IDs :

    Hersteller : HP
    Beschreibung : HP Officejet 6000 E609a Series
    Architektur : amd64
    Hardware-ID : HPOfficejet_6000_E604cdc
    Dienstname :
    Kompatible IDs : HP_Officejet_6000_E609a_Series
    Ausschluss-IDs :

    Hersteller : HP
    Beschreibung : HP Officejet 6000 E609n Series
    Architektur : amd64
    Hardware-ID : HPOfficejet_6000_E60489c
    Dienstname :
    Kompatible IDs : HP_Officejet_6000_E609n_Series
    Ausschluss-IDs :

    Hersteller : HP
    Beschreibung : HP Deskjet F4400 series
    Architektur : amd64
    Hardware-ID : HPDeskjet_F4400_seri4818
    Dienstname :
    Kompatible IDs : HP_Deskjet_F4400_series
    Ausschluss-IDs :

    Hersteller : HP
    Beschreibung : HP Photosmart C4600 series
    Architektur : amd64
    Hardware-ID : HPPhotosmart_C4600_sEC29
    Dienstname :
    Kompatible IDs : HP_Photosmart_C4600_series
    Ausschluss-IDs :

    Hersteller : HP
    Beschreibung : HP Deskjet D2600 series
    Architektur : amd64
    Hardware-ID : HPDeskjet_D2600_seri56FC
    Dienstname :
    Kompatible IDs : HP_Deskjet_D2600_series
    Ausschluss-IDs :

Der Vorgang wurde erfolgreich beendet.

Hier kann man nun den einzelnen Druckernamen erkennen.

Diese Druckerinfos kann man wieder in einer Variable einlesen:

$pd=dism /online /get-driverinfo /driver:prnhp005.inf

und natürlich wieder in Powershell-Objekte übertragen:

$pdl=$pd|select-string -Context 7 -Pattern Hersteller

Sorry aus Zeitmangel überlasse ich es jedem selber hier die sinnvollen Informationen auszulesen.

Hier noch zwei Blogeinträge passend zum Thema, wo mittels Excel eine Übersicht über enthaltene Treiber im Driverstore geliefert werden: http://www.verboon.info/index.php/2010/12/inside-the-windows-7-driver-store/ und http://www.verboon.info/index.php/2011/01/inside-the-windows-7-driver-storepart-2/.

Powershell 9 Arten ein externes Programm zu starten, mir sind aber 11 bekannt oder noch mehr?

7 Januar 2013

Dieser Artikel http://www.admin-source.de/BlogDeu/433/powershell-9-arten-ein-externes-programm-executable-zu-starten, dessen Grundlage, dieser Technet-Wiki-Eintrag ist http://social.technet.microsoft.com/wiki/contents/articles/7703.powershell-running-executables.aspx, spricht von 9 Arten externe Programme unter Powershell starten zu können.

Allerdings muss man bei Version 2 von Powershell sagen, es gibt eigentlich 10 Arten, denn es gibt das tolle Kommando Invoke-WSManAction http://technet.microsoft.com/en-us/library/hh849865.aspx. Mit den richtigen Parametern gefüttert:

Invoke-WSManAction -Action create -ResourceURI wmicimv2/win32_process -ValueSet @{commandline="notepad.exe";currentdirectory="C:\"}

führt dies auch zum Start von Notepad.exe!

Jetzt mag der eine oder andere einwenden, dass ja nur Win32_Process aufgerufen wird aber wird nicht auch bei den anderen Möglichkeiten im Hintergrund immer nur CreateProcess() aufgerufen?

Ach übrigens mit Powershell 3 gibt es noch eine weitere Variante! Die da wäre Invoke-CIMAction http://technet.microsoft.com/en-us/library/jj590759.aspx. Dies sind dann so aus:

$cim=Invoke-CimMethod -ClassName Win32_process -MethodName "Create" -Arguments @{ Commandline="notepad.exe";CurrentDirectory="C:\" }

Wenn ich allerdings jetzt nochmal genau darüber nachdenke, dann fallen mir noch weitere Möglichkeiten ein, wie z. B. ScheduledJobs, BackgroundJobs also Jobs allgemein, mittels Win32_ScheduleJob oder indem man einen Druckertreiber mit entsprechendem Monitorprogramm installiert und dann was ausdruckt. Dann wäre da noch die Möglichkeit über Win32_Service. Und es gibt noch soviel mehr, wenn man seine Kreativität walten lässt.

Man könnte ja auch Powershell benutzen, um mehr zu erfahren

gwmi -List | where if ($_.methods -ne $null) {($_.methods).name -contains "Create"}

listet unter anderem

Win32_Process
Win32_BaseService
Win32_Service
Win32_TerminalService
Win32_SystemDriver
Win32_ScheduledJob

Bei CIM wären die Invoke-Aktionen aber CIM ist noch so undurchschaubar. Gute, wenn auch alte Infos über CIM gibt es hier: http://klaus.jaehne.de/papers/cim/node6.html.

Ich glaub jetzt bin ich irgendwie übers Ziel rausgeschossen. Halten wir also fest: Es gibt mehr Methoden, als wir zu wissen glauben.

Wifi Netzwerksicherheitsschlüssel unter Windows per Powershell auslesen

2 Januar 2013

Es gibt unter Windows zwar wohl eine Methode sich den hinterlegten Netzwerksicherheitsschlüssel für Wifi Netzwerke anzuzeigen aber die Methode ist nur über die GUI-Oberfläche möglich und ist recht umständlich, wenn man die Keys mehrerer Netze abfragen möchte.

Es gibt natürlich auch allerhand Utilities wie z. B. WirelessKeyview von Nirsoft http://www.nirsoft.net/utils/wireless_key.html. Aber wer vertraut per solch sicherheitskritischen Dingen schon gern unbekannter Software. Zumal diese oft von Virenscannern als Malware klassifiziert werden: http://blog.nirsoft.net/2012/10/10/amazing-difference-between-antivirus-false-alerts-on-32-bit-and-64-bit-builds-of-exactly-the-same-tool/.

Was liegt also näher, als die Sache selber mit Bordmitteln zu lösen. Das Thema ist allerdings etwas komplexer weshalb ich als Vorbereitung in den vergangenen Tagen bereits verschiedene Artikel geschrieben habe.

Zuerst werden die Berechtigungen vom Systemdienst benötigt: http://newyear2006.wordpress.com/2013/01/01/eingabeaufforderung-mit-lokalen-systemdienst-rechten-unter-windows-8-und-windows-server-2012/.

Dann ist wichtig, wie man mit SecureStrings in Powershell umgeht: http://newyear2006.wordpress.com/2012/12/30/spa-mit-net-securestring-und-powershell-oder-sicheres-speichern-und-einlesen-von-passwrtern/

Noch etwas mehr Hintergrund, wie man in den tiefen von SecureString die DPAPI benutzt: http://newyear2006.wordpress.com/2012/12/30/in-den-niederungen-von-securestring-mittels-powershell/

Dann braucht man noch die Idee für solch einen Artikel: http://securityxploded.com/wifi-password-secrets.php

So nun zum Script, am besten speichert man es unter WifiUtil.PS1:

# Warmup
ConvertTo-SecureString -AsPlainText -Force Hallo| ConvertFrom-SecureString

function Convert-HexStringToByteArray {
# http://www.sans.org/windows-security/2010/02/11/powershell-byte-array-hex-convert
################################################################
#.Synopsis
# Convert a string of hex data into a System.Byte[] array. An
# array is always returned, even if it contains only one byte.
#.Parameter String
# A string containing hex data in any of a variety of formats,
# including strings like the following, with or without extra
# tabs, spaces, quotes or other non-hex characters:
# 0×41,0×42,0×43,0×44
# \x41\x42\x43\x44
# 41-42-43-44
# 41424344
# The string can be piped into the function too.
################################################################
[CmdletBinding()]
Param ( [Parameter(Mandatory = $True, ValueFromPipeline = $True)] [String] $String )
#Clean out whitespaces and any other non-hex crud.
$String = $String.ToLower() -replace ‘[^a-f0-9\\\,x\-\:]‘,”

#Try to put into canonical colon-delimited format.
$String = $String -replace ’0x|\\x|\-|,’,':’

#Remove beginning and ending colons, and other detritus.
$String = $String -replace ‘^:+|:+$|x|\\’,”

#Maybe there’s nothing left over to convert…
if ($String.Length -eq 0) { ,@() ; return }

#Split string with or without colon delimiters.
if ($String.Length -eq 1)
{ ,@([System.Convert]::ToByte($String,16)) }
elseif (($String.Length % 2 -eq 0) -and ($String.IndexOf(":") -eq -1))
{ ,@($String -split ‘([a-f0-9]{2})’ | foreach-object { if ($_) {[System.Convert]::ToByte($_,16)}}) }
elseif ($String.IndexOf(":") -ne -1)
{ ,@($String -split ‘:+’ | foreach-object {[System.Convert]::ToByte($_,16)}) }
else
{ ,@() }
#The strange ",@(…)" syntax is needed to force the output into an
#array even if there is only one element in the output (or none).
}

function Get-WLANKeyFromProfile {
[CmdletBinding()]
param(
  [xml]$x)

if ($x -ne $null)
{
  $key=$x.WLANProfile.MSM.security.sharedKey.keyMaterial
         $eb=Convert-HexStringToByteArray $key
  $mbl=[System.Security.Cryptography.ProtectedData]::Unprotect($eb,$null,"LocalMachine")
  $key=[System.Text.Encoding]::ASCII.GetString($mbl)
  $key.Substring(0,$key.Length-1) # 0×0

}
}

function Get-SSIDFromProfile {
[CmdletBinding()]
param(
  [xml]$x)

if ($x -ne $null)
{
  $key=$x.WLANProfile.SSIDConfig.SSID.name
  $key
}
}

# C:\ProgramData\Microsoft\Wlansvc\Profiles\Interfaces

$wifi=Get-ChildItem -Recurse|Select-String -pattern "01000000D08C9DDF0115D1118C7A00C04FC297EB"
$wifi | Add-Member -Type ScriptProperty –Name SSID -Value { Get-SSIDFromProfile $this.XMLProfileFile }
$wifi | Add-Member -Type ScriptProperty -Name WlanKey -Value { Get-WLANKeyFromProfile $this.XMLProfileFile }
$wifi | Add-Member -Type ScriptProperty -Name XMLProfileFile -Value { [xml](Get-Content $this.path) }

Wenn man auf dem Desktop des Systemdienst ist, geht man in das Verzeichnis

CD C:\ProgramData\Microsoft\Wlansvc\Profiles\Interfaces

und ruft dort Powershell auf und importiert obiges Script mittels

Import-Module WifiUtil.PS1

Man hat nun in $Wifi alle auf dem System bekannten Wifi-Keys mit Angaben zu den SSIDs. Mittels Powershell 3.0 und Out-Gridview gibt es die perfekte Darstellung:

$wifi | Out-GridView

oder man verwendet die klassische Methode:

$wifi | select –Property SSID,WlanKey

So das war aber erst der Anfang mit dieser Methode lässt sich noch viel mehr anstellen.

Schnelldiagnose mittels Powershell anstatt über die Ereignisanzeige

31 Dezember 2012

Um einen schnellen Überblick über die größten Nöte eines Systems zu finden, kann man diese Powershell Befehle verwenden:

Genereller Überblick

get-eventlog –Logname System | where {$_.EntryType –eq ‘Error’} | select –First 10

get-eventlog –Logname System | where {$_.EntryType –eq ‘Warning’} | select –First 10

get-eventlog –Logname Application | where {$_.EntryType –eq ‘Error’} | select –First 10

get-eventlog –Logname Application | where {$_.EntryType –eq ‘Warning’} | select –First 10

get-eventlog -LogName Security | where {$_.Entrytype -ne "SuccessAudit"} | select –First 10

Seit Windows Vista und Server 2008 wurde die Ereignisanzeige massiv erweitert durch die Windowsereignisse.

Einen schnellen Überblick über Hyper-V Probleme bekommt mittels:

Get-WinEvent –ProviderName "*Hyper-V*"

oder wo ein besitmmter Computername auftaucht

Get-WinEvent –ProviderName "*Hyper-V*" | where {$_.Message –match "Computername"}

oder wo ein Fehler aufgetreten ist:

Get-WinEvent –ProviderName "*Hyper-V*" | where {$_.LevelDisplayName –eq "Fehler"}

Wenn man wissen möchte, was an einem bestimmten Tag geschah:

Get-WinEvent-ProviderName "*Hyper-V*" | where {(Get-Date $_.TimeCreated –format d) –eq (Get-Date 13.10.2012 –format d)}

Wenn man wissen möchte, was zu einer bestimmten Stunde passierte:

Get-WinEvent-ProviderName "*Hyper-V*" | where {(Get-Date $_.TimeCreated –format "yyyyMMddHH") –eq (Get-Date "13.10.2012 11:00" –format "yyyyMMddHH")}

Hierbei ist zu beachten, das alles was vor 11:00Uhr also um 10:59 geschah unberücksichtigt bleibt. Wenn aber ein Ereignis um 11:01Uhr Probleme machte, sollte man natürlich den Überprüfungszeitraum auf 10:xxUhr ausdehnen!

Genau dies macht dieser Befehl, es wird etwas mit Zeiten jongliert und zwar werden dem Ursprungsereignis immer 20 Minuten hinzuaddiert, dadurch rutscht ein Ereignis von 10:45Uhr in das 11:00Uhr Zeitfenster:

Get-WinEvent-ProviderName "*Hyper-V*" | where {(Get-Date (Get-Date $_.TimeCreated).AddMinutes(20) –format "yyyyMMddHH") –eq (Get-Date "13.10.2012 11:00" –format "yyyyMMddHH")}

Logischerweise fallen dann Ereignisse nach 11:40 unter den Tisch.

Wer kompliziertere Abfragen oder gar Remoteabfragen braucht, der sollte sich bei Get-WinEvent einen Filter basteln und diesen angeben, weitere Infos dazu: http://newyear2006.wordpress.com/2011/04/28/ereignisanzeige-query-builder-fr-powershell/

In den Niederungen von SecureString mittels Powershell

30 Dezember 2012

Im ersten Blogbeitrag zu SecureString bin ich auf die allgemeine Anwendung von SecureStrings in Powershell und indirekt im .Net-Framework eingegangen. http://newyear2006.wordpress.com/2012/12/30/spa-mit-net-securestring-und-powershell-oder-sicheres-speichern-und-einlesen-von-passwrtern/

Wenn man mit den SecureStrings herumspielt, fällt einem schnell auf, dass diese quasi immer einen gleichen Header verwenden. Dieser beginnt immer mit der folgenden Zeichenfolge:

01000000d08c9ddf0115d1118c7a00c04fc297eb

Ab hier wird es nun interessant. Wenn man Google bemüht, kommen nicht all zu viele Treffer bei raus: https://www.google.de/search?q=01000000d08c9ddf0115d1118c7a00c04fc297eb. Aber unter den wenigen Treffern, sind wahre Perlen dabei! Denn es geht um nichts anderes als um eine eindeutige Kennung für DPAPI BLOBs welche von Windows seit Windows 2000 verwendet werden um Passwörter sicher in der Registrierung, Festplatte und Speicher abzulegen. DPAPI steht für Data Protection API. http://msdn.microsoft.com/en-us/library/ms995355.aspx.

Bleiben wir zunächst bei Powershell. Michal Grzegorzewski hat auf seiner Seite die Einträge mittels Debugger auseinandergenommen, hier die englische Übersetzung mittels Google: http://translate.googleusercontent.com/translate_c?depth=1&hl=de&prev=_dd&rurl=translate.google.de&sl=auto&tl=en&u=http://zine.net.pl/blogs/mgrzeg/archive/2011/03/11/dpapi-internals-a-securestring-w-powershellu.aspx&usg=ALkJrhhOdJ83W5rHYAcEnuML-v-KZ1KqNw. Dabei hat er festgestellt, dass Powershell die Methode Protect aus der ProtectedData Klasse aus dem .Net-Framework verwendet. http://msdn.microsoft.com/de-de/library/system.security.cryptography.protecteddata.protect.aspx. Protect verwendet wiederum CryptProtectData aus Crypt32.dll. http://msdn.microsoft.com/en-us/library/windows/desktop/aa380261(v=vs.110).aspx. Ein Punkt der bei Powershells ConvertFrom-SecureString und ConvertTo-SecureString zu kurz kommt, ist die Sache dass es sich um benutzerbezogene Verschlüsselungen handelt. D. h. ein Passwort welches mittels ConvertFrom-SecureString als verschlüsselter Standardstring konvertiert und gespeichert wurde, kann nur von dem selben Benutzer auf dem ursprünglichen Rechner wieder gelesen und verwendet werden! Um die Sache dann noch weiter zu komplizieren, sei noch darauf hingewiesen, dass das verwendete Passwort des Benutzers auch noch eine Rolle spielt, was wiederum beim Zurücksetzten von Passwörtern wichtig werden kann: http://support.microsoft.com/kb/309408. Zu welchen Probleme das benutzerbezogene Speichern führen kann, schildert schön dieser Artikel: http://blog.codeassassin.com/2012/05/17/powershell-remoting-user-profiles-delegation-and-dpapi/.

Im zweiten Bereich seines ersten Blogeintrags unter “DAPI Internals” streift Grzegorzewski noch die Geschichte von Masterkeys und dass auf jedem Windows immer die vorhergehenden Keys gespeichert sein müssen, um auf ältere, verschlüsselte Daten zurückgreifen zu können. Thema CREDHIST. Aber das Thema lassen wir außen vor. Im zweiten Blog-Artikel geht er dann noch näher auf die Internas von DAPI Blobs ein http://translate.google.de/translate?hl=de&sl=auto&tl=en&prev=_dd&u=http%3A%2F%2Fzine.net.pl%2Fblogs%2Fmgrzeg%2Farchive%2F2011%2F03%2F30%2Fdpapi-internals-a-securestring-w-powershellu-cz-2.aspx. Dort nennt er Picod and Bursztein, welche das Tool libDPAPIck.dll, zu finden unter http://dpapick.com/ entwickelt haben. Das Tool erlaubt das Lesen von EFS-verschlüsselten Laufwerken von Linux oder anderen Offlinesystemen aus.

So nach dem kleinen Ausflug, wieder zurück zum Thema SecureStrings und Powershell. Im ersten Artikel http://newyear2006.wordpress.com/2012/12/30/spa-mit-net-securestring-und-powershell-oder-sicheres-speichern-und-einlesen-von-passwrtern/ wurde ja schon gezeigt, wie man ein Passwort wiederherstellen und sichtbar machen kann. Nun wollen wir die von Grzegorzewski verwendete Methode mittels Powershell auf den verschlüsselten Standardstring anwenden.

Wir haben also aus unserem ersten Artikel die Zeichenfolge

01000000d08c9ddf0115d1118c7a00c04fc297eb01000000d13e0b3adb59f6469325c229ee5b0d520000000002000000000003660000c0000000100
00000d57efc5b5ccd1e52e71296ec9b91a3530000000004800000a0000000100000006b946cd8b1c877db8c8ae6f39f4932bd10000000858fb31747
0ef57f405d954a5857409a14000000e2154da0885013dc5dbf21097c61c1d429f1e8ce

Dabei handelt es sich um einen Hexstring. Für den Aufruf von Unprotect http://msdn.microsoft.com/en-us/library/system.security.cryptography.protecteddata.unprotect wird als Parameter ein Bytearray benötigt. Dazu benötigen wir als erstes eine Hilfsfunktion, welche den verschlüsselten Standardstring in ein ByteArray umwandelt, diese gibt es hier: http://www.sans.org/windows-security/2010/02/11/powershell-byte-array-hex-convert und nennt sich Convert-HexStringToByteArray. Also los gehts:

# $es enthält obigen String
Import-Module .\HexHelper.PS1
$eb=Convert-HexStringToByteArray $es
$mb=[System.Security.Cryptography.ProtectedData]::Unprotect($eb,$null,"CurrentUser")
[System.Text.Encoding]::Unicode.GetString($mb)

Zurück bekommen wir dann das ursprüngliche “Hallo”.

Dabei gibt es noch ein paar Dinge zu beachten. Der Aufruf von Unprotect funktioniert erst, wenn davor ConvertFrom-SecureString bereits benutzt wurde! Falls dies nicht der Fall ist, bekommt man die Fehlermeldung

Der Typ [System.Security.Cryptography.ProtectedData] wurde nicht gefunden: Vergewissern Sie sich, dass die Assembly, die diesen Typ usw…

Zum Warmlaufen kann man diesen Befehl vorher verwenden:

Read-Host – AsSecureString | ConvertFrom-SecureString

Wie oben bereits geschrieben, die Strings sind immer benutzerbezogen, wenn man also den String auf einer anderen Maschine versucht zu verarbeiten, erhält man die Meldung:

Ausnahme beim Aufrufen von "Unprotect" mit 3 Argument(en):  “Schlüssel ist im angegebenen Status nicht gültig."


Follow

Bekomme jeden neuen Artikel in deinen Posteingang.