Archive for September 2015

Was gibt der Registrierungsschlüssel DHCPGatewayHardware her? Oder – wie kann man alternativ per Powershell das DHCP-IPv4-Gateway ermitteln?

28 September 2015

Hier mal etwas für Forensiker. Aus der Not geboren, dass nur eine Fernwartung beim Kunden möglich war – die nur einmal aufgebaut werden konnte, galt es herauszufinden, warum Netzprobleme bei der IPv4-Adressvergabe auftraten. Eigentlich sollten die Clientrechner IP-Adressen im Bereich 192.168.0.X bekommen aber effektiv bekamen fast alle Rechner eine im Bereich 192.168.1.X. Dadurch war kein Internetzugang mehr möglich und auch der Fileserver unter 192.168.0.1 war nicht mehr erreichbar. Da im konkreten Fall ein Speedport mit der Adresse 192.168.0.100 der DHCP-Server war, wurde zunächst eine Station mit einer fixen IP-Adresse im Bereich des Speedport versehen. Von dort aus war dann der Zugriff zum Speedport möglich. Auch das Internet mit einer Fernwartungssitzung klappte dadurch wieder. Jetzt galt es aber rauszubekommen, warum die Rechner teilweise falsche IP-Adresse bekamen. Nur wie macht man das, wenn man auf der einzigen Netzwerkkarte per Fernwartung aufgeschaltet ist?

Zunächst versuchte ich Scapy per Python ans laufen zu bekommen,  um dieses Script ausführen zu können: https://bitbucket.org/secdev/scapy/wiki/doc/IdentifyingRogueDHCPServers. Die Idee war ganz einfach einen Netzwerkmitschnitt über DHCP-Server-Ankündigungen zu machen. Aber leider beschwerte sich Scapy, beim Versuch der Installation, ständig über eine weitere, fehlende Abhängigkeit. Am Ende lief es auf jeden Fall nicht.

Wireshark wäre noch eine Option gewesen, da die WinPCap-Treiber wegen Scapy eh schon installiert waren. Aber Wireshark kann jeder.

Wie immer wäre mir eine Powershell-Lösung die liebste, aber leider gibt es noch nichts Vergleichbares zu Scapy. Bei der Suche nach der Powershell-Lösung bin ich allerdings über diesen Artikel gestolpert: http://www.ingmarverheij.com/read-dhcp-options-received-by-the-client/. Ich hatte zwar beim betreffenden Windows 7 Rechner keinen Eintrag mit DhcpInterfaceOptions aber zumindest der Eintrag DhcpGatewayHardware war vorhanden. Der Eintrag war als REG_BINARY mit dem Wert

c0 a8 01 01 06 00 00 00 e8 fc af ab c0 24

eingetragen. Der Wert von DhcpGatewayHardware ist zu finden unter HKLM\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\Interfaces\{GUID}.

Per Powershell erreicht man den Wert über

$a = gwmi Win32_NetworkadapterConfiguration
$i = $a | where {$_.Description –like "*Intel*"}

$i.SettingID

$si = $i.SettingID

$ri = Get-ItemProperty -path "registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\Interfaces\$si" -name dhcpgatewayhardware | select DHCPGatewayHardware

$ri

Bei *Intel* sollte man den Hersteller seiner Netzwerkarte eintragen, für Realtek z. B. *Realt*, wenn es mehrere geben sollte, muss natürlich die betreffende herausgefiltert werden. Das entscheidende dabei ist, dass man die GUID der SettingID bekommt, über welche man weiß wo man in der Registrierung bei den Interfaces suchen muss.

Auf jeden Fall bekommt man am Ende bei $ri z. B.  diese Ausgabe:

DhcpGatewayHardware
——————-
{192, 168, 1, 1…}

