
Имплант скрытого канала DNS для Red Teams.
WEASEL — это небольшой имплант, работающий в памяти, на Python 3 без зависимостей. Клиент-маяк отправляет небольшой объём идентифицирующей информации о своём хосте на DNS-зону, которую вы контролируете. Сервер WEASEL может давать клиентам команды на выполнение предварительно подготовленных или произвольных команд.
WEASEL — это нагрузка первого этапа, предназначенная для того, чтобы её было трудно обнаружить, и полезная для восстановления доступа, когда ваши шумные полнофункциональные этапы перехвачены.
Статус
Инструкции по использованию см. в README клиента и README сервера.
Для запуска сервера или клиента выполняйте скрипты напрямую или передавайте их интерпретатору Python.
Убедитесь, что для каждого C2-домена установлена NS-запись с IP-адресом хоста, на котором выполняется server.py.
WEASEL требует Python версии 3.6+.
Клиент является самодостаточным и использует только стандартные библиотеки, поэтому может работать на macOS, Linux и т.д.
У сервера есть несколько зависимостей из pip, включённых в requirements.txt сервера. Сервер должен запускаться на Linux, но нет никаких препятствий для работы на macOS или других *nix.
В этом случае нет необходимости обфусцировать и минимизировать маяк. Операторы print сохраняются. Как и в разделе «Использование» выше, убедитесь, что NS-записи для домена(ов) в servers в beacon.py указывают на IP-адрес server.py.
На хосте сервера:
sudo python3 server.py
На хосте жертвы (может быть тем же, что и сервер):
python3 beacon.py
Вам не нужно понимать всё это, чтобы использовать WEASEL.
Маяк общается по DNS с помощью AAAA-запросов и ответов. Он не использует TXT-записи, так как известно, что они используются DNS-вредоносным ПО и туннелями. Синие команды часто имеют детекции DNS-туннелирования, которые срабатывают на большие TXT-запросы.
Клиентская сторона не требует прав root, не использует raw-сокеты и не создаёт некорректные DNS-пакеты. Она использует обычные системные и языковые интерфейсы для выполнения DNS-запросов. Информация кодируется и шифруется в самих записях.
Этот маяк предназначен для работы в медленном и тихом режиме, с малой пропускной способностью. Он должен сообщать нам, на каких хостах он находится, и давать возможность запускать дальнейшие этапы по мере необходимости, и не более. Хотя он поддерживает выполнение произвольных команд, он не предназначен для использования в качестве обычного интерактивного шелла или канала связи.
WEASEL — это первый этап, который вы оставляете работающим, обеспечивая постоянный доступ, когда ваши полнофункциональные (и, следовательно, более шумные) этапы перехватываются.
WEASEL изначально был нацелен на серверы с высоким временем безотказной работы, где у нас был надёжный вектор доступа/эксплуатации. Обход криминалистики был приоритетом. В результате он не имеет собственных механизмов постоянства.
Вы можете сделать его постоянным, добавив его выполнение в вашу любимую технику обеспечения постоянства — это оставлено в качестве упражнения для читателя :)
Запрос (от клиента) — это одиночный AAAA-запрос для имени, отформатированного как:
<preamble><data>.<stream>.<session>.domain.tld
Преамбула занимает 2 байта. Преймбул[0] — порядковый номер этого пакета. Преймбул[1] — общее количество пакетов в этом потоке.
Данные ограничены 50 байтами (настраивается) и содержат полезную нагрузку. Полезная нагрузка кодируется в base32 с использованием пользовательского алфавита.
Сначала все символы 'w' заменяются на '-'.
Затем символ заполнения заменяется с '=' на 'w' для соответствия набору символов DNS: [a-z0-9] и [-].
Мы не заменяем '=' на '-' напрямую, потому что заполнение всегда будет в конце строки, а завершение имени хоста на '---' подозрительно и противоречит DNS RFC. Таким образом, когда строка имеет заполнение, она будет заканчиваться на 'www', что менее подозрительно и соответствует RFC.
Ответ (от сервера) состоит из одного или нескольких AAAA-ответов.
Каждый AAAA-ответ представляет собой 16-байтовую зашифрованную полезную нагрузку, представленную как IPv6-адрес с помощью socket.inet_ntop. Ответы в DNS-ответе не сохраняют свой порядок при передаче, поэтому они упорядочиваются и собираются заново, как и запросы клиента.
Транспортная полезная нагрузка — это строка элементов данных, разделённых символом ^.
Запросы и ответы следуют этому формату:
<type>|<data>
| Тип | Значение (отправитель) | Также известен как | Данные |
|---|---|---|---|
| 0 | Подтверждение | ACK | Случайный hex |
| 1 | Проверка связи (клиент) | PING | Случайный hex |
| 2 | Завершить себя (сервер), завершаю себя (клиент) | FIN | |
| 3 | Инициализационное сообщение (клиент) | SYN | version|hostname|kernel |
| 4 | Переподключение (сервер) | RST | |
| 5 | Установить интервал обратного вызова (сервер) | секунды | |
| 6 | Получить данные о сетевом интерфейсе | eth0 1.2.3.4/24\neth1 fe80:::/64\n... | |
| 8 | Выполнить произвольный код Python3 размером до 666 байт (сервер), вернуть первые 400 байт вывода (клиент) | EVAL | скрипт python3 в одну строку |
| 9 | Выполнить произвольную команду размером до 666 байт (сервер), вернуть первые 400 байт вывода (клиент) | EXEC | bash-команда |
Сессии долгоживущие: клиент инициирует сессию при первом запуске маяка, и эта сессия должна длиться всё время работы маяка на этом клиенте. Обратите внимание, что поскольку маяк работает в памяти и не является постоянным, данные сессии хранятся в памяти этого процесса Python. Любой новый запуск маяка инициирует новую сессию.
Инициирование сессии включает создание клиентом сообщения с уникально идентифицирующей преамбулой, не содержащей данных (чтобы сигнализировать серверу, что это новая сессия): конкатенация 32-байтового открытого ключа Диффи-Хеллмана и 16-байтового случайного AES IV.