Donut

Post-Exploitation v1.1 · 23.10.2024 >1 года

Фреймворк генерации позиционно-независимого шеллкода для загрузки .NET-сборок, EXE, DLL и VBS-файлов.

v1.1
23.10.2024 current

Установка
git clone http://github.com/thewover/donut.git
nmake -f Makefile.msvc
показать оригинал переведено ИИ

Issues Contributors Stars Forks License Chat Github All Releases Twitter URL

Alt text Текущая версия: v1.1

Содержание

  1. Введение
  2. Как это работает
  3. Сборка
  4. Использование
  5. Подпроекты
  6. Разработка с Donut
  7. Вопросы и обсуждения
  8. Отказ от ответственности

1. Введение

Donut является позиционно-независимым кодом, который позволяет выполнять в памяти VBScript, JScript, EXE, DLL-файлы и сборки .NET. Модуль, созданный с помощью Donut, может быть либо развернут с HTTP-сервера, либо непосредственно внедрён в загрузчик. Модуль может быть опционально зашифрован с использованием блочного шифра Chaskey и случайно сгенерированного 128-битного ключа. После загрузки и выполнения файла в памяти оригинальная ссылка стирается, чтобы помешать работу сканеров памяти. Генератор и загрузчик поддерживают следующие возможности:

  • Сжатие входных файлов с использованием aPLib и LZNT1, Xpress, Xpress Huffman через RtlCompressBuffer.
  • Использование энтропии для хешей API и генерации строк.
  • 128-битное симметричное шифрование файлов.
  • Перезапись собственных заголовков PE.
  • Хранение собственных PE в памяти типа MEM_IMAGE.
  • Патчинг интерфейса Antimalware Scan Interface (AMSI) и политики блокировки Windows (WLDP).
  • Патчинг трассировки событий для Windows (ETW).
  • Патчинг командной строки для EXE-файлов.
  • Патчинг API, связанных с выходом, чтобы предотвратить завершение процесса-хоста.
  • Множественные форматы вывода: C, Ruby, Python, PowerShell, Base64, C#, шестнадцатеричный и строка UUID.

Существуют динамические и статические библиотеки для Linux и Windows, которые можно интегрировать в ваши собственные проекты. Также существует модуль Python, подробнее о котором можно прочитать в Сборка и использование расширения Python.

2. Как это работает

Donut содержит индивидуальные загрузчики для каждого поддерживаемого типа файла. Для сборок EXE/DLL .NET Donut использует неуправляемый API размещения CLR для загрузки среды выполнения общего языка. После загрузки CLR в процесс-хост создаётся новый домен приложений, позволяющий выполнять сборки в временных доменах приложений. Когда домен приложений готов, сборка .NET загружается с помощью метода AppDomain.Load_3. Наконец, точка входа для EXE или публичный метод для DLL, указанный пользователем, вызывается с любыми дополнительными параметрами. Обратитесь к MSDN за документацией по Неуправляемый API размещения CLR. Для автономного примера узла CLR см. код здесь.

Файлы VBScript и JScript выполняются с использованием интерфейса IActiveScript. Также имеется минимальная поддержка некоторых методов, предоставляемых Windows Script Host (wscript/cscript). Для автономного примера см. код здесь. Для более подробного описания см.: Выполнение JavaScript, VBScript, JScript и XSL в памяти

Неуправляемые или нативные EXE/DLL файлы выполняются с помощью собственного загрузчика PE с поддержкой отложенного импорта, TLS и патчинга командной строки. Поддерживаются только файлы с информацией о перемещениях. Подробнее читайте в Выполнение DLL в памяти.

Загрузчик может отключать AMSI и WLDP, чтобы помочь обойти обнаружение вредоносных файлов, выполняемых в памяти. Для получения дополнительной информации читайте: Как команды Red Team обходят AMSI и WLDP для динамического кода .NET. Он также поддерживает распаковку файлов в памяти с использованием aPLib или API RtlDecompressBuffer. Подробнее о сжатии данных читайте в Сжатие данных.

Начиная с версии v1.0, ETW также обходится. Как и в случае с AMSI/WLDP, это модульная система, позволяющая заменить стандартный обход на собственный. Стандартный обход основан на исследованиях XPN. Читать Скрытие вашего .NET - ETW для получения дополнительной информации.

По умолчанию загрузчик перезаписывает заголовки PE неуправляемых PE (от базового адреса до IMAGE_OPTIONAL_HEADER.SizeOfHeaders). Если не используется decoy-модуль (перегрузка модуля), то заголовки PE обнуляются. Если используется decoy-модуль, заголовки PE этого decoy-модуля используются для перезаписи заголовков PE полезного модуля. Это делается для препятствования обнаружению путем сравнения заголовков PE модулей в памяти с файлом, поддерживающим их на диске. Пользователь может запросить сохранение всех заголовков PE в их исходном состоянии. Это полезно в сценариях, когда полезный модуль должен получить доступ к своим заголовкам PE, например, при поиске встроенных ресурсов PE.