Man sieht bereits, dies ist der falsche Wert, der am Anfang dafür gesorgt hatte, dass der Kunde nicht arbeiten konnte. Das interessante dabei ist, 192.168.1.1 entspricht hexadezimal genau “c0 a8 01 01”, die grüne Markierung verdeutlicht nochmal den Zusammenhang. Also ist der Zusammenhang schon mal hergestellt. Der hintere Wert e8 fc af ab c0 24 sieht wie eine MAC-Adresse aus, denn warum sonst sollte Microsoft den Eintrag DhcpGatewayHardware nennen?

Also noch die Bytes 8-14 ausgelesen und daraus eine MAC-Adresse gebastelt:

$mac=$ri.DhcpGatewayHardware[8..14]
$mac=$mac| foreach {$new=""} {$new+="{0:x02}:" -f $_} {$new}
$mac=$mac.TrimEnd(":")

$mac

Nun hat man in $mac die MAC-Adresse des DHCP-Servers, welcher die IP-Adresse 192.168.1.1 geliefert hatte.

Also mal Google bemüht und dies gefunden: http://macaddress.webwat.ch/hwaddr/E8:FC:AF. Hier wird E8:FC:AF Netgear zugeordnet:

Device mac address: E8:FC:AF
Base16 encoding: E8FCAF
producer name: NETGEAR INC.,

producer address:

350 EAST PLUMERIA DRIVE
SAN JOSE CALIFORNIA 95134
UNITED STATES

Jetzt galt es nur noch ein Gerät ausfindig zu machen. Aber mit dem Wissen, dass es sich um ein Netgear Gerät handelte, war der weitere Weg wesentlich einfacher, als wenn es irgendein Gerät im Netz gewesen wäre. Vor allem war dadurch auch klar, dass es sich nicht um einen gefakten bzw. Rogue-DHCP-Server handelte, welcher eine Attacke im Netz ritt.

Übrigens: Bei einem korrekt konfigurierten und funktionierendem Netz bekommt man, bei Anwendung obigen Scripts, einfach das Gateway mit der betreffenden MAC-Adresse, wenn DHCP aktiviert ist.

Windows Emergency Management Services (EMS) Konsole

25 September 2015

Mal wieder so eine Sache, die es schon jahrelang gibt, auf die man dann per Zufall stößt. Man kann mittels Emergency Management Services Rechner neu starten, die eigentlich einen Bluescreen darstellen. Offenbar geht dann auch noch Powershell, irgendwie. Da gerade die Zeit fehlt tiefergehende Tests zu machen, hier einfach mal die einschlägigen Ressourcen zum Thema:

https://www.myotherpcisacloud.com/post/Windows-Emergency-Management-Services

Mit dieser (USB):

Bcdedit.exe /EMS ON /EMSSETTINGS BIOS

bzw. dieser (RS-232):

Bcdedit.exe /EMS ON /EMSSETTINGS EMSPORT:COM2 EMSBAUDRATE:9600

Änderung vor einem Problem, kommt man auf die Kiste von extern wieder drauf und es meldet sich die Special Administration Console (SAC), wo man dann eine herkömmliche Shell hat.

Hier bestätigt tatsächlich jemand, dass dort auch Powershell möglich ist: http://serverfault.com/questions/554298/windows-serial-console.

Hier noch Beschreibungen zu den BCDEdit.EXE und EMS-Parameter: https://msdn.microsoft.com/en-us/library/ff542282%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396

Weitere Infos von MS: http://social.technet.microsoft.com/wiki/contents/articles/2469.windows-server-emergency-management-resources.aspx

Suchen und Ersetzen in Verknüpfungen (.LNK-, .URL- und .WebSite-Dateien) auf dem Desktop automatisieren

20 September 2015

Angenommen, man hat einen üblichen Desktop vor sich. Dieser ist mit zig Dateien und Verknüpfungen übersäht. Wenn man dann wissen möchte, welcher Link auf ein bestimmtes Verzeichnis verweist, dann kann das schnell in Arbeit ausarten. Wenn man dann noch etwas ersetzen muss, kann man in vielen Umgebungen Spaß mit fehlender UAC Unterstützung unter Windows haben. Am Ende flucht man, warum man nicht mal mit Admin-Rechten einen einfachen Link aktualisieren kann.

