Volatility-Workshop (1) : Der Weg in den Hauptspeicher und zu den Prozessen
Im Nachgang zu seinem Überblicksbeitrag [1] zu Prozessen und Open-Source-Tools für Incident-Response und Forensik behandelt unser Autor in einer Reihe von Workshop-Beiträgen den konkreten Einsatz entsprechender Softwarewerkzeuge. Als Erstes steht die Hauptspeicherforensik mit Volatility auf dem Programm.
Von Jochen Schlichting, Karlsruhe
Die Hauptspeicherforensik (oder Speicheranalyse) ist eine Untersuchungstechnik, bei der forensische Artefakte (Datenspuren) im physischen oder virtuellen Speicher (RAM) eines IT-Systems gesucht, idealerweise gefunden und möglichst extrahiert werden. Der Speicher enthält wertvolle Informationen über den Laufzeitzustand des IT-Systems – sichert und analysiert man den Hauptspeicher, entdeckt man meistens die notwendigen Informationen für eine forensische Untersuchung: zum Beispiel welche Anwendungen laufen, auf welche Objekte (Datei, Registrierung usw.) sie zugreifen, aktive Netzwerkverbindungen, geladene Module und Kerneltreiber sowie andere Informationen. Aus diesem Grund wird die Hauptspeicherforensik häufig von Security-Incident-Response-Teams (SIRTs) im Rahmen der Vorfallsbekämpfung (Incident-Response) und Malware-/Schadsoftware-Analyse eingesetzt.
Während der Vorfallsbekämpfung hat man heute in den meisten Fällen keinen Zugriff auf die Schadsoftware selbst (Malware-Samples), sondern besitzt nur das Hauptspeicherabbild eines verdächtigen IT-Systems – beispielsweise nachdem eine Monitoringlösung eine Warnung über ein auffälliges Verhalten ausgelöst hat. Mittels forensischer Methoden kann man ein Speicherabbild tiefergehend auf Unregelmäßigkeiten und verdächtige Artefakte prüfen und gegebenenfalls weitere Schritte zur Analyse und Eindämmung einer Infektion vollziehen.
Hinterlässt ein Angriff oder Schadprogramm keine verräterischen Spuren auf der Festplatte (sog. Memory-only Malware), kann die Hauptspeicherforensik sogar die einzige Methode sein, um Hinweise auf verdächtige oder maliziöse Komponenten zu finden.
Liegt doch ein Sample vor, kann man es zusätzlich für eine statische und dynamische Codeanalyse in einer kontrollierten (meist isolierten) Umgebung zur Ausführung bringen, den infizierten Hauptspeicher sichern und analysieren, um ein besseres Verständnis vom Verhalten der Malware nach der Infektion zu erhalten. Vorteilhaft ist hierbei, dass eventuelle Schutzfunktionen von Malware zur Entdeckung von Sandboxes oder nach dem Erkennen forensischer Live-Werkzeuge ausgehebelt werden, da der Code auf einem „normalen“ System ausgeführt wird.
Unabhängig vom Zweck und Ziel steht der eigentlichen Analyse des Hauptspeichers dessen forensische Erfassung voran, bei der das Hauptspeicherabbild eines IT-Systems auf ein Speichermedium (bspw. Festplatte, USB-Stick oder via Netpipe) gesichert wird.
Akquisition des Hauptspeichers
Der Prozess zur Sicherung des Inhalts eines flüchtigen Speichers (RAM) auf einen nichtflüchtigen Speicher ist einer der wichtigsten und brenzligsten Schritte der Hauptspeicherforensik. Leider vertrauen viele Analysten blind auf Akquisitionstools, ohne sich Gedanken darüber zu machen, wie diese Werkzeuge funktionieren oder auf welche Art von Problemen sie dabei stoßen könnten. Infolgedessen erhält man nicht selten beschädigte Hauptspeicherabbilder, zerstörte Beweise und eine eingeschränkte Analysierbarkeit.
Geht man hingegen richtig vor, liefert das Verfahren im besten Fall Beweise, die helfen können, den aktuellen Zustand des IT-Systems und bis zu einem gewissen Grad die in letzter Zeit durchgeführten Aktivitäten abzuleiten. Es ist zu beachten, dass der „aktuelle“ Zustand der Zeitpunkt sein könnte, an dem die Erfassung begonnen hat, beendet wurde oder ein beliebiger Zeitpunkt dazwischen – je nachdem, in welcher Reihenfolge die physischen Speicherseiten, welche die betreffenden Daten enthalten, gesammelt wurden. Im ungünstigsten Fall erhält man hingegen einen beschädigten Hauptspeicherabzug, den Analysewerkzeuge nicht verarbeiten können, da die Erfassung bestimmter Memorypages nach Beginn einer kritischen Operation, aber vor deren vollständigem Abschluss erfolgte – das kann in zeitlich kritischen Vorfallsbekämpfungen dazu führen, dass eventuell kein zweiter Versuch der Akquisition mehr durchgeführt werden kann. Es lohnt sich also, gut vorbereitet zu sein und sorgsam vorzugehen.
In der Praxis hat sich für Windows das als Open Source verfügbare Werkzeug WinPMem (https://github.com/Velocidex/c-aff4/releases) durch Stabilität und Zuverlässigkeit in der Live-Forensik bewährt. WinPMem funktioniert sowohl mit x86- (32 Bit) als auch mit x64- Windowsinstallationen (64 Bit). Es unterstützt in der aktuellen Version 3.2 sowohl Windows als auch OSX und in einer älteren Version Linux und kann unterschiedliche Abbild-Formate erzeugen, darunter das „Advanced Forensics File Format“ (AFF4) mit sehr vielen Metadaten im komprimierten Form, aber auch das recht gebräuchliche, praktische RAW-Format.
Für die Erzeugung eines RAW-Formats für ein Windowssystem reicht die Ausführung von einem USB-Datenträger mit lokalen Administratorrechten, etwa via X:\winpmem_3.2.exe –o DomainController-DC02.img –volume_format raw -dd -t
In den meisten Fällen kann man den Hauptspeicher einer virtuellen Maschine (VM) sichern, indem man von einer VM-Instanz auf einem ESX-Server die folgenden Zustände mit den dazugehörigen Dateien/Extensions sichert: Snapshots (*.vmem und .vmsn) sowie Suspended-Mode (.vmss). Im forensischen Laborbetrieb nutzt man diese Möglichkeiten teilweise für die Analyse von Malware-Samples, um gezielt verschiedene Zustände des Hauptspeichers während der Ausführung zu erzeugen, die unterschiedliche Situationen in den zwölf Angriffsklassen der ATT&CK Matrix nach Mitre abbilden (vgl. https://attack.mitre.org/matrices/enterprise/).
Speicheranalyse mit Volatility
Volatility (www.volatilityfoundation.org) ist ein in Python geschriebenes Open-Source-Forensik-Framework, mit dem sich digitale Artefakte aus einem Speicherabbild analysieren und extrahieren lassen. Das Tool läuft auf verschiedenen Plattformen (Windows, OSX und Linux) und unterstützt die Analyse von Hauptspeicher abbildern aus 32- und 64-Bit-Versionen von Windows, MacOS und Linux-Betriebssystemen.
Installation von Volatility
Der schnellste Weg, um mit Volatility zu beginnen, ist die Verwendung einer vorkompilierten ausführbaren Programmdatei, die unter www.volatilityfoundation.org/releases für Windows, MacOS und Linux bereitliegt. Der Vorteil besteht darin, dass der Python 2.7-Interpreter und die Paketabhängigkeiten von Volatility direkt in dieser Programmdatei integriert sind und die derzeit vorliegende Version seit 2015 ausgiebig auf Robustheit getestet wurde.
Ein einfacher Weg, um die generelle Funktionsfähigkeit nach dem Herunterladen der Programmdatei zu überprüfen, ist ein Aufruf per Kommandozeile mit der Option „-h“ (oder „–help“). Die Antwort zeigt wie üblich die verschiedenen Optionen und zudem Plugins an, die in der vorliegenden Version verfügbar sind.
Installation des Quellcodes
Volatility ist auch als Python-Quellcode erhältlich, der auf Windows-, OSX-, Linux- und BSD-Betriebssystemen ausführbar ist. Volatility nutzt für Analyseaufgaben verschiedene Plugins. Der Link https://github.com/volatilityfoundation/volatility/wiki/Installation#recommended-packages liefert eine Liste der Python-Pakete von Drittanbietern, die von einigen der Volatility-Plugins benötigt werden.
Um Volatility erfolgreich ausführen zu können, müssen sowohl der Python-2.7-Interpreter als auch alle benötigten Pakete (Requirements) funktionsfähig installiert sein. Sehr pragmatisch ist eine solche Installation „im Paket“ unter OpenBSD 6.5 (www.openbsd.org) möglich: Über den Befehl „pkg_add volatility“ lässt sich so etwa ein gehärtetes Analysesystem in weniger als 30 Minuten in Betrieb nehmen.
Die in diesem Beitrag genutzten Beispiele verwenden das Volatility Python-Skript (vol.py) aus dem Quellcodepaket. Der Einsatz einer vorkompilierten Programmdatei ist aber genauso möglich – der Skriptaufruf „vol.py“ ist dann in den Beispielen einfach durch den entsprechenden Dateinamen zu ersetzen.
Generelle Verwendung
Volatility besteht, wie bereits angemerkt, aus verschiedenen Plugins, die verschiedene Informationen aus dem Hauptspeicherabbild extrahieren können. Will man beispielsweise die laufenden Prozesse aus dem Speicherabbild anzeigen, kann man das Plugin pslist verwenden, für Netzwerkverbindungen netscan. Abbildung 1 zeigt ein Beispiel, wie man mit pslist die laufenden Prozesse aus einem Speicherabbild von Windows Server 2012 R2 (64-Bit) mit Service Pack 1 auflistet.
Die Hilfeoption (-h bzw. –help) zeigt übrigens auch pluginspezifische Optionen und Argumente an – beispielsweise durch den Aufruf „vol.py pslist -h“. Im Hilfetext eines Plugins finden sich meist viele kleine Funktionen, die bei der ersten Nutzung fast immer nicht offensichtlich sind, aber sehr hilfreich sein können.
Es gibt in Version 2.6.0 insgesamt 113 Plugins allein für Windows. Für die Einbindung zahlloser Community-Plugins (siehe https://github.com/volatilityfoundation/community) ist es zwingend erforderlich, dass die Option „–plugins“ zur Angabe zu durchsuchender lokaler Plugin-Verzeichnisse direkt nach dem Aufruf des Volatility-Skripts (bzw. der Programmdatei) angegeben wird.
Unabhängig vom gewählten Plugin ist zudem die richtige Reihenfolge der Befehlssyntax wichtig: Mit „-f“ wird der Pfad zur Speicherabbilddatei definiert und „–profile“ spezifiziert für Volatility, zu welchem IT-System und welcher Architektur das Speicherabbild passt (bspw. Win2008R2SP1x64). Insgesamt ergibt sich als Basis die folgende Kommandozeilenstruktur:
$ vol.py –plugins= -f –profile= [Arguments]
Alternativen zu Befehlszeilenoptionen
Wer eine längere Analyse beginnt und nicht jedes Mal den Pfad zum Hauptspeicherabbild, den Profilnamen und andere Optionen (bspw. –plugins oder –dtb) mit ihren zugehörigen Parametern angeben möchte, kann ein paar sinnvolle „Abkürzungen“ nutzen: Volatility untersucht sowohl Umgebungsvariablen als auch Konfigurationsdateien (in genau dieser Reihenfolge) nach Optionen, wenn diese nicht in der Befehlszeile angegeben werden. Gleich bleibende Parameter lassen sich so wiederverwenden, was neben einer Zeitersparnis nicht zuletzt eine Minimierung von Eingabefehlern bedeutet.
Standardmäßig sucht Volatility im aktuellen Verzeichnis oder in einem mit der Option –conf-file angegebenen Pfad nach einer Datei namens „.volatilityrc“. Dies ist beispielsweise sehr praktisch, wenn unterschiedliche Speicherabbilddateien in verschiedenen Analyseverzeichnissen vorgehalten werden. Die Konfigurationsdatei verwendet das Standard-INI-Format – zunächst muss ein Abschnitt mit dem Namen „DEFAULT“ vorhanden sein, gefolgt von den Optionen, die man mit einem Parameter einstellen möchte (vgl. Abb. 2). Eine entsprechende Konfigurationsdatei wird auch in den folgenden Beispielen vorausgesetzt, um unnötig lange Kommandozeilen und stetige Wiederholungen der Parameter zu vermeiden.
Das passende Profil
Die meisten Volatility-Plugins basieren darauf, Informationen aus den Betriebssystemstrukturen zu extrahieren, die aber je nach Version (Build) variieren. Über die Option „- – profile“ teilt man Volatility mit, welche Datenstrukturen, Symbole und Algorithmen verwendet werden sollen.
Manchmal ist bei einem Speicherabbild zunächst unklar, welches Profil Volatility nutzen sollte. In diesem Fall kann man das „imageinfo“-Plugin verwenden, um das richtige Profil zu bestimmen. Abbildung 3 zeigt ein Beispiel, bei dem imageinfo mehrere Profile vorschlägt – meist kann in einem solchen Fall jedes der vorgeschlagenen Profile verwendet werden.
Sofern man neue Builds von Windows analysieren muss, kann es allerdings sein, dass Volatility hierfür kein Profil kennt. Eine Alternative ist es dann, Analysen mit dem Tool „Rekall“ (https://github.com/google/rekall) durchzuführen, das meist in der Lage ist, dynamisch ein Profil zu erstellen. Rekall ist jedoch mit Volatility nicht kompatibel.
Prozesse im Hauptspeicher
Die nachfolgenden Abschnitte erläutern genauer, wie sich forensische Artefakte mit verschiedenen Plugins aus einem Speicherabbild extrahieren lassen. Bei solchen Untersuchungen konzentriert man sich hauptsächlich darauf, verdächtige Prozesse – im betrachteten Beispiel unter Windows – zu identifizieren. Zum Auflisten von Prozessen gibt es in Volatility verschiedene Plugins.
Auflisten von Prozessen mit pslist
Das pslist-Plugin listet Prozesse aus einem Speicherabbild ähnlich auf wie der Task-Manager Prozesse auf einem laufenden Windows-System anzeigt. Der Beispiel-Output in Abbildung 1 zeigt einen Auszug aus dem Ergebnis eines Speicherabbilds, das mit dem Exploit „EternalBlue“ (via DoublePulsar) infiziert ist. Darin sind viele verdächtige Prozesse von csrs.exe zu erkennen (PID 3720, 10512 etc.) – diese fallen Forensikern auf, weil ihr Name eine Verkürzung gegenüber dem Standardprozess csrss.exe darstellt. Auf einem sauberen Windows findet man csrss.exe-Instanzen zudem nur ohne eine Parent Process-ID (PPID). Im Beispiel ist es jedoch die PPID 4172 von smss.exe, die auf einem sauberen Betriebssystem nach dem Starten von Child-Prozessen beendet würde. Durch die Erstellung eines Prozesses wie csrss.exe versucht der Angreifer, sich anzupassen, indem er diese Prozesse dem legitimen csrss.exe-Prozess ähnlich aussehen lässt. Die csrs.exe-Instanzen dienen hingegen zum Scannen und zur Weiterverbreitung von EternalBlue.
Man kann ein Plugin in Volatility recht einfach ausführen, ohne zu wissen, wie es funktioniert – das Verständnis um seine Funktionsweise hilft allerdings naturgemäß erheblich dabei, die Genauigkeit und Aussagekraft der Ergebnisse zu beurteilen sowie das richtige Plugin auszuwählen, wenn ein Angreifer beispielsweise Tarnmechanismen einsetzt. Wie also funktioniert pslist? Für die Antwort muss man zuerst verstehen, was ein Prozess eigentlich ist und wie der Windows-Kernel Prozesse verfolgt.
Hintergrund: Prozesse unter Windows
Das Windows-Betriebssystem ist objektbasiert – ein Prozess ist ein Objekt (allerdings nicht zu verwechseln mit dem in objektorientierten Sprachen verwendeten Objektbegriff). Unter Windows bezieht sich ein Objekt auf eine Systemressource (z. B. ein Prozess, eine Datei, ein Gerät, ein Verzeichnis, ein Mutant usw.) und wird von einer Kernelkomponente namens Objektmanager verwaltet. Um einen Überblick über alle Objekttypen unter Windows zu erhalten, kann man etwa das WinObj-Tool verwenden (https://docs.microsoft.com/en-us/sysinternals/downloads/winobj) – dazu startet man WinObj einfach als lokaler Administrator und klickt im linken Bereich auf ObjectTypes, um alle Windows-Objekte aufzulisten.
Die Objekte werden in C als Strukturen dargestellt. Das bedeutet, dass einem Prozessobjekt eine Struktur zugeordnet ist, die als _EPROCESS-Struktur bezeichnet wird und sich im Kernelspeicher befindet. Der Windows-Kernel verwendet diese Struktur, um einen Prozess intern darzustellen. Sie enthält dazu verschiedene Informationen wie den Namen des Prozesses, die Prozess-ID (PID), die übergeordnete Prozess-ID (PPID), die Anzahl der dem Prozess zugeordneten Threads, die Erstellungszeit des Prozesses und so weiter.
Im pslist-Output von Abbildung 1 zeigt beispielsweise der achte Eintrag den Prozess-Namen lsass.exe, seine Prozess-ID 500, die übergeordnete Prozess-ID 396 und so weiter – diese Informationen entstammen seiner _EPROCESS-Struktur.
Will man nur Informationen eines bestimmten Prozesses ermitteln, lässt sich der pslist-Output anhand seiner PID beschränken – dazu dient die Option ist „-p“ (oder „–pid“). Eine weitere wichtige Option ist „- – output-file“, um die Ausgabe in eine Datei umzuleiten: $ vol.py pslist – – output-file=pslist.txt
Auflistung von Prozessen mit psscan
psscan ist ein weiteres Volatility-Plugin, das die auf dem Betriebssystem Windows laufenden Prozesse auflistet. Anders als pslist nutzt es dazu aber nicht die doppelt verknüpfte Liste (Doubly Linked List) der _EPROCESS-Objekte, sondern durchsucht stattdessen den physischen Speicher nach der Signatur von Prozessobjekten (sog. Pool-Tag-Scanning).
Aufgrund dieses Ansatzes kann psscan daher zusätzlich sowohl beendete als auch versteckte Prozesse erkennen. Ein Angreifer kann einen Prozess etwa ausblenden, um zu verhindern, dass ein Analyst während einer Live-Forensik einen schädlichen Prozess direkt auf dem Windows-System entdeckt. Für ein solches Versteckspiel kann beispielsweise eine Angriffstechnik zum Einsatz kommen, die als „Direct Kernel-Object-Manipulation“ bekannt ist.
Hintergrund: Direct Kernel-Object Manipulation (DKOM)
Um einen Prozess (oder auch einen Treiber usw.) auszublenden, findet ein Angreifer die zugehörige _EPROCESS-Struktur eines schädlichen Prozesses und ändert darin das Feld „ActiveProcessLinks“: Dazu setzt er den Front-Link des vorherigen _EPROCESS-Blocks auf den Front-Link des nachfolgenden _EPROCESS-Blocks und den Back-Link des nachfolgenden _EPROCESS-Blocks auf den Front-Link des vorherigen _EPROCESS-Blocks. So wird der dem Malware-Prozess zugeordnete _EPROCESS-Block aus der doppelt verlinkten Liste herausgetrennt.
Durch dieses Entkoppeln eines Prozesses kann ein Angreifer ihn vor forensischen Werkzeugen (live oder z. B. auch pslist) verstecken, die darauf angewiesen sind, diese Liste zu durchlaufen, um aktive Prozesse zu finden. Abbildung 4 zeigt auszugsweise den Output von pslist und psscan von einem mit einer Malware infizierten Windows, bei dem DKOM einen Prozess versteckt. Vergleicht man die Ausgaben, findet man bei psscan zusätzliche Prozesse ohne Namen mit hohen PIDs, die bei pslist nicht auftreten (der Übersicht halber ist der Output in Abb. 4 stark verkürzt).
Hintergrund: Pool-Tag-Scanning-Methode
Windows-Systemressourcen wie Prozesse, Dateien, Threads und so weiter sind sogenannte Exekutivobjekte und werden, wie angemerkt, vom Objektmanager verwaltet. Jedem solchen Objekt ist eine Struktur zugeordnet (z. B. _EPROCESS für Prozessobjekte). Dieser exekutiven Objektstruktur geht eine _OBJECT_HEADER-Struktur voraus, die Informationen über den Typ eines Objekts und einige Referenzzähler enthält – dem _OBJECT_HEADER gehen wiederum null oder mehr optionale Header voraus. Anders gesagt kann man sich ein solches Objekt als die Kombination aus „executive object“, „object header“ und „optional headers“ vorstellen.
Für ein Objekt wird Speicher benötigt, der vom Windows-Speichermanager aus Kernel-Pools zugewiesen wird: Ein Kernel-Pool ist ein Speicherbereich, der in kleinere Blöcke zur Speicherung von Daten wie Objekten unterteilt werden kann. Der Pool gliedert sich in einen Paged Pool, dessen Inhalt auf die Festplatte ausgelagert werden kann, und einen Non-Paged-Pool, dessen Inhalt sich dauerhaft im Hauptspeicher befindet. Objekte wie Prozesse und Threads werden in einem nicht ausgelagerten Pool im Kernel gehalten, befinden sich also immer im physischen Speicher.
Wenn der Windows-Kernel die Anforderung erhält, ein Objekt zu erstellen (möglicherweise aufgrund von API-Aufrufen, durch CreateProcess- oder CreateFile-Prozesse), wird dem Objekt abhängig von seinem Typ entweder Speicher aus dem Paged- oder dem Non-Paged-Pool zugewiesen. Diese Zuordnung erfolgt, indem dem Objekt eine _POOL_HEADER-Struktur vorangestellt wird, sodass im Speicher jedes Objekt eine vorhersagbare Struktur hat. Die Struktur _POOL_HEADER enthält ein Feld namens PoolTag, das ein Vier-Byte-Tag (sog. Pool-Tag) enthält. Dieses Pool-Tag kann verwendet werden, um ein Objekt zu identifizieren: Für Prozessobjekte lautet es „Proc“, für File-Objekte „File“ und so weiter. _POOL_HEADER enthält zudem Felder, welche die Größe der Zuordnung und die Art des zugewiesenen Speichers angeben.
Man kann sich alle Prozessobjekte, die sich im nicht ausgelagerten Pool des Kernelspeichers befinden (der letztendlich auf den physischen Speicher abbildet) so vorstellen, als ob sie mit dem Tag ‚Proc‘ markiert wären – dieses Tag verwendet psscan (so wie viele weitere Volatilitys-Plugins) als Ausgangspunkt für die Identifizierung von Prozessen. Sobald das Plugin ein Prozessobjekt gefunden hat, extrahiert es die notwendigen Informationen aus dessen _EPROCESS-Struktur des Prozessobjekts.
psscan kann so nicht nur versteckte, sondern auch bereits beendete Prozesse erkennen: Denn wenn ein Objekt „zerstört“ wird (z. B. weil ein Prozess endet), wird seine Speicherzuweisung wieder an den Kernel-Pool freigegeben, aber der Inhalt im Speicher nicht sofort überschrieben. Das eigentliche Prozessobjekt kann sich also noch im Speicher befinden, wo es psscan erkennt.
Ermitteln von Prozessbeziehungen
Bei forensischen Untersuchungen kann es sinnvoll sein, die Parent-Child-Relation (PPID->PID) zwischen Prozessen zu bestimmen. Bei der Untersuchung von Malware hilft dies etwa zu verstehen, welche anderen Prozesse damit zusammenhängen. Das pstree-Plugin zeigt die Parent-Child-Relationen an, indem es den Output aus pslist verwendet und in einer Art Baumansicht formatiert – ein Child-Prozess wird dabei nach rechts eingerückt und mit Punkten versehen.
Abbildung 5 zeigt die pstree-Ergebnisse eines mit EternalBlue via DoublePulsar infizierten Speicherabbilds. Man kann hier sehen, dass services.exe (PID 520) svchost.exe (PID 852) gestartet hat, das wiederum taskeng.exe (PID 1132) aufrief, um den Malware-Prozess CPUInfo.exe (PID 1164) auszuführen. Wenn man sich die Ereignisse ansieht, wird recht schnell sichtbar, dass services.exe offenbar kompromittiert wurde und mit seser.exe (PID 1096) und mssecsvc.exe (PID 1236) auch noch weitere Malware-Prozesse startet.
Da das pstree-Plugin auf pslist zurückgreift, kann es keine versteckten oder abgebrochenen Prozesse auflisten. Eine weitere Methode zum Bestimmen der Prozessbeziehung besteht darin, mit psscan eine visuelle Darstellung der Parent-Child-Relationen zu erzeugen. Der folgende Befehl psscan gibt den Output im .dot-Format aus, das sich dann mit einer Visualisierungssoftware wie Graphviz betrachten lässt:
$ vol.py psscan –output=dot
–output-file=eternalblue.dot
Analysen mit psxview
Die für Pool-Tag-Scans wichtige Struktur _POOL_HEADER dient ursprünglich nur zu Debuggingzwecken – Manipulationen daran beeinträchtigen nicht die Stabilität des Betriebssystems. Das bedeutet, dass ein Angreifer einen Kerneltreiber installieren könnte, der Pool-Tags oder jedes andere Feld im _POOL_HEADER ändern kann. So ließen sich Analyse-Plugins, die auf Pool-Tag-Scanning basieren, sabotieren – durch Ändern des Pool-Tags ist es etwa möglich, Prozesse vor psscan zu verbergen.
Um dieses Problem zu lösen, basiert das psxview-Plugin auf der Extraktion von Prozessinformationen aus verschiedenen Quellen: Es listet für einen Prozess sieben verschiedene Prüfmethoden auf – durch den Vergleich der Ergebnisse ist es möglich, Abweichungen zu erkennen, die durch die Malware verursacht sein könnten.
Die Informationen zu jedem Prozess werden in einer einzigen Zeile angezeigt, die bei der Suche erfolgreichen Methoden spaltenweise dargestellt (True/False). Abbildung 6 zeigt, wie psxview unter anderem den versteckten Prozess dllhost.exe (PID 4752) mit den Methoden psscan und thrdproc finden konnte.
Allerdings müssen nicht immer Manipulationen vorliegen, wenn Prozesse mit bestimmten Methoden nicht auffindbar sind. explorer.exe ist in Abbildung 6 beispielsweise ausschließlich per psscan gefunden worden. Der Prozess wurde aber nicht versteckt, sondern der Grund, warum fast überall „False“ steht, ist, dass explorer.exe mit der PID 5092 beendet wurde (siehe Spalte ExitTime) – und nur das Pool-Tag-Scanning kann abgebrochene Prozesse erkennen. Um einfach darzustellen, ob der gefundene Wert einer Methode erwartbar war oder nicht, kann man psxview – wie im zweiten Aufruf von Abbildung 6 – mit der Option „-R“ (oder „–apply-rules“) verwenden. Bestimmte „False“-Werte werden dann durch „Okay“ ersetzt – zeigen sich dennoch „False“-Angaben (z. B. wie bei WmiPrvSE.exe mit PID 4752), dann ist das ein starker Hinweis darauf, dass der betreffende Prozess bewusst vor der jeweiligen Methode verborgen wurde.
Mit psxview endet der erste Teil des Volatility-Workshops – die Fortsetzung wird sich in der nächsten <kes> mit Plugins und Techniken zu den folgenden Bereichen beschäftigen: Handles / Prozesszugriffe / DLLs / Extraktion / Netzwerkverbindungen / Registry / Services und Command History.
Jochen Schlichting (CISA, CISM, Auditteamleiter auf Basis von IT-Grundschutz) arbeitet als Consultant, Forensic Lead und Incident Responder bei der Secorvo Security Consulting in Karlsruhe (jochen.schlichting@secorvo.de).
Abbildung 1: Auflisten laufender Prozesse mit Volatility aus einem infizierten Speicherabbild von Windows-Server 2012 R2 (64-Bit) mit Service Pack 1
Abbildung 2: Einfaches Beispiel einer INI-Datei für Volatility (.volatilityrc)
Abbildung 3: Das Plugin „imageinfo“ kann zu einem vorliegenden Speicherabbild passende Profile vorschlagen.
Abbildung 4: Das psscan-Plugin kann auch versteckte Prozesse finden
Abbildung 5: Auszug des pstree-Outputs eines infizierten Speicherabbilds
Abbildung 6: psxview-Ausgabe zur Klärung, mit welchen Methoden (Plugins) Volatility Prozesse in einem Speicherabbild finden kann
Literatur
[1] Jochen Schlichting, Für alle (Vor-)Fälle, Prozesse und Open-Source-Tools für Incident-Response und Forensik, <kes> 2019#2, S. 27