-
Notifications
You must be signed in to change notification settings - Fork 275
C2 Framework Integration
Covenant is a freely open source C2 framework developed in .NET. Covenant is a collaborative framework that demonstrates modern capabilities of .NET offensive tooling.
There are a number of commonalities between C2 frameworks that should be considered prior to integration with C3:
-
Payload generation – all frameworks have some manual or automated way of generating payloads.
-
Staging – the majority of frameworks provide access to staged and stageless payloads.
-
Implant tracking – any framework that expects to handle multiple implants running across several compromised system must internally track those implants.
In Covenant’s case:
-
Payload generation – Grunts (implants) can be generated from the Web UI or the Web API.
-
Staging – payloads have 3 stages before a fully established C2 channel is setup.
-
Implant tracking – Grunt’s are set with a unique GUID that is sent in any communication for internal tracking.
The second consideration to make is the ability for the given framework to accept connections and receive implant data. Cobalt Strike for example has the ExternalC2 specification. For Covenant the “Bridge Listener” provides similar functionality.
Finally, for ease of integration it helps if the chosen framework provides access to implants that communicate with each other over internal communication channels. Specifically, C3 expects the implants it runs in memory to create a named pipe for which data is read from and written to.
At a high level, the objective of integration would result in the communication flow described in the figure below: FIGURE1
The first step for integrating Covenant involves creating the new source files within C3. Initially this is performed by copying the the code from /src/Common/MWR/C3/Interfaces/Connectors/TeamServer.cpp
to Covenant.cpp
.
After replacing references to TeamServer, we end up with a number of methods that we simply need to redesign to work with Covenant. Highlighted below are the main functions which require alteration.
namespace MWR::C3::Interfaces::Connectors
{
/// A class representing communication with Covenant.
struct Covenant : Connector<Covenant>
{
/// Public constructor.
/// @param arguments factory arguments.
Covenant(ByteView arguments);
<...Snipped...>
}
<...Snipped...>
}
MWR::C3::Interfaces::Connectors::Covenant::Covenant(ByteView arguments)
{
<...Snipped...>
}
MWR::ByteVector MWR::C3::Interfaces::Connectors::Covenant::GeneratePayload(ByteView binderId, std::string pipename, uint32_t delay, uint32_t jitter, uint32_t connectAttempts)
{
<...Snipped...>
}
MWR::ByteView MWR::C3::Interfaces::Connectors::Covenant::GetCapability()
{
<...Snipped...>
}