In allen diesen Fällen hilft wie immer Omo, nö Powershell wars.

Zunächst gilt es alle Verknüpfungen auf dem Desktop zu finden. Man erzeugt zunächst ein Shell-Objekt:

$shell = New-Object –ComObject Shell.Application

Nun benötigt man die Links vom Desktop. Man könnte nun direkt auf den Pfad des aktuellen Benutzers verweisen aber noch eleganter ist es, sich vom System den Pfad geben zu lassen:

$desktop = $shell.Namespace(0x10)

Wenn man sich $desktop anschaut erhält man:

Title                      : Desktop
Application                : System.__ComObject
Parent                     :
ParentFolder               : System.__ComObject
Self                       : System.__ComObject
OfflineStatus              :
HaveToShowWebViewBarricade : False
ShowWebViewBarricade       : False

Nicht sehr überzeugend oder? Besser wird es damit:

PS > $desktop.Self

Application  : System.__ComObject
Parent       : System.__ComObject
Name         : Desktop
Path         : C:\Users\Benutzer\Desktop
GetLink      :
GetFolder    : System.__ComObject
IsLink       : False
IsFolder     : True
IsFileSystem : True
IsBrowsable  : False
ModifyDate   : 17.09.2015 17:31:32
Size         : 0
Type         : Dateiordner

Man bekommt also mittels $desktop.Self.Path den aktuellen Pfad zum Desktop. Damit kann man nun etwas anfangen, z. B. die Verknüpfungen ermitteln:

Get-ChildItem $desktop.Self.Path -Filter *.lnk

Aber Moment, wer sich vielleicht wundert, warum nicht alle Verknüpfungen auftauchen, die ein Benutzer auf seinem Desktop hat, dem sei gesagt, es gibt auch einen öffentlichen Desktop, der für alle Benutzer gilt. Obiger Namespaceaufruf hatte nur den Desktop des aktuellen Benutzers zurückgegeben. Die öffentliche Variante erhält man so:

$publicDesktop = $shell.Namespace(0x19)

wenn man sich hier $publicDesktop.Self.Path anschaut erhält man

C:\Users\Public\Desktop

Kurz noch als Erklärung zu 0x10 bzw. 0x19, dabei handelt es sich um Konstanten aus den Shell Special Folders, eine Auflistung ist hier zu finden: https://msdn.microsoft.com/en-us/library/windows/desktop/bb774096(v=vs.85).aspx. Da es wie immer eine Tortur ist, eine aktuelle Beschreibung in der MSDN zu finden, sei noch diese Methode genannt, um alle möglichen Werte zu sehen:

0..250| % { $v=($shell.NameSpace($_)).Self; if ($v -ne $null) { New-Object psObject -Property @{Index=$_; Name=$v.Name; Path=$v.Path}} }

Weiter beim eigentlichen Thema. Nun wird es langsam was, so bekommt man beides zusammen:

$dl = Get-ChildItem $desktop.Self.Path -Filter *.lnk
$dl += Get-ChildItem $publicDesktop.Self.Path -Filter *.lnk

Nun enthält $dl tatsächlich alle LNK-Dateiverweise. Jetzt also zum Inhalt der Verknüpfungen. Da LNK-Dateien ein eigenwilliges Binärformat haben, muss dieses speziell gelesen werden. Aber die Shell-Klassen bieten hier auch Unterstützung. Dazu gibt es die Methode ParseName, welche so angewendet werden kann:

$fileItem = $desktop.ParseName($dl[0].Name)
$fileItem.IsLink

Erst jetzt weiß man, ob die LNK-Datei wirklich eine Linkdatei ist. Wenn dem so ist, kann man hiermit das Link-Objekt instanzieren:

$sc = $fileItem.GetLink

$sc enthält, dann z. B. Daten wie diese:

