N-W0rm Analyse (Teil 1)

Laut Malware Bazaar werden Samples seit ca. Mitte Januar verbreitet. Der finale Payload ist ein .NET RAT, welcher dem Angreifer die Möglichkeit gibt, Befehle an das infizierte System zu senden.

Überblick

Gegenstand dieses Artikels ist unsere Analyse einer N-W0rm-Sample. Dieses Modul wurde erst vor kurzem entdeckt. Laut Malware Bazaar wurde die erste Variante am 18. Januar 2022 entdeckt.

Wir haben diese N-W0rm Variante von Malware Bazaar erhalten und wissen daher nicht, wie diese verbreitet wird. Laut @executemalware wird N-W0rm jedoch per E-Mail zugestellt.

Das analysierte Sample kann hier heruntergeladen werden:

https://bazaar.abuse.ch/sample/1b976a1fa26c4118d09cd6b1eaeceafccc783008c22da58d6f5b1b3019fa1ba4/

Bevor wir mit der Analyse der N-W0rm Variante beginnen, sollten wir uns die Architektur der Kompromittierung genauer ansehen. Die folgende Abbildung zeigt die komplette Infektionskette, von der initialen Kompromittierung bis hin zum finalen Payload:

Abb.1: Infektionsverlauf

Wie in der obigen Abbildung ersichtlich, endet die Infektion mit zwei .NET-Binärdateien, die abgelegt werden. Im heutigen Artikel wird der gesamte Weg von der ersten Infektion bis zu diesem Punkt beschrieben. Die Analyse der beiden Binärdateien wird in unserem nächsten Artikel behandelt.

Stufe 1

Diese Variante wird als VBS-Datei geliefert, die obfuskiert ist, um die statische Analyse zu erschweren und Signaturen zu umgehen. In unserem ersten Schritt werden wir den VBS-Code deobfuskieren und die zweite Stufe enthüllen. Nachfolgend finden Sie den vollständigen Code der ersten Stufe. Zeile 3 enthält eine ziemlich lange Zeichenfolge, die obfuskierten PowerShell enthält. Da diese lange Zeile das Bild zerstören würde, haben wir sie aus ästhetischen Gründen ersetzt.

Abb. 2:Initialer VBS Code

Da der ursprüngliche Quelltext nur 5 Zeilen umfasst, können wir den Code Zeile für Zeile durchgehen. Hier werden einige wichtige Zeichenketten verschleiert, indem einige Zeichen durch andere Zeichen ersetzt werden und dieser Vorgang dann bei Ausführung rückgängig gemacht wird. Wir können diesen Vorgang mit Hilfe der Python REPL rückgängig machen.

Abb. 3: Entschleierung der 1. Zeile

Die Zeichenkette wird also zu Wscript.SheLL gewandelt. Das bedeutet, dass dieses Beispiel später einige Befehle an das Betriebssystem senden wird. In der nächsten Zeile passiert nichts von Relevanz, es wird lediglich das Wscript.SheLL-Objekt erstellt. Zeile 3 ist nun der interessante Teil, denn diese Zeile enthält eine lange Zeichenkette mit obfuskiertem PowerShell-Code. Wie in Zeile 4 wird auch dieser Code ausgeführt. Diesen analysieren wir vollständig, um diese Malware in Gänze zu verstehen. Wie in Zeile 3 ersichtlich, befindet sich der vollständige PowerShell-Code in einer Zeile. Normalerweise schreiben wir keinen derartigen Code. Um ihn besser lesbar zu machen, müssen wir diesen Code über mehrere Zeilen verteilen. Semikolons (;) werden verwendet, um Zeilenumbrüche anzuzeigen. Um diese zu unserem Vorteil zu nutzen, können wir diese lange Zeile in einen Texteditor einfügen und alle Semikolons durch einen Zeilenumbruch (\n) und ein Semikolon ersetzen, damit die Syntax erhalten bleibt.

Abb. 4: Optisch verbesserter PowerShell Code

Das erste, was uns ins Auge sticht, ist die IP-Adresse ganz oben. Wir werden später darauf zurückkommen, aber  zunächst haben wir einen wichtigen IOC gefunden.

Dieses PowerShell-Snippet definiert in Zeile 2 eine Funktion namens CHGBGWUCPVSBXIVTHVKR. Diese Funktion wird in Zeile 10 aufgerufen und das Ergebnis wird mit IEX in Zeile 11 ausgeführt. Anhand des Aufrufs von IEX können wir also davon ausgehen, dass die Funktion weiteren PowerShell Code dekodiert, der ausgeführt wird. Die Zeichenkette, die deobfuskiert werden soll, befindet sich in Zeile 10, die wiederum eine sehr lange Zeichenkette ist, die wir erneut ersetzt haben. Um diese Zeichenkette zu deobfuskieren, ist es wahrscheinlich am einfachsten, den gesamten Codeschnipsel zu kopieren, das IEX in Zeile 11 durch echo zu ersetzen und ihn in einer PowerShell-Sitzung auszuführen. Alternativ könnte man die Funktion z. B. in Python neu implementieren und sie dort ausführen. Wir haben uns für die zweite Methode entschieden und die Logik in Python neu implementiert. Der nachfolgende Screenshot zeigt den Code.

