Как я встретил Вашу мамку. Часть 1. Обзор

D2

Администратор
Регистрация
19 Фев 2025
Сообщения
4,380
Реакции
0
Введение

Ни для кого не секрет, что MDSec предоставляет коммерческую систему командования и контроля, ориентированную на уклонение от тайных операций. Помня об этом, мы постоянно проводим исследования и разработки методов, позволяющих не только скрыть маяки, но и обнаружить их. Действительно, некоторые утверждают, что лучший способ создать неуловимый маяк — это не только понять, каким образом ваши оппоненты обнаруживают вас, но и попытаться найти новые способы, с помощью которых они могли бы обнаружить вас в будущем.

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

Первоначально этот материал обсуждался на x33fcon 2022, слайды к этому материалу можно найти здесь - https://github.com/mdsecresearch/Publications/blob/master/presentations/How I Met Your Beacon - x33fcon.pdf.

Подходы к обнаружению маяков

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

Поведение

Поведение маяка во время его не только работы, но и загрузки может создать возможности обнаружения для защитников. Многие коммерческие фреймворки имеют закрытый исходный код, и поэтому некоторые модели поведения не могут быть легко изменены, что позволяет защитникам создавать подписи, соответствующие этим действиям.

Отличным примером этого является то, как маяк загружает себя и свои зависимости; давайте посмотрим, как поведение, связанное с загрузкой изображений, может предоставить защитникам возможности обнаружения.

Чтобы маяк обеспечивал богатую структуру постэксплуатации, он часто в значительной степени полагается на библиотеки, встроенные в операционную систему, что позволяет разработчику сохранять размер маяка как можно меньшим, избегая статического объединения многих зависимостей.

Анализируя ряд фреймворков маяков, мы заметили, что многие из них будут загружать все зависимости, необходимые для основного маяка, во время загрузки, а не при использовании. В некоторых случаях это приводит к уникальной последовательности событий, происходящих на конечной точке, которую защитники могут легко подписать.

Например, часто можно увидеть маяки, использующие собственные HTTP-библиотеки Windows для выходных маяков путем загрузки winhttp.dll и wininet.dll; они могут выделяться как аномалии при загрузке в процессы, которые обычно не выполняют HTTP-взаимодействие. Кроме того, было замечено, что некоторые маяки загружают библиотеки, которые используются реже, например credui.dll, dbghelp.dll или samcli.dll.

Используя эти последовательности загрузки DLL, становится возможным создавать сигнатуры с использованием правил EQL для определения момента выполнения маяка.

Например, используя правило EQL, подобное следующему, можно обнаружить или отслеживать все процессы, загружающие credui.dll и winhttp.dll в течение короткого периода времени:

1696592745840.png



Конечно, этой категории обнаружения можно избежать с помощью маяков, которые спроектированы так, чтобы быть модульными или зависеть от нагрузки в зависимости от использования или с задержкой загрузки.

При обнаружении памяти

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

Типичный процесс загрузки маяка может выглядеть следующим образом:

1696592759673.png



После того как маяк запускается в памяти, посредством анализа процесса часто появляется ряд индикаторов, которые мы можем использовать для обнаружения маяка; давайте рассмотрим некоторые подходы к обнаружению в памяти.

Сигнатуры

Возможно, одна из самых простых, но наиболее эффективных стратегий обнаружения маяков в памяти для известных вредоносных программ — это обнаружение сигнатур. Хотя многие антивирусные механизмы и EDR реализуют свои собственные процедуры сканирования памяти, охотники за угрозами могут легко выполнить комплексное сканирование памяти, используя правила Yara.

Простое правило Yara, которое можно использовать с утилитой командной строки yara64.exe, может выглядеть следующим образом и будет соответствовать при обнаружении любой из трех перечисленных строк в памяти:

1696592772298.png



Создание правил Yara для строк/данных, встроенных в маяк, или кода из раздела .text концептуально может использоваться как эффективный метод обнаружения известных вредоносных программ в памяти.