Path             : C:\Windows\SysWOW64\cmd.exe
Description      :
WorkingDirectory : C:\windows\SysWOW64
Arguments        :
Hotkey           : 0
ShowCommand      : 1
Target           : System.__ComObject

Hier kann man nun konkret auch den Pfad oder das Working-Directory ändern. So kann man z. B. im obigen Beispiel den Pfad von SysWOW64 in System32 ändern, welches dann so aussieht:

$sc.Path = $sc.Path.Replace("SysWOW64", "System32")

Damit diese Änderung aber tatsächlich auch auf der Platte landet, muss die Änderung noch gespeichert werden:

$sc.Save

Leider hat die bisherige Vorgehensweise ein paar Probleme. Denn das obige Zusammenführen des User- und des Öffentlichen-Desktop, macht Probleme. denn ParseName verlangt immer den reinen Dateinamen ohne Pfad, was dann bei Anwendung obiger Methode bei öffentlichen Desktopobjekten beim Aufruf über $desktop nicht zum Ziel führt. Man sollte also $dl nach dem Pfad abfragen und entsprechend $desktop oder $publicDesktop verwenden.

if ($_.DirectoryName –eq $desktop.Self.Path) {
  $fi = $desktop.ParseName($_)
} else {
  $fi = $publicDesktop.ParseName($_)
}

Somit hat man nun in $fi immer das richtige FileItem und kann so weiterverfahren:

if ($fi.IsLink) {
  $sc = $fi.GetLink
  $sc.Path = $sc.Path.Replace("ALT", "NEU")
  $sc.Save

}

Übrigens kann man nicht nur LNK-Dateien sondern auch .URL und .WebSite –Dateien damit bearbeiten, welche etwas abgewandelte Link-Dateien sind. Von der Verarbeitung jedoch ändert sich nichts, man geht direkt auf die Pfad-Eigenschaft los und ändert diese.

So da es nun wie so oft etwas unübersichtlich wurde, alles nochmal geballt, inkl. .URL und .WEBSITE:

$shell = New-Object –ComObject Shell.Application
$desktop = $shell.Namespace(0x10)
$publicDesktop = $shell.Namespace(0x19)
$dl = Get-ChildItem $desktop.Self.Path -Filter *.lnk
$dl += Get-ChildItem $desktop.Self.Path -Filter *.url
$dl += Get-ChildItem $desktop.Self.Path -Filter *.website
$dl += Get-ChildItem $publicDesktop.Self.Path -Filter *.lnk
$dl += Get-ChildItem $publicDesktop.Self.Path -Filter *.url
$dl += Get-ChildItem $publicDesktop.Self.Path -Filter *.website
$dl | foreach {
    if ($_.DirectoryName –eq $desktop.Self.Path) {
         $fi = $desktop.ParseName($_.Name)
    } else {
         $fi = $publicDesktop.ParseName($_.Name)
    }
    if ($fi.IsLink) {
       $sc = $fi.GetLink
       $sc.Path = $sc.Path.Replace("ALT", "NEU")
       $sc.Save()
    }
}

Falls man eine Fehlermeldung wie z. B. diese bekommt

Es ist nicht möglich, eine Methode für einen Ausdruck aufzurufen, der den NULL hat.
In Zeile:21 Zeichen:8
+        $sc.Path = $sc.Path.Replace("ALT", "NEU")
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

sollte man sich überlegen, das Script vielleicht als Admin auszuführen, denn es ist nicht so gern gesehen, wenn einfache Benutzer den Öffentlichen Desktop verändern!

CHKDSK Ergebnisse per Powershell auslesen

17 September 2015

Wenn man ChkDsk auf Laufwerk C: eines Windows Rechners anwendet, wird man meist gefragt, ob man beim nächsten Neustart die Prüfung durchführen möchte. Soweit kein Problem. Nur muss man sich nach der Prüfung die passende Log-Datei heraussuchen, mit GUI mitteln wie immer mühsam, deshalb hier ein kleiner Powershell-Einzeiler, der die CHKDSK-Einträge auflistet:

