ESET-Forscher haben einen bisher unbekannten Loader für Windows Binärdateien entdeckt. Im Gegensatz zu anderen, läuft dieser als Server und führt empfangene Module im Speicher aus. Wir haben diese neue Malware nach ihrer Dynamic Link Library Wslink benannt.

In den letzten zwei Jahren haben wir nur wenige solcher Treffer in unserer Telemetrie gesehen, überwiegend in Mitteleuropa, Nordamerika und im Nahen Osten. Der ursprüngliche Angriffsvektor ist uns nicht bekannt; die meisten Beispiele sind mit MPRESS gepackt und einige Teile des Codes sind virtualisiert. Leider ist es uns bisher nicht gelungen, eines der Module in die Hände zu bekommen, die der Loader erhalten soll. Es gibt keine Ähnlichkeiten im Code, in der Funktionsweise oder der Verwendung, die darauf hindeuten, dass es sich hier möglicherweise um ein Tool von bekannten Schadcode-Autoren handeln könnte.

In den folgenden Abschnitten finden Sie eine Analyse des Loaders, gefolgt von unserer eigenen Client-Implementierung. Diese haben wir eigens dafür entwickelt, um mit unterschiedlichen Erkennungsmethoden zu experimentieren. Wir glauben, dass der Quellcode dieses Clients besonders für Einsteiger im Bereich der Malware-Analyse interessant ist. Denn er zeigt, wie man bestehende Funktionen von bereits analysierter Malware wiederverwenden und mit ihr interagieren kann. Außerdem könnte unsere Untersuchung als Informationsquelle für Blue Teams dienen, die sich mit dieser Bedrohung auseinandersetzen wollen.

Technical analysis

Wslink wird als Dienst ausgeführt und überwacht alle Netzwerkschnittstellen an dem Port, der im Registry-Wert ServicePort des Parameters-Schlüssels des Dienstes angegeben ist. Die Komponente, die den Wslink-Dienst zuvor registriert, ist nicht bekannt. Abbildung 1 zeigt den Code, der einhergehende Verbindungen zu diesem Port akzeptiert.

Abbildung 1. Hex-Rays Dekompilierung der Schleife, die eingehende Verbindungen annimmt

Nach der Annahme einer Verbindung erfolgt ein RSA-Handshake mit einem festcodierten öffentlichen 2048-Bit-Schlüssel, um sowohl den Schlüssel als auch die IV sicher auszutauschen, die für 256-Bit-AES im CBC-Modus verwendet werden (siehe Abbildung 2). Anschließend wird das verschlüsselte Modul mit einer eindeutigen Kennung – Signatur - und einem zusätzlichen Schlüssel zur Entschlüsselung empfangen.

Besonders interessant ist, dass das zuletzt empfangene verschlüsselte Modul mit seiner Signatur global gespeichert wird und damit allen Clients zur Verfügung steht. Auf diese Weise kann man Datenverkehr einsparen, nämlich nur den Schlüssel zu übertragen, wenn die Signatur des Moduls, das geladen wird, mit der vorherigen übereinstimmt.

Abbildung 2. Hex-Rays Dekompilierung des Empfangs des Moduls und seiner Signatur

Wie in Abbildung 3 zu sehen ist, wird das entschlüsselte Modul, bei dem es sich um eine normale PE-Datei handelt, mit Hilfe der MemoryModule-Bibliothek in den Speicher geladen und  schließlich der erste Export ausgeführt. Die Funktionen für Kommunikation, Socket, Schlüssel und IV werden in einem Parameter dem Export übergeben, so dass das Modul über die bereits bestehende Verbindung Nachrichten austauschen kann.

Abbildung 3. Hex-Rays Dekompilierung von Code, der das empfangene Modul im Speicher ausführt

Implementierung des Clients

Unsere eigene Implementierung eines Wslink-Clients, wie unten beschrieben, baut einfach eine Verbindung mit einem modifizierten Wslink-Server auf und sendet ein Modul, das dann entschlüsselt und ausgeführt wird. Da unser Client den privaten Schlüssel, der mit dem öffentlichen Schlüssel in einer bestimmten Wslink-Serverinstanz übereinstimmt, nicht kennen kann, haben wir unser eigenes Schlüsselpaar erstellt. Daraufhin haben wir die ausführbare Datei des Servers mit dem öffentlichen Schlüssel aus diesem Paar modifiziert und den privaten Schlüssel in unserer Wslink-Client-Implementierung verwendet.