В прошлом компания Elastic проделала большую работу по изучению того, как это можно использовать для обнаружения Cobalt Strike в памяти , и рекомендуется прочитать, как эти методы можно применять на практике - https://www.elastic.co/blog/detecting-cobalt-strike-with-memory-signatures.

Чтобы избежать такого сканирования памяти, маяки могут использовать ряд методов для скрытия своего следа в памяти, включая замену известных строк, что может быть достигнуто с помощью опции Malleable профиля Cobalt Strikes strrep и/или использования стратегии запутывания и сна, такой как тот, который мы используем в Nighthawk для защиты всех строк, данных и кода маяка во время сна.

Хуки памяти

Чтобы обойти элементы управления или изменить способ функционирования процесса, маяки (или оператор) могут применять перехватчики к определенным функциям в памяти. Эти хуки могут оставлять скрытые следы, которые могут предоставить охотникам за угрозами возможность обнаружить скрытые маяки. Давайте рассмотрим несколько примеров такого поведения.

Исправления ETW и AMSI

Исправление элементов управления безопасностью, таких как AMSI, и/или ухудшение телеметрии, полученной с помощью трассировки событий для Windows, не является секретом для атакующего сообщества, более того, в прошлом мы уже писали об этой тактике в блогах .

Эти исправления обычно применяются путем изменения памяти; давайте посмотрим на два примера, взятые из арсенала Sliver C2:


1696592789915.png




1696592804464.png



Как мы можем видеть на скриншотах выше, оба этих примера заставят маяк применить исправление либо к функциям ntdll!etwEventWrite, либо к функциям amsi.dll!AmsiOpenSession .

Имея это в виду, возможность обнаружения с низким уровнем шума возникает просто путем поиска процессов с этими исправлениями, примененными к этим и другим обычно исправленным функциям, таким как AmsiScanBuffer или SleepEx, к которым применяется перехват с помощью функции подмены стека потоков Cobalt Strike из комплекта арсенала.

Копирование при записи

Как отмечалось выше, маяки нередко применяют исправления к памяти процессов, которые могут создать возможности обнаружения для охотников. Однако плодотворность этих поисков может снизиться, если маяк удалит патчи после завершения операций по эксплуатации. Например, имплант может применить исправление AMSI перед выполнением сборки .NET в памяти, а затем после выполнения вернуть исправление к исходным кодам операций. Этот подход в некоторой степени более разумен, чем простое оставление висящих участков в памяти.

Однако, чтобы избежать дублирования, Windows сохраняет общие библиотеки DLL в физическую память, которая используется совместно всеми запущенными процессами. Если маяк или оператор выполнит операцию, которая применяет исправление к одной из этих DLL, произойдет копирование при операции записи, что сделает страницу частной для этого процесса. Используя API QueryWorkingSetEx, мы можем запрашивать информацию о страницах по определенному виртуальному адресу процесса. В возвращаемой структуре PSAPI_WORKING_SET_EX_INFORMATION находится объединение PSAPI_WORKING_SET_EX_BLOCK, которое указывает атрибуты страницы по запрошенному адресу. В рамках этого объединения мы можем определить, произошла ли на странице операция копирования при записи, по возвращаемому значению бита Shared. Этот метод используется сканерами памяти, такими как Moneta очень эффективен при обнаружении патчей в памяти, даже если исходное значение патча восстановлено.

Однако существует некоторый риск ложного срабатывания при применении этого метода в большом масштабе, поскольку EDR и антивирусное программное обеспечение нередко применяют свои собственные перехватчики в памяти, а это означает, что они могут аннулировать часть ценности, которую мы можем получить от поиска для копирования при операциях записи. Однако, чтобы, возможно, снизить риск ложных срабатываний, мы можем применить к этому больше интеллекта, разрешив экспорт на измененных страницах и применив больший вес к функциям, которые EDR обычно не перехватывают, например EtwEventWrite или AmsiScanBuffer .