Get-WinEvent -FilterHashtable @{logname="Application"; id="1001"}| where providername -eq Microsoft-Windows-WinInit | fl *

Wer sich für die vergangenen Prüfungen interessiert, der wird wahrscheinlich eher im “System Volume Information”-Verzeichnis, dort speziell im Chkdsk-Verzeichnis fündig. Dort gibt es z. B.

Chkdsk20150917130104.log

welche man sich per Powershell mittels

Get-Content .\Chkdsk20150917130104.log -Encoding Unicode

anschauen kann.

Um auf System Volume Information zugreifen zu können, benötigt man allerdings spezielle Rechte! Näheres hier: https://support.microsoft.com/en-us/kb/309531. Davon die Kurzfassung als Admin:

icacls "C:\System Volume Information" /E /G Admin:F

Wer sich für die reine Powershellfassung für ICACLS interessiert, wird hier fündig: http://blogs.technet.com/b/josebda/archive/2010/11/09/how-to-handle-ntfs-folder-permissions-security-descriptors-and-acls-in-powershell.aspx sowie http://blogs.msdn.com/b/johan/archive/2008/10/01/powershell-editing-permissions-on-a-file-or-folder.aspx.

Für was das “System Volume Information”-Verzeichnis alles herhalten muss: http://blogs.msdn.com/b/oldnewthing/archive/2003/11/20/55764.aspx.

Auswirkungen von 32-Bit Programmen unter 64-Bit Betriebssystemen

14 September 2015

Ein Kunde hat einen Brother PTouch Labeldrucker. Nach dem Umzug auf Windows 8.1 lief die zugehörige Software nicht mehr. Um dem Problem auf die Spur zu kommen war prinzipiell eine Aktualisierung der Client PTouch Software notwendig. Beim Testen zeigten sich aber die typischen Probleme bei Verwendung von 32-Bit Programmen unter 64-Bit Windows-Betriebssystemen. Deshalb hier mal exemplarisch was man machen kann und vor allem, wie sich die Probleme äußern.

Generell bietet es sich an, wenn man Problemen auf den Grund gehen möchte, eine Eingabeaufforderung zu öffnen. Jetzt muss man aber wissen, dass man unter einem 64-Bit Betriebssystem unter Windows normalerweise auch die 64-Bit CMD.EXE erhält. In der Regel klappt damit alles problemlos aber bei bestimmten Dingen provoziert man dadurch auf einmal ein anderes Verhalten.

So hatten wir ein Testskript in VBScript geschrieben, welches einfach nachvollziehbar ein Objekt erzeugen sollte. Der betreffende Eintrag lautete:

Set objDoc=CreateObject("bpac.Document")

als Fehlermeldung gab es aber immer

C:\Temp\TestDruckDirekt.VBS(10, 1) Laufzeitfehler in Microsoft VBScript:
ActiveX-Komponenten kann kein Objekt erstellen: ‚bpac.Document‘

Blöd sowas, aber wer verwendet noch VBScript? Also Powershell aufgerufen und da gibt es was ähnliches:

$c=new-object -ComObject "bpac.Document"
new-object : Die COM-Klassenfactory für die Komponente mit CLSID
{B940C105-7F01-46FE-BF41-E040B9BDA83D} konnte aufgrund des folgenden Fehlers
nicht abgerufen werden: 80040154 Klasse nicht registriert (Ausnahme von
HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).
In Zeile:1 Zeichen:4
+ $c=new-object -ComObject "bpac.Document"
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (:) [New-Object], COMExcept
   ion
    + FullyQualifiedErrorId : NoCOMClassIdentified,Microsoft.PowerShell.Comman
   ds.NewObjectCommand

Zwar ausführlicher aber im Prinzip die gleiche Meldung wie bei VBScript. Solche Geschichten sind immer irgendwie doof.

