
Python API для использования со спецификацией External C2 от Cobalt Strike
Python-фреймворк для создания и использования интерфейсов передачи данных между фреймворками, с особым акцентом на использование в качестве расширения для фреймворков управления командными центрами (Command and Control).
В настоящее время это предполагается только как реализация спецификации External C2 от Cobalt Strike, описанной в этом документе спецификации, но по мере развития проекта это может измениться.
Огромная благодарность xychix. Этот проект был бы вообще невозможен без его ценного вклада. По сути, этот проект является переработкой и расширением проекта External C2 от Outflank
Этот проект состоит из следующих основных частей:
Builder считывает файл конфигурации и использует настроенные параметры для генерации сборки путём замены маркеров внутри skeletons.
Builder можно использовать с помощью build_files.py. Пример конфигурации builder'а предоставлен как sample_builder_config.config.sample.
skeletons — это различные «скелеты» кода, которые builder динамически заполняет для генерации полностью рабочей сборки. skeletons содержат маркеры, которые будут заменены builder'ом на используемые значения. Существует три различных «типа» скелетов:
Маркер может быть размещён в любом файле внутри skeleton, и он будет заменён значением, указанным в конфигурации builder'а. Согласно лучшим практикам, маркеры никогда не должны использоваться для непосредственной записи переменных и должны использоваться только для установки значений. Если значение маркера необходимо использовать повторно, следует сохранить значение в переменной и ссылаться на него таким образом, вместо повторного использования того же маркера.
Формат маркера: ```[var:::identifier_for_the_marker]```
Строки будут записаны в скелет, обрамлённые одинарными кавычками, а числа будут записаны как есть.
В случае, если строка в конфигурации заключена в двойные кавычки, строка будет записана в файл в двойных кавычках, а обрамляющие одинарные кавычки будут удалены.
Эту зависимость можно продемонстрировать так:
#################
# Skeleton Code #
#################
# Skeleton contains the following line of code:
foo = ```[var:::bar]```
##############
# End Result #
##############
# Stored in config as:
# foo = bar
# Written as:
foo = 'bar'
# Stored in config as:
# foo = "bar"
# Written as:
foo = "bar"
# Stored in config as:
# foo = 2
# Written as:
foo = 2
# Stored in config as:
# foo = "2"
# Written as:
foo = "2"
Frameworks — это базовое приложение, которое определяет, какие данные используются transport и encoder, и как эти данные используются. То, что конкретный framework фактически делает, не имеет большого значения, если существует логика для импорта и использования encoder и transport. Большинство важных частей фреймворка (в первую очередь логика client) будут храниться в виде skeleton, а интерфейс для взаимодействия с серверной его частью будет храниться как базовый объект framework.
Как правило, фреймворк содержит server и client и использует encoders и transports для передачи данных между ними.
При создании framework следует учитывать несколько основных моментов:
framework отвечает за то, чтобы encoder был доступен transport для использования.framework использует связь клиент-сервер, они должны быть соответствующим образом организованы.client фреймворка, поэтому если вы хотите, чтобы что-то можно было перенастраивать на client, ему необходимо уметь делать это во время выполнения без прямого взаимодействия.skeleton для server, потому что конечный пользователь будет напрямую взаимодействовать с server фреймворка. Вместо этого следует как считывать параметры из конфигурации, так и давать конечному пользователю возможность изменять параметры (например, таймер блокировки или подробность вывода) во время выполнения.Skeleton фреймворка будет обработан builder'ом, который перебирает каждый файл в нём, поэтому, если определённый аргумент должен быть настраиваемым во время сборки, это можно легко сделать.server фреймворка должен иметь возможность взаимодействовать с общим framework_manager.Сервер — это приложение, которое обеспечивает связь между client и c2 server. Логика сервера в основном статична. Логика сервера для фреймворка cobalt_strike, называемая в спецификации third-party Client Controller, показана ниже:
encodertransporttransportencodertransporttransportencoderserver должен поддерживать возможность работы с несколькими клиентами (ещё не реализовано) и иметь интерфейс для взаимодействия с framework_manager.
Клиент — это, по сути, полезная нагрузка (payload), которая запускается на конечной точке. Логика клиента для фреймворка cobalt_strike в основном статична и показана ниже:
transporttransporttransport на предмет новых задачtransportКлиент использует указанные encoder и transport для передачи данных между собой и соответствующим server.
Encoders получают данные, а затем преобразуют их либо для подготовки к отправке через transport, либо декодируют данные, полученные через transport, обратно в исходную форму для интерпретации тем компонентом framework, который их использует.
Encoders должны рассчитывать на прямое взаимодействие с transport и обрабатывать данные независимо от фреймворка и компонента.
Transports выполняют роль отправки и получения данных через канал связи, а также взаимодействуют с encoder, чтобы гарантировать преобразование данных в необходимый формат. Transports должны получать данные от компонента фреймворка или через канал связи и иметь возможность передавать данные через канал связи. Transports отвечают за вызов encoder для кодирования или декодирования данных по мере необходимости.
Transports должны рассчитывать на прямое взаимодействие с компонентом framework и обрабатывать данные независимо от фреймворка и компонента.
Сначала определите, какие модули транспорта и кодирования вы хотите использовать. В следующем примере мы будем использовать transport_imgur и encoder_lsbjpg.
Затем создайте builder_config.config в соответствии с вашими потребностями; обратитесь к предоставленному примеру конфигурации и шаблону для понимания того, как это сделать.