Dieser Client ermöglichte uns, die Kommunikation von Wslink zu reproduzieren und nach einzigartigen Mustern suchen. Dies bestätigte unsere Ergebnisse zusätzlich, weil wir sein Verhalten nachahmen konnten.

Einige Funktionen zum Senden/Empfangen von Nachrichten haben wir aus dem Originalmuster übernommen (siehe Abbildung 4) - wir können sie sofort nutzen und müssen sie später nicht neu implementieren.

Abbildung 4. Der Code zum Laden von Funktionen aus einem Wslink-Beispiel

Anschließend liest unser Client den verwendenden privaten RSA-Schlüssel aus einer Datei und baut eine Verbindung zur angegebenen IP und zum Port auf. Es ist davon auszugehen, dass eine Instanz von Wslink bereits auf der angegebenen Adresse und dem Port lauscht. Natürlich muss auch der darin enthaltene öffentliche Schlüssel durch einen ersetzt werden, dessen privater Schlüssel bekannt ist.

Daraufhin führen unser Client und der Wslink-Server den Handshake aus, der den Schlüssel und IV für die AES-Verschlüsselung austauscht. Dieser Austausch besteht aus drei Schritten, wie in Abbildung 5 zu sehen ist: Senden eines Client-Hallo, Empfangen des symmetrischen Schlüssels mit IV und Zurücksenden, um die erfolgreiche Entschlüsselung zu überprüfen.

Aus der Umkehrung der Wslink-Binärdatei haben wir gelernt, dass die einzige Einschränkung der Hallo-Nachricht, abgesehen von der Größe von 240 Bytes, darin besteht, dass das zweite Byte eine Null sein muss, also setzen wir es einfach auf Null.

Abbildung 5. Der Code unseres Kunden für den RSA-Handshake

Der letzte Teil ist das Senden des Moduls. Wie man in Abbildung 6 sehen kann, besteht es nur aus ein paar einfachen Schritten:

  • Empfang der Signatur des zuvor geladenen Moduls - wir haben beschlossen, in unserer Implementierung nichts damit zu machen, da es für uns nicht wichtig war
  • Senden einer hartcodierten Signatur des Moduls
  • Lesen des Moduls aus einer Datei, verschlüsseln (siehe Abbildung 7) und
  • Senden des Verschlüsselungsschlüssels des Moduls

Abbildung 6. Der Code unseres Clients zum Senden des Moduls

Abbildung 7. Der Code unseres Clients zum Laden und Verschlüsseln des Moduls

Der vollständige Quellcode für unseren Client ist in unserem WslinkClient-GitHub-Repository  verfügbar. Ein Hinweis vorneweg: Um für kriminelle Zwecke eingesetzt zu werden, müsste noch ein beträchtlicher Arbeitsaufwand in den Code gesteckt werden – da wäre es viel einfacher, einen anderen Loader von Grund auf neu zu erstellen.

Fazit

Wslink ist ein einfacher, aber bemerkenswerter Loader, der im Gegensatz zu denen, die wir normalerweise sehen, als Server läuft und empfangene Module im Speicher ausführt.

Interessanterweise verwenden die Module die Funktionen des Loaders für die Kommunikation, Schlüssel und Sockets wieder, so dass sie keine neuen ausgehenden Verbindungen initiieren müssen. Wslink verfügt darüber hinaus über ein gut entwickeltes kryptographisches Protokoll zum Schutz der ausgetauschten Daten.

IoCs

Samples

SHA-1 ESET detection name
01257C3669179F754489F92947FBE0B57AEAE573 Win64/TrojanDownloader.Wslink
E6F36C66729A151F4F60F54012F242736BA24862 #rowspan#
39C4DE564352D7B6390BFD50B28AA9461C93FB32 #rowspan#

MITRE ATT&CK techniques

This table was built using version 9 of the ATT&CK framework.

Tactic ID Name Description
Enterprise T1587.001 Develop Capabilities: Malware Wslink is a custom PE loader.
Execution T1129 Shared Modules Wslink loads and executes DLLs in memory.
T1569.002 System Services: Service Execution Wslink runs as a service.
Obfuscated Files or Information T1027.002 Obfuscated Files or Information: Software Packing Wslink is packed with MPRESS and its code might be virtualized.
Command and Control T1573.001 Encrypted Channel: Symmetric Cryptography Wslink encrypts traffic with AES.
T1573.002 Encrypted Channel: Asymmetric Cryptography Wslink exchanges a symmetric key with RSA.