
Freeze — это набор инструментов для создания payload'ов, предназначенный для обхода EDR с помощью приостановленных процессов, прямых системных вызовов и альтернативных методов выполнения.
Чтобы просмотреть последнюю версию Freeze или отправить вопрос, обратитесь по адресу https://github.com/Tylous/Freeze.
Если вы хотите узнать больше о техниках, используемых в этом фреймворке, ознакомьтесь с блогом SourceZero Blog
Freeze — это инструмент для создания полезной нагрузки, используемый для обхода средств защиты EDR и выполнения шелл-кода скрытным образом. Freeze использует несколько техник не только для удаления хуков EDR на уровне пользователя, но и для выполнения шелл-кода таким образом, чтобы обходить другие средства мониторинга конечных точек.
При создании процесса первой загружается библиотека Ntdll.dll. Это происходит до загрузки любых DLL EDR. Это означает, что существует небольшая задержка перед тем, как EDR сможет загрузиться и начать установку хуков и модификацию сборки системных DLL. Если посмотреть на системные вызовы Windows в Ntdll.dll, можно увидеть, что ещё ничего не перехвачено. Если создать процесс в приостановленном состоянии (замороженном во времени), можно увидеть, что загружена только Ntdll.dll, а другие DLL отсутствуют. Также видно, что DLL EDR не загружены, следовательно, системные вызовы в Ntdll.dll не модифицированы.
Чтобы использовать этот чистый приостановленный процесс для удаления хуков из загрузчика Freeze, нам нужен способ программно находить и читать память чистого приостановленного процесса. Здесь в игру вступает рандомизация адресного пространства (ASLR). ASLR — это механизм безопасности для предотвращения уязвимостей, связанных с повреждением памяти стека. ASLR рандомизирует адресное пространство внутри процесса, чтобы гарантировать уникальность всех объектов, отображаемых в память, стека, кучи и самой исполняемой программы. И вот здесь становится интересно: хотя ASLR работает, он не работает для позиционно-независимого кода, такого как DLL. Для DLL (особенно известных системных DLL) адресное пространство рандомизируется один раз при загрузке системы. Это означает, что нам не нужно перечислять информацию удалённого процесса для поиска базового адреса его ntdll.dll, потому что он одинаков во всех процессах, включая тот, который мы контролируем. Поскольку адрес каждой DLL одинаков для каждой загрузки, мы можем получить эту информацию из собственного процесса и никогда не перечислять приостановленный процесс для поиска адреса.
Имея эту информацию, мы можем использовать API ReadProcessMemory для чтения памяти процесса. Этот вызов API обычно ассоциируется с чтением LSASS в рамках атак на учётные данные; однако сам по себе он не является вредоносным, особенно если мы просто читаем произвольный участок памяти. Единственный случай, когда ReadProcessMemory будет помечен как подозрительный, — это чтение того, что читать не следует (например, содержимого LSASS). Продукты EDR никогда не должны помечать сам факт вызова ReadProcessMemory, так как эта функция имеет легитимные операционные применения, и это привело бы к множеству ложных срабатываний.
Мы можем пойти ещё дальше, читая только ту часть Ntdll.dll, где хранятся все системные вызовы, — её .text-секцию, а не всю DLL целиком.
Объединив эти элементы, мы можем программно получить копию .text-секции Ntdll.dll, чтобы перезаписать нашу существующую перехваченную .text-секцию перед выполнением шелл-кода.
ETW использует встроенные системные вызовы для генерации этой телеметрии. Поскольку ETW также является встроенной функцией Windows, продуктам безопасности не нужно «перехватывать» системные вызовы ETW для доступа к информации. В результате для предотвращения ETW Freeze патчит многочисленные системные вызовы ETW, очищая регистры и возвращая поток выполнения к следующей инструкции. Патчинг ETW теперь включён по умолчанию во всех загрузчиках.
Поскольку восстанавливается только Ntdll.dll, все последующие вызовы для выполнения шелл-кода должны находиться в Ntdll.dll. Используя Go (обратите внимание: это можно сделать и на других языках, но в Go это довольно легко реализовать), мы можем определить и вызвать системные вызовы NT, необходимые для выделения, записи и защиты шелл-кода, эффективно пропуская стандартные вызовы, расположенные в kernel32.dll и Kernelbase.dll, так как они всё ещё могут быть перехвачены.
Freeze разработан на Golang.
Чтобы установить Freeze, выполните следующие команды или используйте скомпилированный бинарный файл:
go build Freeze.go
___________
\_ _____/______ ____ ____ ________ ____
| __) \_ __ \_/ __ \_/ __ \\___ // __ \
| \ | | \/\ ___/\ ___/ / /\ ___/
\___ / |__| \___ >\___ >_____ \\___ >
\/ \/ \/ \/ \/
(@Tyl0us)
Soon they will learn that revenge is a dish... best served COLD...
Использование ./Freeze:
-I string
Путь к сырому 64-битному шелл-коду.
-O string
Имя выходного файла (например, loader.exe или loader.dll). В зависимости от расширения файла Freeze определит, создавать DLL или EXE.
-console
Только для бинарных полезных нагрузок — выводит подробную консольную информацию при выполнении полезной нагрузки. Это отключает функцию скрытого окна.
-encrypt
Шифрует шелл-код с помощью AES 256.
-export string
Только для загрузчиков DLL — указывает конкретное имя экспортируемой функции для загрузчика.
-process string
Имя запускаемого процесса. Этот процесс должен существовать в C:\Windows\System32\. Пример 'notepad.exe' (по умолчанию "notepad.exe")
-sandbox
Включает обход песочницы путём проверки:
Присоединена ли конечная точка к домену?
Имеет ли конечная точка более 2 процессоров?
Имеет ли конечная точка более 4 ГБ ОЗУ?
-sha256
Выводит значение SHA256 загрузчиков (полезно для отслеживания).
Freeze может генерировать как .exe, так и .dll файлы. Чтобы указать это, убедитесь, что параметр командной строки -O заканчивается на .exe для бинарных файлов или .dll для DLL. Другие типы файлов в настоящее время не поддерживаются. В случае DLL-файлов Freeze также может добавить дополнительную экспортную функциональность. Для этого используйте -export с указанием конкретного имени экспортируемой функции.
Freeze использует технику, при которой сначала создаётся процесс, а затем он перемещается в фоновый режим. Это даёт два преимущества: во-первых, помогает скрыть процесс, а во-вторых, позволяет избежать обнаружения продуктами EDR. Немедленный запуск процесса в фоновом режиме может быть очень подозрительным и указывать на вредоносность. Freeze делает это, вызывая функции Windows ‘GetConsoleWindow’ и ‘ShowWindow’ после создания процесса и загрузки хуков EDR, а затем изменяя атрибуты окна на скрытые. Freeze использует эти API вместо традиционных -ldflags -H=windowsgui, так как последние сильно сигнатурны и классифицируются большинством продуктов безопасности как индикатор компрометации.
Если выбран параметр командной строки -console, Freeze не будет скрывать процесс в фоновом режиме. Вместо этого Freeze добавит несколько отладочных сообщений, показывающих, что делает загрузчик.
Особая благодарность aahmad097 за разработку AlternativeShellcodeExec
Особая благодарность mvdan за разработку Garble