ЦЕЛЬ Новый бот является развитием идеи о легковесности. В предыдущей версии был реализован минимальный набор функций - разные варианты запуска нагрузки, скачивание файла итд. В новой версии даже эти функции будут вынесены из ядра и будут подгружаться по требованию в виде имплантов. Таким образом мы попробуем минимизировать поверхность контакта с АВ. Бот и его протокол является над/под-множеством предыдущих версий, то есть стыкуется с имеющимися и кодовой базой бэкендом бесшовно. Часть команд протокола не используется, часть команд новые. АРХИТЕКТУРА Бот состоит из загрузчика, ядра и имплантов. Загрузчик является опциональным, может быть можно грузить ядро напрямую ввиду его минимализма. Функции ядра: - запрос импланта (команды) - отправка результата команды - отправка телеметрии Функции импланта - все остальное. Формат импланта - либо двоичный позиционно-независимый код, либо .dll (вероятней всего .dll; станет ясно в процессе разработке). Ядро вертится в цикле запроса команд, загружает имплант, загружает параметры и нагрузку к нему, запускает, отправляет результаты. Есть противоречие между устойчивостью бота к сбою и обнаружимостью АВ: - для устойчивости имплант лучше запускать в отдельном процессе; - для необнаружимости лучше запускать имплант в своём процессе. Противоречие снимаем добавлением флага контекста запуска. Запуск в собственном процессе делается с помощью бесфайлового PE-загрузчика .dll - исходный код есть в сети. Второй вариант - https://github.com/DimopoulosElias/SimpleShellcodeInjector/blob/master/SimpleShellcodeInjector.c Для достижения устойчивости к сбою ядро бота должно быть обернуто в SEH/VEH-обработчики исключений. Запускаемые потоки также должны иметь обработку исключений, позволяющую безопасно завершить и отцепить .dll после исключения. Окончательная архитектура определится по результатам работы. ПРОТОКОЛ Общая канва протокола (цикл запрос-ответ, обработка ошибок, формат ответов итд) совпадает с протоколом версии 1. Если не оговорено иначе, нагрузка отправляется в виде тела HTTP GET ответа. Формат команды: %code% %timeout% [%args%] где code - код команды timeout - таймаут ожидания ответа (0 - запуск команды в фоновом режиме и готовность к запросу следующей команды) args - аргументы различаются для разных типов команд 0 %timeout% - нет операции. Время - число секунд, на которое должен заснуть бот до следующего отстука на сервер. 117 %timeout% %payload% - запуск импланта в виде shell-кода. Другие параметры отсутствуют. Shell-код запускается в контексте текущего процесса. Заметим, что отличие от команды 17 только в наличии таймаута. Возможно, эти две команды сольем в одну. Нагрузка в двоичном виде, является позиционно-независимым двоичным кодом, выполняется ботом как есть, без каких-либо конверсий. 111 %timeout% ?caching? %payload% [%URI% [%args]] - запуск импланта в виде .dll. caching == 0 разрешается кешировать данный имплант. FIXME а как бот поймет что это за имплант? нужен ид импланта? == 1 имплант следует немедленно выгрузить после его завершения URI - ссылка на основную нагрузку импланта. Если основная нагрузка для данного импланта не используется, и это не последний аргумент команды, то в качестве значения ставится знак - (минус). Более подробная трактовка аргументов описана в соответствующем разделе. ?114 %timeout% - сброс кеша имплантов. Все закешированные импланты должны быть выгружены. Отправка ответов и телеметрия совпадает с протоколом версии 1. ИНТЕРФЕЙС ЯДРО-ИМПЛАНТ Основной нюанс в передаче параметров импланту и получению ответа от импланта. Для этого и ядро, и имплант предоставляют друг другу интерфейс. Dll должна экспортировать минимум одну функцию со следующим интерфейсом: DWORD WINAPI EntryPoint( TELEMETRY_PROC lpTelemetryProc, LPVOID payload, SIZE_T paylen, LPVOID args, SIZE_T arglen ) TELEMETRY_PROC определена так: VOID WINAPI send_telemetry(CONST LPVOID message, SIZE_T len) и является callback'ом для отправки телеметрии в админку. Если оба аргумента функции send_telemetry являются нулями, это является сигналом от импланта к родителю о необходимости его выгрузки. payload, paylen - нагрузка для импланта. Нагрузка скачивается ботом из %URI% (команда 111) и расшифровывается приватным ключом перед передачей в имплант. FIXME тут вопрос как лучше - упростить бота и дать импланту самостоятельно возиться со своей нагрузкой? или подготовить это для него, раз уж для этого все есть. args, arglen - указатель на буфер и его длину с кастомными аргументами импланта. Имплант самостоятельно парсит и трактует аргументы. Ядро модифицирует буфер перед передачей его импланту: - производит замену подстроки %id% на идентификатор бота - возможны другие макросы Для этого ядро должно позаботиться о безопасности такой подстановки (реаллокациях буфера, при необходимости) АДМИНКА Команды типа "запустить .exe", "запустить скрипт" теперь будут реализованы через импланты. Потому билдер команд должен конфигурироваться - ранее он был захардкожен, теперь пункты меню и доп.поля к ним будут браться из конфигов/конфигуратора. Потому нужен конфигуратор команд, либо в виде формы, либо хотя бы в виде конфига. Команда описывается следующими полями: - имя команды - файл с имплантом - наличие основной нагрузки импланта - тип основной нагрузки импланта: бинарная/текстовая - дополнительный параметр 1 (тип поля) - дополнительный параметр 2 (тип поля) - ... Основная нагрузка импланта - это запускаемый командами выполнения 10-13 файл. Дополнительные параметры - это (в основном) командная строка для команд 10-13.