Abb.5: Reimplementierung der entschlüsselten Zeichenkette

Wenn wir unser Python-Skript ausführen, um die lange Zeichenfolge zu deobfuskieren, erhalten wir erneut einen verschleierten PowerShell-Befehl.

Abb. 6: Output des obigen Python-Skripts

Auch jetzt können wir diesen Code entweder in eine PowerShell-Sitzung eingeben oder das Skript z. B. in Python neu erstellen und es dort ausführen. Auch hier entscheiden wir uns für eine Neuimplementierung in Python. Der Code ist untenstehend zu sehen:

Abb. 7: Entschlüsselung und Output

Dieser letzte dekodierte Befehl bringt uns zurück zum Anfang. Erinnern Sie sich an die IP-Adresse am Anfang? Das ist der Inhalt der Variablen $Hx. Die komplette Dekodierung dient also nur dazu, die Datei herunterzuladen und auszuführen.

Stufe 2 (RILSXDKOPJHN.TXT)

Nun, die zweite Stufe sieht ein bisschen umfangreicher aus als die erste. Dieses Beispiel ist vollgepackt mit obfuskierten Zeichenketten und die Verwendung der replace-Funktion ist hier recht dominierend. Da diese Phase etwas mehr Code enthält als die vorherige, werden wir hier nicht jede einzelne Zeile durchgehen. Wenn Sie wirklich verstehen wollen, was hier passiert, empfehlen wir Ihnen, die Variante selbst herunterzuladen und mitzuverfolgen.

Wir beginnen mit der Dekodierung des ersten großen Blocks der obfuskierten Zeichenfolge gleich zu Beginn:

Abb. 8: Erster Block des verschleierten Codes der Stufe 2

Die obfuskierte Zeichenfolge steht in der zweiten Zeile. Diese Zeichenfolge wird zunächst durch zweimaligen Aufruf von replace() geändert. Schließlich wird die Zeichenkette durch die Schleife in Zeile 3 deobfuskiert. Diese Schleife mag auf den ersten Blick seltsam aussehen, aber sie ist recht einfach: Sie beginnt mit dem Aufruf von -split für die Zeichenkette aus Zeile 2, d. h. die Umwandlung der großen Zeichenkette in eine Liste auf der Grundlage einer Bedingung. Diese Regex-basierte Bedingung sucht nach Hex-Zeichen und teilt diese nach jedem zweiten Erscheinen. Das bedeutet, dass unsere Iterationsvariable immer zwei Hex-Zeichen enthält. Diese Zeichen werden dann in ASCII umgewandelt und schließlich miteinander verkettet. Wenn wir all dies zusammenfügen, können wir diese Logik in Python nachbilden.

Abb. 9: Python-basierte Entschleierung des ersten Blocks

Wenn Sie dieses Skript ausführen, erhalten Sie die folgende Ausgabe (der Übersichtlichkeit halber habe ich die Variable $A1 aus der ersten Zeile hinzugefügt):

Abb. 10: Erster vollständig entschleierter Block

Auch hier erhalten wir einen interessanten IOC. Die zweite Stufe beginnt also mit der Erstellung des Verzeichnisses C:\ProgramData\YHWZHLCQJHGQRFRHWZLCKSEUZIHLSJYATIODFBQPXTUSLQUEHVXQJENITGNZ und schläft dann 3 Sekunden lang.

Die nächsten beiden Zeilen sind wichtig, weil wir hier unsere Persistenzindikatoren erhalten. Das neu erstellte Verzeichnis wird als StartUp festgelegt, d. h. es wird bei jedem Neustart des Systems ausgeführt. Gehen wir zurück zum Code und sehen wir uns den nächsten Block an.

Der nächste Schritt ist interessant. Die Variable $ZEJOTRZCRVYEGGCGNZPLJDJROGPKEIGINPVGHOQXYSFSXBDOKJATKYHEPRNO enthält einen scheinbaren HTML-Inhalt, der mit einem Skriptblock beginnt, der VBScript-Code andeutet.

Abb. 11: Beginn des Skriptblocks

Die Funktion var_func() benötigt keine Argumente und hat nur den Zweck, mehrere in ihr enthaltene Zeichenketten zu entschleiern.

