
Полиморфный шифратор, который преобразует shellcode, PE и COFF файлы в обфусцированные, позиционно-независимые полезные нагрузки с использованием шифрования RC4 и случайного блочного шифра, а также генерацию мусорных инструкций с помощью библиотеки AsmJit.
Представлено на
Shoggoth — это проект с открытым исходным кодом, основанный на C++ и библиотеке asmjit, используемый для полиморфного шифрования заданного шеллкода, PE и COFF файлов.
Shoggoth генерирует выходной файл, который хранит полезную нагрузку и соответствующий загрузчик в обфусцированной форме. Поскольку содержимое выходного файла является позиционно-независимым, оно может быть выполнено непосредственно как шеллкод. Во время выполнения полезной нагрузки она расшифровывает себя во время выполнения. В дополнение к процедуре шифрования, Shoggoth также добавляет мусорные инструкции, которые ничего не меняют, между процедурами.
Я начал разрабатывать этот проект для изучения различных подходов к динамической генерации инструкций, практики ассемблера и обнаружения сигнатур. Я планирую регулярно обновлять репозиторий новыми знаниями.
Текущие возможности перечислены ниже:
Общая схема выполнения Shoggoth для входного файла показана на изображении ниже. Вы можете наблюдать этот поток с конфигурациями по умолчанию.
В основном Shoggoth сначала объединяет предварительно скомпилированный шеллкод загрузчика в соответствии с выбранным режимом (файл COFF или PE) и входной файл. Затем он добавляет несколько мусорных инструкций, которые генерирует, к этой объединенной полезной нагрузке. Стеб, содержащий загрузчик, мусорные инструкции и полезную нагрузку, шифруется сначала с помощью RC4, а затем с помощью случайно сгенерированного блочного шифрования путем объединения соответствующих дешифраторов. Наконец, он добавляет мусорную инструкцию к результирующему блоку.
При случайной генерации инструкций для мусорных стебов или процедур шифрования Shoggoth использует библиотеку AsmJit.
AsmJit — это легковесная библиотека для генерации машинного кода, написанная на языке C++. Она может генерировать машинный код для архитектур X86, X86_64 и AArch64 и поддерживает базовые инструкции и все последние расширения. AsmJit позволяет задавать коды операций, регистры, непосредственные операнды, метки вызовов и встраивать произвольные значения в любое смещение внутри кода. При генерации некоторых ассемблерных инструкций с помощью AsmJit достаточно вызвать функцию API, которая соответствует требуемой операции ассемблера, с значениями операндов ассемблера из класса Assembler. Для каждого вызова API AsmJit хранит информацию о коде и перемещениях в своей внутренней структуре CodeHolder. После вызова функций API всех команд ассемблера, которые нужно сгенерировать, можно использовать его класс JitRuntime для копирования кода из CodeHolder в память с разрешением на выполнение и его перемещения.
Когда я искал библиотеку для генерации кода, я наткнулся на AsmJit и увидел, что она широко используется многими популярными проектами. Поэтому я решил использовать её для своих нужд. Я не знаю, является ли Shoggoth первым проектом, использующим её в контексте red team, но я считаю, что это может стать ориентиром для будущих реализаций.
Shoggoth можно использовать для шифрования заданных файлов PE и COFF, так что оба они могут быть выполнены как шеллкод благодаря предварительно скомпилированным позиционно-независимым загрузчикам. Я просто использовал метод C в шеллкод для получения PIC-версии известных загрузчиков PE и COFF, которые я модифицировал для своих старых проектов. Для компиляции я использовал Makefile из проекта HandleKatz, который представляет собой дампер LSASS в PIC-форме.
В основном, для получения шеллкода с помощью техники C в шеллкод, я удалил все глобальные переменные в исходном коде загрузчика, поместил все строки в стек и разрешил адреса функций Windows API, загружая и анализируя необходимые DLL во время выполнения. После этого я определил точку входа с помощью скрипта компоновщика и скомпилировал код с помощью MinGW с различными флагами компиляции. Я извлек секцию .text из полученного исполняемого файла и получил шеллкод загрузчика. Поскольку полученный после редактирования кода исполняемый файл не содержит других секций, кроме .text, код в этой секции может использоваться как позиционно-независимый.
Исходный код этих загрузчиков можно просмотреть и отредактировать в каталогах COFFLoader и PELoader. Скомпилированные версии этих исходных кодов можно найти в каталоге stub. На данный момент, если вы хотите отредактировать или изменить эти загрузчики, вы должны соблюдать сигнатуры и заменить предварительно скомпилированные бинарники из каталога stub.
Для передачи аргументов в BOF используйте опцию '--coff-arg'. Shoggoth ожидает предварительно отформатированную hex-строку, содержащую упакованные аргументы, которую можно создать с помощью скрипта TrustedSec's beacon_generate.py. Копия этого скрипта включена как COFFArgGenerator/beacon_generate.py. (Большое спасибо @Octoberfest7)
Shoggoth сначала использует один из потоковых шифров, алгоритм RC4, для шифрования полученной полезной нагрузки. После случайной генерации ключа, используемого здесь, он шифрует полезную нагрузку этим ключом. Стеб-дешифратор, который расшифровывает полезную нагрузку во время выполнения, динамически создается и собирается с помощью AsmJit. Регистры, используемые в стебе, случайным образом выбираются для каждого образца.
Я использовал код Nayuki как ссылку для реализации алгоритма RC4, который я применил в Shoggoth.
После выполнения первого шифрования Shoggoth использует второе шифрование, которое представляет собой случайно сгенерированный блочный шифр. С помощью второго шифрования он шифрует как дешифратор RC4, так и опционально стеб, содержащий полезную нагрузку, мусорные инструкции и загрузчик, зашифрованный с помощью RC4. Он делит шифруемый блок на 8-байтовые блоки и использует случайно сгенерированные инструкции для каждого блока. Эти инструкции включают ADD, SUB, XOR, NOT, NEG, INC, DEC, ROL и ROR. Операнды для этих инструкций также выбираются случайным образом.
Логика генерации мусорных инструкций сильно вдохновлена замечательным проектом SGN от Ege Balci. Shoggoth может выбирать мусорные инструкции на основе перепрыгивания через случайные байты, инструкций без побочных эффектов, поддельных вызовов функций и инструкций, которые имеют побочные эффекты, но сохраняют исходные значения. Все эти инструкции выбираются случайным образом и генерируются вызовом соответствующих API-функций библиотеки AsmJit. Кроме того, для увеличения размера и разнообразия комбинаций эти функции генерации вызываются рекурсивно.
В первой версии Shoggoth есть много мест, куда можно поместить мусорные инструкции. Например, мы можем поместить мусорные инструкции между инструкциями блочного шифра или инструкциями шифра RC4. Однако для демонстрационных целей я оставил это для следующих версий, чтобы избежать дополнительной сложности генерируемых полезных нагрузок.
Я не компилировал основной проект, поэтому вам придется скомпилировать его самостоятельно. Опционально, если вы хотите отредактировать исходный код загрузчика PE или COFF, на вашем компьютере должен быть MinGW для их компиляции с помощью предоставленных Makefile.
______ _ _
/ _____) | _ | |
( (____ | |__ ___ ____ ____ ___ _| |_| |__
\____ \| _ \ / _ \ / _ |/ _ |/ _ (_ _) _ \
_____) ) | | | |_| ( (_| ( (_| | |_| || |_| | | |
(______/|_| |_|\___/ \___ |\___ |\___/ \__)_| |_|
(_____(_____|
by @R0h1rr1m
"Tekeli-li! Tekeli-li!"
Usage of Shoggoth.exe:
-h | --help Показать справочное сообщение.
-v | --verbose Включить более подробный вывод.
-i | --input <Путь к входному файлу> Путь к входному файлу полезной нагрузки для шифрования. (Обязательно)
-o | --output <Путь к выходному файлу> Путь к выходному файлу для зашифрованных данных. (Обязательно)
-s | --seed <Значение> Установить значение зерна для рандомизации.
-m | --mode <Значение режима> Установить режим шифрования полезной нагрузки. Доступные режимы: (Обязательно)
[*] raw - Shoggoth не добавляет стеб загрузчика. (Режим по умолчанию)
[*] pe - Shoggoth добавляет стеб загрузчика PE. Входной файл должен быть корректным x64 PE.
[*] coff - Shoggoth добавляет стеб загрузчика COFF. Входной файл должен быть корректным x64 COFF.
--coff-arg <Аргумент> Установить аргумент для загрузчика COFF. Сгенерируйте эту строку с помощью COFFArgGenerator/beacon_generate.py.
пример: --coff-arg 0a0000000600000068656c6c6f00
Используется только в режиме загрузчика COFF. (Спасибо @Octoberfest7)
-k | --key <Ключ шифрования> Установить первый ключ шифрования вместо случайного.
--dont-do-first-encryption Не выполнять первое (потоковое) шифрование.
--dont-do-second-encryption Не выполнять второе (блочное) шифрование.
--encrypt-only-decryptor Шифровать только стеб-дешифратор во втором шифровании.
"Это была ужасная, неописуемая вещь, больше любого поезда метро — бесформенное скопление протоплазматических пузырей, слабо самосветящееся, с мириадами временных глаз, формирующихся и исчезающих, как пустулы зеленоватого света, по заполняющему туннель фронту, который надвигался на нас, сокрушая обезумевших пингвинов и скользя по блестящему полу, который он и его сородичи так зловеще очистили от всякого мусора." ~ Г. Ф. Лавкрафт, Хребты безумия
Шоггот — это вымышленный монстр в Мифах Ктулху. Эти существа упоминались вскользь в цикле сонетов Г. Ф. Лавкрафта «Грибы с Юггота» (1929–30), а позже подробно описаны в его повести «Хребты безумия» (1931). Они способны формировать любые органы или придатки, необходимые для текущей задачи, хотя их обычное состояние — это извивающаяся масса глаз, ртов и шевелящихся щупалец.
Поскольку эти существа похожи на разумную массу самолепящейся студенистой плоти и не имеют фиксированной формы в описаниях Лавкрафта, я хотел дать это имя инструменту полиморфного шифрования. 🙂
Только для авторизованного тестирования безопасности. Неправомерное использование этого инструмента против систем без явного разрешения является незаконным.