Для подробного пошагового руководства по использованию генератора и того, как Donut влияет на торговые приемы, прочтите Donut - внедрение .NET-сборок в виде шеллкода. Для получения дополнительной информации о загрузчике прочтите Загрузка .NET-сборок из памяти.

Те, кто хочет узнать больше о внутренностях, должны обратиться к Заметкам разработчика.

3. Сборка

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

Клонирование

Из командной строки Windows или терминала Linux выполните клонирование репозитория.

 
  git clone http://github.com/thewover/donut.git

Следующий шаг зависит от вашей операционной системы и выбранного компилятора. В настоящее время генератор и шаблон загрузчика для Donut можно успешно скомпилировать как с помощью Microsoft Visual Studio 2019, так и с MingGW-64. Чтобы использовать библиотеки в собственном проекте на C/C++, пожалуйста, обратитесь к примерам, предоставленным здесь.

Windows

Для генерации шаблона загрузчика, динамической библиотеки donut.dll, статической библиотеки donut.lib и генератора donut.exe запустите x64-командную строку разработчика Microsoft Visual Studio, перейдите в каталог, где вы клонировали репозиторий Donut, и выполните следующее:

  nmake -f Makefile.msvc

Для выполнения той же операции, но с использованием MinGW-64 в Windows или Linux, перейдите в каталог, где вы клонировали репозиторий Donut, и выполните следующее:

  make -f Makefile.mingw

Linux

Для генерации динамической библиотеки donut.so, статической библиотеки donut.a и генератора donut перейдите в каталог, где вы клонировали репозиторий Donut, и просто выполните make.

Python-модуль

Donut можно установить и использовать как Python-модуль. Для установки из исходников требуется pip для Python3. Сначала убедитесь, что более старые версии donut-shellcode не установлены, выполнив следующую команду в терминале Linux или командной строке Microsoft Visual Studio.

  pip3 uninstall donut-shellcode

После подтверждения, что более старые версии больше не установлены, выполните следующую команду.

  pip3 install .

Вы также можете установить Donut как Python-модуль, получив его из репозитория PyPi.

  pip3 install donut-shellcode

Для получения дополнительной информации обратитесь к Сборке и использованию расширения Python.

Docker

Сборка контейнера Docker.

  docker build -t donut .

Запуск Donut.

  docker run -it --rm -v "${PWD}:/workdir" donut -h

Инструменты поддержки


Donut включает несколько других исполняемых файлов, которые могут быть собраны отдельно. В их число входят «hash.exe», «encrypt.exe», «inject.exe» и «inject_local.exe». Первые два используются при генерации шеллкода. Последние два предоставлены для помощи в тестировании шеллкода Donut. «inject.exe» внедряет исполняемый двоичный файл (loader.bin) в процесс по его PID или имени процесса. «inject_local.exe» внедряет исполняемый двоичный файл в собственный процесс.

Для отдельной сборки этих вспомогательных исполняемых файлов можно воспользоваться makefile MSVC. Например, чтобы собрать «inject_local.exe» для тестирования вашего шеллкода Donut, выполните.

  nmake inject_local -f Makefile.msvc

Релизы

Для каждой версии релиза Donut предоставлены теги, содержащие скомпилированные исполняемые файлы.

В настоящее время доступны два других генератора.

4. Использование

В следующей таблице перечислены переключатели, поддерживаемые командной строкой версии генератора.