Da man aber in Powershell mehr Möglichkeiten hat, bietet sich z. B. dieses an: https://newyear2006.wordpress.com/2012/06/20/prfen-ob-eine-powershell-sitzung-in-einer-32bit-oder-64bit-prozess-umgebung-luft/. Damit kann man ganz einfach sehen, ob man unter einem 32-Bit oder 64-Bit Prozess läuft.

[System.IntPtr]::Size
8

Aha, also 8, d.h. die aktuelle Eingabeaufforderung ist unter 64-Bit unterwegs. Also nochmal denselben Test gemacht, nachdem mit

START C:\Windows\SysWOW64\CMD.EXE

eine neue Eingabeaufforderung explizit als 32-Bit Prozess gestartet wurde. Dort brachte dann die Überprüfung mittels Powershell die 4 für einen 32-Bit Prozess als Ergebnis.

Wenn man nun unter dieser Shell das Testscript.VBS aufruft, läuft alles.

Hat man Batchdateien in diesem Zusammenhang laufen, dann kann man die Umgebungsvariablen PROCESSOR_ARCHITECTURE und PROCESSOR_ARCHITEW6432 abfragen. Speziell wenn die Umgebungsvariable PROCESSOR_ARCHITEW6432 vorhanden ist, weiß man, dass man unter einem 64-Bit-System unter einem 32-Bit Prozess unterwegs ist. Hier ist die Sache mit PROCESSOR_ARCHITEW6432 näher beschrieben: http://blogs.msdn.com/b/david.wang/archive/2006/03/26/howto-detect-process-bitness.aspx

Phänomene mit QNAP NAS und großen Dateien, wie Reboots, Abbrüche usw – was das mit der Zeit zu tun hat

11 September 2015

Die primäre Aufgabe eines NAS ist eigentlich große Datenmengen zu speichern, wenn aber diese Aufgabe nicht erfüllt wird, stellt sich die Frage nach dem Sinn. Bei einem QNAP eines Kunden lief auf einmal die Sicherung nicht mehr durch. Es gab ständig Abbrüche nach ca. 32GB. Dabei wurde nur per SMB auf das NAS gesichert eine Funktion die davor über Jahre lief.

Allerdings wurde vor kurzem die NAS-Firmware aktualisiert, lag da das Problem? Tatsächlich gab es kurz darauf nochmal ein Update, allerdings deutete die Changelog nicht auf die Probleme. Also trotzdem das Update probiert aber leider keine Besserung.

Erstaunlich war, dass bei den Systemereignisprotokollen diese Meldung stand:

[Mirror Disk Volume: Drive 1 2] The file system is not clean. It is suggested that you go to [Storage Manager] to run "Check File System".

Der Versuch dieses Problem zu beheben klappte erst nach mehreren Anläufen. Gleichzeitig schien der NAS manchmal Nachts einen Neustart hinzulegen.

An einem Punkt war es sogar so schlimm, dass der Versuch das Dateisystem zu prüfen sofort mit den Meldungen

[Mirror Disk Volume: Drive 1 2] Examination failed(Cannot unmount disk by vs_refres).

und

[Mirror Disk Volume: Drive 1 2] Examination failed(Cannot unmount disk by smbd).

abgebrochen wurde. Diese Meldung blieben auch, obwohl das NAS vor dem Aufruf extra nochmal neu gebootet wurde und damit die Wahrscheinlichkeit recht gering war, dass ein Prozess den Vorgang blockiert.

Kurz davor die große Debugaktion zu starten, um dem Problem auf den Grund zu gehen, fiel mir noch eine Abweichung bei der NAS-Uhrzeit auf. OK einen Versuch ist es Wert. Es waren zwar nur drei Minuten aber für Rechner können das Ewigkeiten sein. Die Überlegung war: Neueste Firmware, damit Samba 4.x und damit Kerberos und deshalb pingelig mit den Zeiten.

Tatsächlich brachte dies dann die Lösung! Nun flutscht wieder alles.