Archive for the ‘Forensik’ Category

Soft- und Hardware-Inventarisierung per Powershell leichtgemacht

5 August 2015

Von Zeit zu Zeit muss man wissen, was alles in einem System verbaut ist, welche Software installiert ist, welche Frameworks verfügbar sind, welche DLLs da sind, welche Fehler aufgetreten sind, wie viel Speicherplatz frei ist, wann die Oma Geburtstag hat usw. usf.

Nichts leichter als das, man halte Zettel und Bleistift bereit und gibt in einer Powershelleingabeaufforderung – am besten mit Adminrechten – folgendes ein:

Get-CimAssociatedInstance (Get-CimInstance CIM_ComputerSystem)

Nun nehme man Zettel und Bleistift zur Hand und schreibe mit.

Mittels Alias wird es noch etwas knackiger:

Get-CimAssociatedInstance (gcim CIM_ComputerSystem)

Damit es funktioniert braucht man nur Windows 8, Server 2012 oder höher. Um es auf Windows 7 oder Server 2008 R2 ausführen zu können, benötigt man das Microsoft Management Framework 3.0, welches Powershell 3.0 mitbringt und damit auch die CIM-Cmdlets.

So wer jetzt immer noch die Infos auf seinem Zettel mitschreibt, dem sei gesagt, das Ding läuft EWIG, auch auf guter und aktueller Hardware!

Netter Nebeneffekt: Da durch den Aufruf so ziemlich alles im System angelangt wird, was irgendwie installiert oder verbaut ist, eignet sich der Aufruf auch ideal um Rechner auf Zuverlässigkeit zu testen. Forensiker freuen sich über die Vielzahl von Informationen. Mal sehen, vielleicht taugt es sogar für DOS-Attacken…

Übrigens, wer die ganzen Infos noch langfristig speichern möchte, der fügt noch ein | Export-CliXml Inventar.xml hinzu, also so:

Get-CimAssociatedInstance (gcim CIM_ComputerSystem) | Export-CliXML $Env:USERPROFILE\Inventar.XML

Somit kann man die ganzen Infos später wieder mittels Import-CliXML einlesen und zum Vergleich heranziehen. Somit hat man eine Baseline mittels der Veränderungen immer nachvollzogen werden können.

Nutzt man Powershell 5.0 kann man die XML-Datei mittels Compress-Archive noch etwas kleiner bekommen. Leider hat MS an den Möglichkeiten bei Compress-Archive etwas gezaudert, so dass nicht ein Stream von Export-CliXML übernommen werden kann, sondern es muss die XML-Datei von der Platte gelesen und dann komprimiert werden:

Compress-Archive $Env:USERPROFILE\Inventar.XML $Env:USERPROFILE\Inventar.ZIP

Hier noch eine kleine Einführung in CIM: http://blogs.msdn.com/b/powershell/archive/2012/08/24/introduction-to-cim-cmdlets.aspx.

Werbeanzeigen

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. https://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 https://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."