Переключатель Аргумент Описание
-a arch Целевая архитектура загрузчика : 1=x86, 2=amd64, 3=x86+amd64(по умолчанию).
-b level Поведение при обходе AMSI/WLDP : 1=Нет, 2=Прерывать при сбое, 3=Продолжать при сбое.(по умолчанию)
-k headers Сохранять заголовки PE. 1=Перезаписать (по умолчанию), 2=Оставить все
-j decoy Необязательный путь к модулю-приманке для перегрузки модулей.
-c class Необязательное имя класса. (требуется для DLL .NET) Также можно указать пространство имён: например namespace.class
-d name Имя домена приложения для создания в .NET. Если включена энтропия, будет сгенерировано случайным образом.
-e level Уровень энтропии. 1=Нет, 2=Генерировать случайные имена, 3=Генерировать случайные имена + использовать симметричное шифрование (по умолчанию)
-f format Формат вывода загрузчика, сохраняемого в файл. 1=Двоичный (по умолчанию), 2=Base64, 3=C, 4=Ruby, 5=Python, 6=PowerShell, 7=C#, 8=Шестнадцатеричный
-m name Необязательный метод или функция для DLL. (для DLL .NET требуется метод)
-n name Имя модуля для HTTP-промежуточного хранения. Если включена энтропия, оно будет сгенерировано случайным образом.
-o path Указывает, где Donut должен сохранить загрузчик. По умолчанию — «loader.bin» в текущем каталоге.
-p parameters Необязательные параметры/командная строка внутри кавычек для метода/функции DLL или EXE.
-r version Версия среды выполнения CLR. По умолчанию используется MetaHeader, либо v4.0.30319, если он недоступен.
-s server URL HTTP-сервера, который будет размещать модуль Donut. Учетные данные могут быть указаны в следующем формате:
https://username:password@192.168.0.1/
-t Запустить точку входа неизменяемого/нативного EXE в виде потока и дождаться его завершения.
-w Командная строка передаётся в функцию неуправляемой DLL в формате UNICODE. (по умолчанию используется ANSI)
-x option Определяет, как загрузчик должен завершать работу. 1=выход из потока (по умолчанию), 2=выход из процесса, 3=Не завершать и не очищать, блокировать бесконечно
-y addr Создаёт новый поток для загрузчика и продолжает выполнение по адресу, который представляет собой смещение относительно исполняемого файла хост-процесса. Предоставленное значение является смещением. Эта опция поддерживает загрузчики, которым необходимо возобновить выполнение хост-процесса после завершения работы donut.
-z engine Упаковать/Сжать входной файл. 1=Без сжатия, 2=aPLib, 3=LZNT1, 4=Xpress, 5=Xpress Huffman. В настоящее время последние три поддерживаются только в Windows.

Payload Requirements

Есть некоторые конкретные требования, которые должна выполнять ваша полезная нагрузка, чтобы Donut успешно загрузил её.

.NET Assemblies

  • Метод точки входа должен принимать только строки в качестве аргументов, либо не принимать аргументов.
  • Метод точки входа должен быть помечен как public и static.
  • Класс, содержащий метод точки входа, должен быть помечен как public.
  • Сборка НЕ ДОЛЖНА быть смешанной (содержащей как управляемый, так и нативный код).
  • Таким образом, сборка НЕ ДОЛЖНА содержать никаких неуправляемых экспортов.

Native EXE/DLL

  • Бинарники, собранные с Cygwin, не поддерживаются.
Исполняемые файлы Cygwin используют инициализационные процедуры, которые ожидают, что хост-процесс будет запущен с диска. Если выполнять из памяти, хост-процесс, скорее всего, упадёт.

Unmanaged DLLs

  • Указанный пользователем метод точки входа должен принимать только одну строку в качестве аргумента, либо не принимать аргументов. Мы предоставили пример.

5. Subprojects

С donut поставляются четыре сопутствующих проекта:

Tool Description
DemoCreateProcess Пример .NET сборки для использования в тестировании. Принимает два параметра командной строки, каждый из которых указывает программу для выполнения.
DonutTest Простой инжектор шеллкода на C# для тестирования donut. Шеллкод должен быть закодирован в base64 и вставлен как строка.
ModuleMonitor Инструмент proof-of-concept, который обнаруживает внедрение CLR, выполняемое такими инструментами, как Donut и Cobalt Strike's execute-assembly.
ProcessManager Инструмент обнаружения процессов, который атакующие операторы могут использовать для определения, во что внедрять, а защитные операторы могут использовать для определения того, что запущено, какие свойства имеют эти процессы и загружен ли в них CLR.

6. Developing with Donut

Вы можете захотеть добавить поддержку большего числа типов полезных нагрузок, изменить наш набор функций или интегрировать Donut в ваш существующий набор инструментов. Мы предоставили документацию для разработчиков. Дополнительные функции оставлены в качестве упражнения для читателя. Наши предложения:

  • Добавить привязку к окружению.
  • Сделать Donut полиморфным, обфусцируя загрузчик каждый раз при генерации шеллкода.
  • Интегрировать Donut как модуль в ваш любимый фреймворк RAT/C2.

7. Questions and Discussion

Если у вас есть любые вопросы или комментарии по Donut. Присоединяйтесь к каналу #Donut в BloodHound Gang Slack

8. Disclaimer

Мы не несем ответственности за любое злоупотребление этим программным обеспечением или техникой. Donut предоставляется как демонстрация внедрения CLR и загрузки в памяти через шеллкод, чтобы предоставить красным командам способ эмулировать противников, а защитникам — основу для построения аналитики и мер противодействия. Это неизбежно создает риск злоупотребления им авторами вредоносного ПО и злоумышленниками. Однако мы считаем, что чистая выгода перевешивает риск. Надеемся, что это верно. В случае, если продукты EDR или AV способны обнаружить Donut по сигнатурам или поведенческим паттернам, мы не будем обновлять Donut для противодействия сигнатурам или методам обнаружения. Чтобы не обидеться, пожалуйста, не спрашивайте.

Войдите, чтобы оставить комментарий