Conti Ransomware malware leak WITH LOCKER
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

301 lines
16 KiB

НЕРЕЗИДЕНТНЫЙ ЛОАДЕР, ТРЕБОВАНИЯ
ЦЕЛЬ
Нужен загрузчик не из паблика, ранее неизвестный для АВ.
Максимально приветствуются нестандартные подходы к решению задачи доставки и запуска произвольной нагрузки.
ДОСТАВКА
Приветствуются новые методы доставки и обхода SmartScreen:
1. использование нативных утилит ОС для скачивания нагрузки https://lolbas-project.github.io/
2. использование стегано, нестандартных типов нагрузок (картинки, легит.файлы, упаковка под видом сертификатов, инсталляторы и пр.),
как вариант в комбинации с простейшим загрузчиком нулевой ступени (на скриптах).
Под загрузчиком нулевой ступени имеется в виду ситуация, когда юзера каким-либо образом побуждают скопировать с сайта/ввести вручную и выполнить короткий скрипт.
3. использование нативных утилит ОС для сборки и запуска нагрузки
ТРЕБОВАНИЯ К ЛОАДЕРУ
1. Без закрепления
1.1. Без сохранения состояния на диске, в реестре или где-либо еще
2. Идентификация клиента в общем случае необязательна, для этого достаточно IP-адреса. Однако, если идентификатор клиента генерируется, к нему выставляется требование:
Генерация одного и того же идентификатора на одном и том же компьютере, вне зависимости от текущего пользователя и прочих обстоятельств.
Предлагаемый вариант - hardware id (хэш от суммы оборудования). Формат идентификатора не оговаривается.
2.1. Клиент также идентифицирует принадлежность себя к определенной группе (ботнету). Группа нужна для удобства эксплуатации - чтобы логически отделить одних ботов от других.
Группа прошивается в лоадер в момент сборки и в течение времени жизни конкретного экземпляра лоадера не меняется никогда.
2. Разрядности x86/x64. Приоритетная разрядность x64. Запуск нагрузки только той же разрядности, что сам лоадер.
3. Сбор инфы о системе:
- имя хоста
- имя пользователя
- версия и разрядность ОС
- имя и версия АВ
- результат команды net view /all
- результат команды net view /all /domain
- результат команды nltest /domain_trusts /all_trusts
- IP-адрес получать НЕ ОБЯЗАТЕЛЬНО - это может быть сделано средствами бэкенда
4. Без повышения прав
4.1. Работа от непривилегированного пользователя.
5. Без обхода UAC
6. Возможность выполнения простой программы по запуску нагрузки:
6.1. Повторный запуск процесса при вылетах
6.2. Выдерживание циклов и таймаутов (возможность указать, сколько раз перестартуем, интервалы между попытками перезапуска)
Общий смысл этого пункта: не всегда нагрузка запускается с первого раза; бывает, что нагрузка вылетает из-за ошибок; бывает, что одну нагрузку грохает АВ, а другую нет.
Потому у нас всегда есть планы Б и В.
Следует учесть, что админка может отдавать РАЗНЫЕ нагрузки при последовательных запросах на закачку загрузки.
7. Запуск как .exe, так и .dll
8. Запуск нагрузки бесфайловой техникой (process hollowing, dll from memory и другими подобными)
9. Мимикрия нагрузки под легитимный процесс
10. Использование открытых каналов связи для обмена с C&C (HTTPS, DNS, почта итд)
11. Мимикрия сетевой активности под легитимный процесс (странно видеть сетевые запросы от cmd.exe или WerFault.exe, буде вы решите хоститься в них)
12. Шифрование трафика; простая схема распределения ключей. Цель шифрования - защита от машинного анализа, DPI.
Простая достаточно для реализации и генерации ключей, и сложная достаточно, чтобы нельзя было скачать нагрузку в броузере или прикрутить нужный диссектор в DPI.
13. Защита от машинного анализа (обфускация строк, системных вызовов; разбавление низкой энтропии шумом итд).
Тут речь идет про защиту от анализа как человеком, так и АВ:
13.1. Усложняем работу по раскрытию алгоритмов работы
13.2. Сбиваем с толку эмулятор АВ
13.3. Защита от ханипотов и продвинутых песочниц допустима, только если вы предоставляете доказательства её эффективности.
Как правило тут идет речь о получении характерных для песочниц ID устройств, hostname, виртуальной машины итд.
Однако по отдельности эти факторы могут ничего не значить и давать ложно-позитивные сработки, тем самым просаживая трафик.
14. Наличие билдера необязательно, если вы готовы к постоянному сотрудничеству впоследствии. Но вообще мы хотим исходники.
15. ОС - Windows Server 2008 R2+, Windows Vista+ - не ниже данных версий, включая все современные десктопные и серверные винды.
Если вы сделаете совместимость с Windows Server 2008 (без R2, то есть фактически это XP), это будет очень круто.
16. Компиляция в нативный код, либо (в случае скриптовых языков или .Net) лоадер должен выполняться на голой ОС.
Не должно быть зависимостей. Если они крайне необходимы ради крутой идеи (например, вы решили выполняться в виртуальной машине и для этого поставить VMWare Player), то они зашиты в ЕДИНЫЙ файл.
PowerShell - не выше 2.0.
Допускаются любые связки cscript, jscript, .bat, при условии компоновки в единый файл.
Другими словами, это должен быть один файл, и он должен работать на любых виндах без расчета на то, что у нас тут стоит .Net или Microsoft Visual C++ Redistributable нужной версии.
17. Совместимость с криптами (для нативного кода):
17.1. Сборка самого лоадера как в .exe, так и в .dll
17.2. Умеренный размер (скажем, до 1М)
17.3. Минимизация CRT/STL (не все крипты переваривают).
ПРИЕМОЧНЫЙ ТЕСТ
Приемка производится исходя из отсутствия у разработчика полной интеграции с админкой, для возможности гаранта самостоятельно оценить работу.
Соответственно, разработчик делает демо для гаранта на своих ресурсах (VPS, виртуалках итд).
0. На тест предоставляются 1 (один) файл лоадера и файл(ы) шлюза админки + нужные для него заглушки (см.ниже), которые использованы разработчиком для внутренних тестов.
Если файл компилируется в нативный .exe, дополнительно должна предоставляться .dll - для демонстрации наличия профиля сборки в .dll.
В таком случае .dll запускается через rundll и также тестируется.
Исходники на этом этапе не нужны, может быть какая угодно обфускация/криптование.
Шлюз админки разворачивается на сервере заказчика. Настройка производится совместно заказчиком и разработчиком.
Демо производится также на арендованном заказчиком VPS. Учтите, что слово V в VPS - значит virtual (виртуальная машина).
1. Статика на dyncheck.com должна быть чистой.
2. Не более 4 детектов по поведению на момент приемки на dyncheck.com.
Настройки dyncheck: 240 секунд теста, полный доступ к интернету.
2.1. Отсутствие среди динамических детектов
- Windows Defender
- ESET Nod32
- Avast Home
- Kaspersky Antivirus
- Bitdefender
3. В качестве нагрузки должны проверяться поочередно несколько файлов:
3.1. putty.exe
3.2. notepad.exe
3.3. DbgView.exe https://docs.microsoft.com/en-us/sysinternals/downloads/debugview
Дополнительно заказчик предложит несколько других файлов не из паблика. Это будут простейшие заглушки типа MessageBox("hello, world!"), статически скомпонованные,
без зависимостей. Возможно, с минимальным использованием WinApi (функции GDI). Цель этого - продемонстрировать, что лоадер способен работать с произвольной нагрузкой.
Данные файлы размешаются на веб-сервере заказчика.
4. Тест производится поочередно на двух компьютерах с включенными АВ (Windows Defender, ESET Nod32) и произвольной версией Windows из требований.
Антивирусные базы обновлены, облачная защита выключена, отправка образцов выключена.
Тестируются поочередно все предоставленные нагрузки.
5. Лоадер в виде "как есть" (без упаковки в архив; если это .exe - то значит .exe и качаем) скачивается с файлообменника qaz.im (или другого оговоренного) в броузере Chrome последней на момент версии.
Не должно быть предупреждений о вирусе ни от броузера, ни от антивируса.
6. Лоадер запускается. Если не будет возможности подписать файл лоадера EV-сертификатом для запуска прямо из Chrome, то вопли Chrome о недоверии к файлу игнорируются, файл запускается руками из Проводника.
7. Лоадер должен скачать и запустить нагрузку. Факт скачивания мониторится на веб-сервере.
Нагрузка должна проработать на компьютере минимум час и не быть снесена броузером/АВ.
Тесты поочередно проводятся для каждой представленной нагрузки, с пересборкой лоадера если необходимо.
Мы понимаем, что современные АВ очень умные, последовательными тестами мы только помогаем им обучаться, и на каком-то этапе может появиться детект там где его не было.
И все же, этим мы имитируем реальную работу, а вы демонстрируете живучесть решения.
При необходимости мы можем сменить у VPS адрес и hardware id, чтобы снять ассоциации у АВ с конкретным демо-стендом.
ШЛЮЗ К АДМИНКЕ
Админка уже есть.
Админка предоставляет интерфейс на PHP для подключения к ней.
Объект админки называется $adm и является глобалом.
Сам шлюз должен быть оформлен в виде класса на PHP с определенным набором публичных методов (т.е. проэкспортировать свой интерфейс для админки).
Шлюз идентифицируется в админке по имени.
В случае использования отличных от HTTP протоколов для общения с лоадером, шлюз будет напрямую на нашу HTTP-прокладку, протокол для неё запрашивается и предоставляется отдельно.
Это более сложный случай, мы поможем с такой интеграцией.
В случае протокола поверх HTTP, способ интеграции с админкой описан ниже.
ИНТЕРФЕЙС БЭКЕНДА
1. Регистрация настройки
$adm->register_property($plugin_name, $prop_name, $length) зарегистрировать настройку для данного шлюза в админке
$plugin_name: строка с идентификатором шлюза
$prop_name: строка с идентификатором свойства
$length: максимальная длина поля
TODO: возможно в будущем добавятся также тип поля и параметры отображения в админке (тип виджета).
Настройка хранится в двоичном виде в БД (это значит, что вам не нужно ее как-либо экранировать при сохранении).
Возвращает true в случае успеха, false в случае ошибки.
Свойство появляется в диалоге настройки группы (ботнета) в админке. То есть настройка меняется в разрезе группы.
Например, в своей реализации протокола вы решили использовать разные имена HTTP-заголовков, URI-префиксов и прочих свойств HTTP-запроса, для разных групп.
В таком случае вы регистрируете нужные настройки, в обработчике запроса получаете их значения для той группы, к которой принадлежит клиент.
Дальнейший разбор запроса происходит с учетом этих данных.
Настройками могут быть ключи шифрования, номера портов, какие-либо адреса итд - все что вам понадобится для организации собственного протокола.
2. Получить настройку
$adm->get_property($plugin_name, $prop_name, $group = null) получить свойство (настройку) с указанным именем; опционально указывается группа
$plugin_name: строка с идентификатором шлюза
$prop_name: строка с идентификатором свойства
$group: идентификатор группы (ботнета), опционально. Если не указано, вернется значение настройки по умолчанию без разреза группы.
Возвращает значение настройки.
3. Получить список ботнетов
$adm->get_groups($plugin_name) получить массив со списком групп, доступных для данного плагина
$plugin_name: строка с идентификатором шлюза
Возвращает словарь словарей:
"имя группы" => "словарь" {
"имя настройки1" => "значение настройки1"
...
"имя настройкиN" => "значение настройкиN"
}
3. Получить нагрузку
$adm->get_payload($bitness, $group) получить нагрузку из заданной группы с указанной разрядностью
$bitness: принимает два возможных значения 86 и 64 (int)
$group: идентификатор группы
Возвращает нагрузку, которую следует отдать лоадеру
4. Регистрация отстука
$adm->knock($group, $id = null) регистрация отстука с заданного адреса
$group: идентификатор группы
$id: идентификатор компьютера (опционально)
Ничего не возвращает.
5. Регистрация информации и системе
$adm->put_sysinfo($group, $info, $id = null) информация о компьютере
$group: идентификатор группы
$id: идентификатор компьютера (опционально)
$info: словарь с информацией о системе.
Поля у словаря следующие:
hostname: имя хоста
uname: имя пользователя
os: название ОС
os_bitness: разрядность ОС
os_version: версия ОС
av: имя и версия АВ
net: результат команды net view /all
netdomain: результат команды net view /all /domain
trust: результат команды nltest /domain_trusts /all_trusts
Словарь расширяемый, если хотите передать еще что-нибудь полезное.
Функция ничего не возвращает.
6. Отправить телеметрию
$adm->put_telemetry($group, $data, $id = null) телеметрия с отстука
$group: идентификатор группы
$id: идентификатор компьютера (опционально)
$data: произвольное сообщение от лоадера
Примечание
Смысл телеметрии - удаленная отладка, и сведения о работе лоадера.
Неплохо было бы узнать:
- о том что лоадер скачал нагрузку
- о том что он её запустил
- о произошедших ошибках (например, процесс нагрузки быстро помер)
- о повторных попытках запуска нагрузки
- о других событиях
ОБРАБОТКА ОШИБОК
Если вызывающий контекст обнаруживает какую-либо ошибку при работе через API, и если эта ошибка особо не оговорена, обработка прерывается.
Либо молча (в боевых условиях), либо попытается вам сказать почему (если включен error_reporting).
ИНТЕРФЕЙС ШЛЮЗА
Шлюз - это класс на PHP, без зависимостей в виде фреймворков.
Шлюз будет выполняться в контексте некоего фреймворка, но на это не следует рассчитывать.
Шлюз экспортирует две публичные функции:
1. Инсталляция в систему
$gate->install()
Тут происходит регистрация настроек, нужных шлюзу.
2. Обработка запроса
$gate->process_request($HTTP_request)
Обрабатывает входящий запрос и формирует ответ.
$HTTP_request: входящий запрос со всеми заголовками
Возвращает словарь:
code => HTTP-код ответа (число или строка)
response_headers => HTTP-заголовки сформированного ответа. Если ответ не 200, могут быть пустыми.
response_body => HTTP-тело сформированного ответа. Если ответ не 200, может быть пустыми.
Если ответ 400 - это значит что шлюз не опознал запрос как валидный.
Если ответ 404 - это значит что шлюз в целом опознал запрос как валидный, но не смог сопоставить его с группой.
Если ответ 200 - это значит что ответ полностью обработан, и дальнейшая обработка не требуется.
Любые другие коды ответа трактуются как ошибка обработки; на этом обработка ответа для данного шлюза завершена.
PHP
Версия PHP - не ниже 7.0.
Можно рассчитывать на все распространенные плагины.
Если нужно что-либо кастомное - включим или соберем.
ПРИМЕР РЕАЛИЗАЦИИ ШЛЮЗА (PHP-ПОДОБНЫЙ ПСЕВДОКОД)
require_once "adm_api.php";
// отсюда взяли объект $adm
class sample_gate {
string $plugin_name = "Plagin Vasi";
// функция регистрации плагина в системе
// эта функция экспортируется из класса (публичная)
function install() {
// регаем настройку (поле) с таким-то именем и такой-то длиной
// Например, хотим накрыть нагрузку шифром, дабы лоадер ее расшифровал на том конце
$adm->register_property($plugin_name, "RSA_public_key", 4096);
}
// обработка одного запроса, сюда передается целиком HTTP-запрос
// эта функция экспортируется из класса (публичная)
// в ответ получаем массив с HTTP-кодом, заголовками и телом ответа
function process_request(string $request) {
// хочу от админки список доступных Васе групп, с их префиксами и всей херней
array $groups = $adm->get_groups_list();
// разобрал запрос на части, сделал предварительную валидацию
if(not valid request)
return array("code=>"400"); // bad request; после этого вызывающий контекст может продолжить поиск подходящего плагина для этого запроса
foreach($g => $groups) {
if(request matches this group) {
$adm->knock($REMOTE_ADDR);
if(request is telemetry)
$adm->put_telemetry($g, $message_from_request);
else if(this is sysinfo) {
$info = get_sysinfo_from_request();
$adm->put_sysinfo($g, $info);
}
else if(request for payload) {
$bitness = figure out bitness from the request;
$payload = $adm->get_payload($bitness, $g);
$encryption_key = $adm->get_property($plugin_name, "RSA_public_key");
$HTTP_body = encrypt_payload($payload, $encryption_key);
$HTTP_headers = arrange_headers_somehow();
}
return array("code=>"200", "response_headers" => ...);
}
}
return array("code=>"404");
}
// дальше идут приватные функции класса, о которых админка знать не хочет
function encrypt_payload() {}
function arrange_headers_somehow() {}
//etc
}