
C2Bridges allow developers to create new custom communication protocols and quickly utilize them within Covenant.
C2Bridges позволяют разработчикам создавать новые пользовательские протоколы связи и быстро использовать их в Covenant.
C2Bridges используются для разработки исходящего протокола управления и контроля без редактирования кода Covenant. Для разработчиков, которые чувствуют себя комфортно при интеграции новых слушателей, новый протокол C2 следует добавлять как полноценный тип слушателя первого класса, полностью интегрированный в интерфейс. Однако в некоторых ситуациях может быть быстрее создать C2Bridge вне Covenant и подключить его к BridgeListener для концептуальных прототипов или тестирования новых протоколов.
Разработчики могут использовать проект C2Bridge в качестве шаблона для создания новых C2Bridges. В проекте C2Bridge есть абстрактный класс C2Bridge. Разработчик может унаследоваться от этого класса и реализовать необходимые функции для чтения и записи имплантов в BridgeListener с помощью нового выбранного протокола C2.
using System.Threading;
using System.Threading.Tasks;
namespace C2Bridge
{
/// <summary>
/// IC2Bridge — это интерфейс, реализуемый классом C2Bridge.
/// </summary>
public interface IC2Bridge
{
Task RunAsync(CancellationToken token);
}
/// <summary>
/// C2Bridge — это абстрактный класс, от которого должны наследоваться новые C2Bridges.
/// </summary>
public abstract class C2Bridge : IC2Bridge
{
// BridgeConnector обрабатывает связь между сервером Covenant и C2Bridge
protected BridgeConnector BridgeConnector { get; set; }
// BridgeProfile обрабатывает парсинг и форматирование данных, передаваемых между имплантом и Covenant
protected BridgeProfile BridgeProfile { get; set; }
/// <summary>
/// Конструктор для C2Bridge. Новые C2Bridges должны использовать свой собственный конструктор,
/// который принимает любые аргументы командной строки, необходимые для работы C2Bridge.
/// </summary>
/// <param name="Connector">BridgeConnector, который обрабатывает связь с сервером Covenant.</param>
/// <param name="Profile">BridgeProfile, который обрабатывает парсинг и форматирование данных.</param>
protected C2Bridge(BridgeConnector Connector, BridgeProfile Profile)
{
this.BridgeConnector = Connector;
this.BridgeProfile = Profile;
BridgeConnector.OnReadBridge += OnReadBridge;
}
/// <summary>
/// Функция RunAsync является основной функцией, которая должна запустить C2Bridge и продолжать работу, пока
/// вы не завершите свою операцию. Разработчики C2Bridge должны реализовать логику запуска и работы слушателя
/// в этой функции.
/// </summary>
/// <param name="Token">CancellationToken, который отменит C2Bridge, если источник токена будет отменён.</param>
/// <returns></returns>
public abstract Task RunAsync(CancellationToken Token);
/// <summary>
/// Функция OnReadBridge вызывается каждый раз, когда с сервеера Covenant считываются данные, предназначенные для импланта.
/// Разработчики C2Bridge должны реализовать логику для определения, какому импланту предназначены эти данные, и записать
/// эти данные в имплант.
/// </summary>
/// <param name="sender">
/// Sender — это объект, который вызвал функцию OnReadBridge. Разработчики C2Bridge могут игнорировать этот параметр.
/// </param>
/// <param name="args">Args содержит данные, которые должны быть записаны с сервера Covenant в имплант.</param>
protected abstract void OnReadBridge(object sender, BridgeConnector.ReadBridgeArgs args);
/// <summary>
/// Функция WriteToConnector обрабатывает запись данных от импланта на сервер Covenant. Эта логика должна быть
/// одинаковой для всех типов C2Bridge, но может быть перегружена разработчиком C2Bridge, если требуется пользовательская логика.
///
/// При вызове этой функции возвращаемая строка GUID должна использоваться для отслеживания значений GUID импланта в C2Bridge.
/// </summary>
/// <param name="Data">Данные, прочитанные из импланта, которые должны быть записаны на сервер Covenant.</param>
/// <returns>
/// Возвращает значение GUID, извлечённое из Data. Это значение должно использоваться для отслеживания значений GUID импланта в C2Bridge.
/// </returns>
protected virtual string WriteToConnector(string Data)
{
var parsed = this.BridgeProfile.ParseWrite(Data);
if (parsed != null)
{
_ = this.BridgeConnector.Write(this.BridgeProfile.FormatRead(parsed));
return parsed.Guid;
}
return null;
}
/// <summary>
/// Функция GetBridgeMessengerCode должна содержать код, который будет встроен в имплант для связи с
/// C2Bridge. Эта функция нигде не используется в проекте, но она здесь для того, чтобы необходимый
/// код импланта можно было найти вместе с C2Bridge. Разработчики C2Bridge должны разместить код здесь для использования в
/// свойстве BridgeMessengerCode BridgeProfile.
/// </summary>
/// <returns></returns>
protected abstract string GetBridgeMessengerCode();
}
}
Проект C2Bridge содержит пример класса TCPC2Bridge, который наследуется от этого интерфейса и предоставляет пример того, как его реализовать.