In Zeile 36 sehen wir, dass dies eine hta-Datei sein wird, die unter folgendem Pfad gespeichert wird: C:\Programdata\YHWZHLCQJHGQRFRHWZLCKSEUZIHLSJYATIODFBQPXTUSLQUEHVXQJENITGNZ\YHWZHLCQJHGQRFRHWZLCKSEUZIHLSJYATIODFBQPXTUSLQUEHVXQJENITGNZ.HTA

Abb. 12: Erstellung einer HTA Datei

Da der Inhalt dieses hta nur durch die Verwendung von wiederholten Aufrufen von replace() obfuskiert wird, werden wir nicht alle Schritte zur Entschleierung zeigen, sondern nur das Endergebnis. Die Entschlüsselung endet damit, dass die Skripte die nächste Stufe von http://15.188.246[.]78/Q/SSSSSSHSJSJSA.txt herunterladen und ausführen.

Stufe 3

Dies wird die letzte Phase sein, das verspreche ich!

Wieder werden wir mit einem Haufen obfuskiertem Codes begrüßt. Diesmal gibt es zwei große Blöcke von obfuskiertem Code. Beide Strings beginnen mit 4D5A, d.h. dem MZ-Header.

Danach folgt eine Funktion namens vip(). Sie sieht zwar etwas verwirrend aus, aber sie dekodiert nur die base64-Eingabe.

Schließlich enthält der Code einen großen Block obfuskiertem Codes, der als Eingabe an die Funktion vip() übergeben wird. Übergeben wir diesen großen Codeblock an die vip()-Funktion und sehen wir uns an, was passiert. Um die Dinge vielleicht ein wenig leichter zu verstehen, habe ich den entschlüsselten Block unten eingefügt.

Abb. 13: Letzter Codeblock der dritten Stufe

Wir können eine neue Funktion namens HB sehen, die einen einzigen Parameter annimmt und anscheinend eine Dekodierung vornimmt. Diese Funktion wird in den Zeilen 17 und 18 aufgerufen. Weiter unten erkennen wir einige wichtige Strings. Sehen Sie sich z. B. Zeile 33 an, wo wir Teile von .NET-Code zum Laden von Binärdateien in den Speicher sehen. Ich nehme an, dass alle Zeilen ab 19 nur dafür zuständig sind, die beiden Binärdateien zu laden, die in den Zeilen 17 und 18 dekodiert werden. Im Moment bin ich nicht wirklich daran interessiert, wie die Binärdateien geladen werden, sondern nur an den Binärdateien, die wir auf die Festplatte auslagern, indem wir sie deobfuskieren. Da wir nur die beiden Strings benötigen, die mit 4D5A beginnen – die Funktion, um sie zu entschlüsseln, und dann einen einzigen Aufruf der Funktion, können wir den folgenden Code schreiben.

Abb. 14: Entschleierung der zwei PEs

Bei der Ausführung dieses Codes werden zwei .NET-Binärdateien ausgegeben, die im nächsten Artikel analysiert werden.

 

Host-basierende Indikatoren:

  • C:\ProgramData\YHWZHLCQJHGQRFRHWZLCKSEUZIHLSJYATIODFBQPXTUSLQUEHVXQJENITGNZ\YHWZHLCQJHGQRFRHWZLCKSEUZIHLSJYATIODFBQPXTUSLQUEHVXQJENITGNZ.HTA
  • MD5 (RILSXDKOPJHN.TXT) = 3d8ff7f298f64d9150a11e61dcbfd87b
  • MD5 (SSSSSSHSJSJSA.txt) = 9ce8d6f136b95fab140bc8904666003a
  • MD5 (1b976a1fa26c4118d09cd6b1eaeceafccc783008c22da58d6f5b1b3019fa1ba4.vbs) = e04e4cb7e410b885babba54cd59d5ae9
  • MD5 (first_pe.exe) = 83dc22a1493e609b8b16f732e909418f
  • MD5 (second_pe.exe) = 08587e04a2196aa97a0f939812229d2d

Network-basierende Indikatoren:

  • http://15.188.246.78/Q/SSSSSSHSJSJSA.txt
  • http://15.188.246.78/Q/RILSXDKOPJHN.TXT

Serienübersicht

N-W0rm Analyse Teil 2

Beitrag teilen auf:

XING
Twitter
LinkedIn

SECUINFRA Falcon Team • Autor

Digital Forensics & Incident Response Experten

Neben den Tätigkeiten, die im Rahmen von Kundenaufträgen zu verantworten sind, kümmert sich das Falcon Team um den Betrieb, die Weiterentwicklung und die Forschung zu diversen Projekten und Themen im DF/IR Bereich.

> alle Artikel
Cookie Consent mit Real Cookie Banner