Аномалии в потоках

Как отмечалось ранее, когда маяк работает в памяти, он обычно находится внутри одного или нескольких потоков, в зависимости от того, является ли маяк синхронным или асинхронным. Аномалии, связанные с этими потоками, могут обеспечивать высокие показатели сигнала активности маяка, в частности, в сочетании с другими индикаторами или совместно друг с другом. Некоторые распространенные индикаторы, связанные с подозрительными потоками, включают следующее:

- Неотображенная память: потоки, возникающие из виртуальной памяти без поддержки DLL, являются классическим индикатором внедренного потока. Эти потоки можно легко обнаружить, выискивая потоки с областями памяти с MemoryType MEM_IMAGE и MemoryState MEM_COMMIT. Альтернативно, эти потоки обычно обнаруживаются при проверке EDR с помощью обратных вызовов ядра для API создания потоков. Этот индикатор хорошо документирован , и существует множество инструментов для поиска этого индикатора.

- Состояние задержки: большую часть времени маяк будет находиться в спящем режиме, прежде чем пробудится для восстановления своей работы. Для достижения такого режима сна обычно используются вызовы Windows API, такие как SleepEx ; они переводят поток в состояние ожидания и приводят к созданию стека вызовов потока, содержащего вызовы KernelBase.dll!SleepEx и ntdll.dll!NtDelayExecution. В сочетании с другими индикаторами, такими как признаки поломки модуля (обсуждаемые позже) или вызовы виртуальной памяти в стеке вызовов, это может дать некоторую информацию о поведении маяка.

Попытки уклониться от обнаружения подозрительных потоков в последнее время стали популяризированы: было опубликовано несколько доказательств концепции и коммерческих реализаций.

Эти реализации обычно работают либо путем усечения стека вызовов потока (например, путем установки адреса возврата кадра в ноль), либо путем клонирования контекста существующего потока. Имея это в виду, у нас есть дополнительные индикаторы, которые мы можем добавить к нашим метрикам:

- Подозрительный начальный адрес: одним из побочных эффектов усечения стека вызовов потока является то, что начальный адрес происходит не из ожидаемого местоположения. То есть потоки обычно возникают из ntdll!RtlUserThreadStart и kernel32!BaseThreadInitThunk или ntdll!RtlGetAppContainerNamedObjectPath в случае потоков CLR. Поиск потоков, не соответствующих этому шаблону, может быть использован как подозрительный показатель для дальнейшего анализа. Более того, начальный адрес потока также может считаться подозрительным и указывать на потенциальное усечение, если существует несоответствие между возвращаемым значением NtQueryInformationThread(ThreadQuerySetWin32StartAddress) для потока и обратным адресом последнего кадра.

- Расстояние между начальными кадрами: как уже упоминалось, начальный начальный адрес стека вызовов обычно происходит из заданного количества адресов, используемых для инициализации и создания потока. Расстояние между этими исходными кадрами стека считается относительно постоянным и обычно статическим между первым и вторым кадрами (например, ntdll!RtlUserThreadStart и kernel32!BaseThreadInitThunk ). В сценарии, где стек вызовов усекается, расстояние между этими кадрами почти наверняка будет переменным.

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

Разрешения страницы

Вообще говоря, маяк будет работать из виртуальной памяти или из региона, поддерживаемого DLL.

Чтобы маяк мог восстановиться и выполнить свои задачи, к страницам, на которых находится маяк, должны быть применены разрешения на выполнение. Если это происходит из виртуальной памяти и за исключением сжатого кода (например, CLR), очень редко можно увидеть частную выделенную память с разрешениями на выполнение.

Например, на следующем снимке экрана мы видим, что память по адресу 0x22f96c5000 не поддерживается DLL, она помечена как «Private:Commit» (т.е. виртуальная память в результате VirtualAlloc ) и ей установлены разрешения страницы RX:

1696592830950.png



Эти индикаторы являются сильным сигналом о том, что в этом регионе работает маяк.