После того как вы написали свой новый C2Bridge, вызов конструктора TCPC2Bridge в функции Main() можно заменить на новый конструктор:

Абстрактный метод GetBridgeMessengerCode() нигде не используется в проекте C2Bridge, но он используется для связывания C2Bridge с имплантом. Импланту нужен код, который может читать и записывать данные в исходящий C2Bridge. Этот код специфичен для конкретного C2Bridge и должен быть помещён в унаследованный метод GetBridgeMessengerCode(). Пользователь Covenant, использующий C2Bridge, возьмёт BridgeMessengerCode из этого метода и использует его в BridgeProfile.
Пользователям Covenant, использующим C2Bridge, необходимо будет настроить BridgeProfile, специфичный для этого C2Bridge. Импланты Grunt должны знать, как читать и записывать данные в исходящий C2Bridge. Свойство BridgeProfile.BridgeMessengerCode представляет собой код, который будет помещён в имплант и отвечает за чтение и запись в исходящий C2Bridge. Этот код должен быть найден в методе GetBridgeMessengerCode() C2Bridge.
Пользователи могут создать совершенно новый BridgeProfile или отредактировать DefaultBridgeProfile, указав правильный BridgeMessengerCode. Для этого перейдите на страницу навигации слушателей и выберите вкладку "Profiles":

Чтобы создать новый профиль, нажмите кнопку "Create". Чтобы отредактировать конкретный профиль, нажмите на его название. Имейте в виду, что вы не можете редактировать профили, связанные с активными слушателями.
После нажатия "Create" выберите вкладку "BridgeProfile":

При редактировании или создании профиля необходимо настроить следующие параметры:
Name профиля, который будет использоваться во всём интерфейсе. Выберите что-то узнаваемое!Description профиля. Это должно быть подробное описание профиля, которое операторы смогут прочитать и легко понять, как работает профиль и в каких случаях его следует использовать.MessageTransform — это уникальный способ указать, как данные связи будут преобразованы перед помещением в форматы, указанные в ReadFormat и WriteFormat. MessageTransform должен быть статическим C# классом с именем MessageTransform, который включает публичные функции Transform и Invert. Класс может преобразовывать данные любым желаемым способом, при условии, что функции Transform и Invert зеркально отражают друг друга (т.е. data == MessageTransform.Invert(MessageTransform.Transform(data))). Класс MessageTransform должен быть кроссплатформенным и компилироваться под , и .При настройке этих параметров пользователь Covenant имеет полную свободу настраивать любые значения по своему усмотрению, за исключением свойства BridgeMessengerCode. Свойство BridgeMessengerCode должно быть взято из C2Bridge.
Если пользователь Covenant изменяет свойства ReadFormat и/или WriteFormat, C2Bridge должен быть уведомлён об этом изменении при запуске C2Bridge. Проект C2Bridge принимает параметр --profile <profile.yaml>, который принимает YAML-файл профиля; его можно использовать по желанию, когда эти свойства настроены индивидуально.
Общий процесс разработки и использования C2Bridge выглядит следующим образом:
C2Bridge из проекта C2Bridge. В качестве примера используйте класс TCPC2Bridge.BridgeProfile, использующий BridgeMessengerCode, найденный в методе GetBridgeMessengerCode() C2Bridge.BridgeProfile.ReadFormat и/или WriteFormat BridgeProfile, используйте параметр командной строки --profile <profile.yaml> для информирования C2Bridge об этих настройках.GruntBridge и запущенный вами BridgeListener.Net40Net35NetCore21ReadFormat — это формат сообщения, когда Grunt читает данные из C2Bridge. Формат должен включать место для данных и GUID Grunt. Вставьте строку "{DATA}" для указания места размещения данных и строку "{GUID}" для указания места размещения GUID.WriteFormat — это формат сообщения, когда Grunt записывает данные в C2Bridge. Формат должен включать место для данных и GUID Grunt. Вставьте строку "{DATA}" для указания места размещения данных и строку "{GUID}" для указания места размещения GUID.BridgeMessengerCode — это код, который будет помещён в имплант и отвечает за чтение и запись в исходящий C2Bridge. Этот код должен быть найден в методе GetBridgeMessengerCode() C2Bridge.