Тогда возникает проблема: как можно избежать этого показателя; простой ответ - получится, если ваш маяк работает из виртуальной памяти, в какой-то момент маяк должен выполниться. Компромисс на самом деле состоит в том, чтобы поддерживать разрешения на исполняемый файл только в то время, пока маяк выполняет задачи, и использовать стратегии для удаления разрешений на исполняемый файл, пока маяк находится в спящем режиме. Таким образом, отказ от таких профессиональных приемов, как проксирование SOCKS, может помочь минимизировать воздействие этого индикатора:

1696592839116.png



Некоторые имплантаты используют стратегии для перетасовки защиты страницы в соответствии с состоянием маяка, а также несколько реализаций с открытым исходным кодом, таких как Foliage @ Ilove2pwn_ , Ekko @ c5pider, ShellcodeFluctuation @mariuszbit и Gargoyle Джоша Лоспинозо .

Эти стратегии обычно используют ту или иную форму выполнения, управляемого событиями, для перевода маяка в режим сна и пробуждения, повторного запуска выполнения с использованием гаджетов ROP для вызова VirtualProtect и сброса страниц маяка обратно к исполняемым разрешениям. Техника, основанная на таймере, открытая Питером Винтер-Смитом из MDSec и использованная Экко, изначально была реконструирована на основе Nighthawk c2 от MDSec. Короче говоря, этот метод работает путем постановки в очередь нескольких таймеров с помощью CreateTimerQueueTimer, которые затем, когда триггеры событий возвращаются к ранее определенной записи контекста, выполняемой с использованием NtContinue, и вызова VirtualProtect для повторного включения бита выполнения.

Модуль Stomping

Модуль Stomping предоставляет альтернативный метод сокрытия вашего маяка в памяти, избегая некоторых общих индикаторов, связанных с маяком из неотображенной памяти. Концептуально для этого загружается легитимная DLL, которая вряд ли будет использоваться процессом, и маяк копирует себя поверх модуля; затем создается поток, поддерживаемый Stomping кодом:

1696592853725.png



Cobalt Strike предлагает эту функцию с момента выпуска 3.11, и она доступна с использованием гибких параметров конфигурации «set module_x64/module_x86».

Хотя этот метод может обеспечить ряд преимуществ OpSec, он оставляет после себя несколько индикаторов, которые мы можем надежно обнаружить:

Пожалуй, самый простой метод обнаружения этой атаки — сравнение содержимого модуля в памяти с тем, что существует на диске. Любые изменения в разделах кода почти наверняка будут указывать на какое-то подозрительное поведение. Этот процесс, конечно, относительно интенсивен, поскольку он потребует загрузки всех модулей работающего процесса с диска и сравнения с рабочей памятью.

Как описано ранее, изменения во внутренней памяти модуля приведут к выполнению операции копирования при записи. Имея это в виду, та же логика, которая описана для обнаружения перехватов памяти, также может быть применена для обнаружения прерывания модуля, поскольку перезапись DLL в памяти приведет к созданию копии DLL и очистке общего бита.

Существует несколько подходов, которые можно использовать для выполнения обработки модулей: некоторые включают использование существующих API-интерфейсов Windows, таких как LoadLibrary, тогда как другие, более сложные реализации могут использовать специальные загрузчики для отображения DLL в памяти. Некоторые методы имеют связанные с ними известные индикаторы, оставляющие постоянные следы в PEB, которые можно использовать для поиска этого метода с высокой степенью достоверности. Примеры этого будут обсуждаться более подробно позже.

В заключение мы изложили ряд стратегий обнаружения маяков в памяти. В следующей части этой серии мы начнем рассматривать ряд примеров реальных фреймворков и посмотрим, как мы можем применять эти методы.

Переведено специально для XSS.IS
Автор перевода: yashechka
Источник: https://www.mdsec.co.uk/2022/07/part-1-how-i-met-your-beacon-overview/


View hidden content is available for registered users!
 
Сверху Снизу