Greetings fellow red teamers and pen testers! In today’s increasingly complex security landscape, it’s crucial that we stay updated with the latest tools and techniques in order to keep our skills sharp and to provide the best possible services to our clients. Today, I’m excited to talk about Covenant, a powerful and versatile command and control (C2) framework that has become a game-changer for red teaming and post-exploitation operations.

This article is intended for a technical audience and assumes an intermediate understanding of security and hacking. It will be a deep dive into Covenant, including its architecture, installation, setup, usage, and real-world examples. We’ll also provide code samples and examples of tool execution to help you gain a better understanding of its capabilities. So, buckle up and let’s get started!

Covenant: An Overview

Covenant is a .NET-based C2 framework designed to enable red teamers and penetration testers to conduct post-exploitation operations with ease. Developed by Ryan Cobb (@cobbr_io), Covenant boasts a slick web-based interface, advanced features, and excellent support for the .NET runtime, making it particularly well-suited for Windows environments.

Key features of Covenant include:

  • Collaborative multi-user support
  • Modular architecture with a wide range of Grunt tasks
  • Support for dynamic compilation of .NET assemblies
  • Encrypted communication channels
  • Extensible through the development of custom tasks

With these features, Covenant has quickly gained traction in the red teaming and pen testing community and has been used in high-profile engagements, such as the Red Team vs. Blue Team exercise at DEF CON 27.

Covenant Architecture

Covenant’s architecture is based on a server-client model, with the Covenant server acting as the C2 and Grunt agents running on compromised systems. Grunt agents communicate with the Covenant server over encrypted channels, typically using HTTP, HTTPS, or a custom TCP protocol. This architecture allows for easy scalability and the ability to manage multiple Grunt agents simultaneously.

At a high level, Covenant’s architecture can be broken down into the following components:

  • Covenant Server: The main C2 server that orchestrates operations, manages Grunt agents, and serves the web-based interface.

  • Grunt Agent: The implant that runs on compromised systems and carries out tasks as directed by the Covenant server.

    Note: This is not to be confused with the Grunt javascript task runner.

  • Listener: A component responsible for handling incoming connections from Grunt agents and facilitating communication with the Covenant server.

  • Task: A unit of work that can be executed by a Grunt agent. Tasks can be predefined or custom-developed and are dynamically compiled as .NET assemblies.

Installing and Setting up Covenant

To get started with Covenant, you’ll need to install the framework on a system that will act as the C2 server. The installation process is quite straightforward, but we’ll walk you through it step by step.

Prerequisites

Covenant requires the following prerequisites to be installed on the system:

Installation Steps

First, clone the Covenant repository from GitHub:

git clone --recurse-submodules https://github.com/cobbr/Covenant.git

Next, navigate to the Covenant directory and build the project:

cd Covenant/Covenant
dotnet build

Finally, run the Covenant server:

dotnet run

Once the server is running, you can access the web-based interface by navigating to https://localhost:7443 in your browser. The default username is admin, and the default password is password. You should change these credentials upon logging in for the first time.

Creating a Listener

Before deploying Grunt agents, you’ll need to set up a listener to handle incoming connections. Covenant supports various listener types, such as HTTP, HTTPS, and TCP. In this example, we’ll create an HTTP listener.

Creating an HTTP Listener

To create an HTTP listener, follow these steps:

  1. Log in to the Covenant web interface.
  2. Navigate to the “Listeners” tab on the left-hand side.
  3. Click the “Create” button at the top right corner.
  4. Select “HttpListener” from the “Listener Type” dropdown menu.
  5. Fill in the required fields, such as Name, BindAddress, and Port. You may also configure optional settings like the ConnectAddress, ConnectPort, and URLs for the listener.
  6. Click “Create” to finalize the listener setup.

Once the listener is running, you can see its status in the “Listeners” tab.

Generating and Deploying Grunt Agents

With a listener in place, you can now generate Grunt agents to deploy on target systems. Covenant allows you to customize the agents, including their communication channels, staging methods, and obfuscation techniques.

Generating a Grunt Agent

To generate a Grunt agent, follow these steps:

  1. Log in to the Covenant web interface.
  2. Navigate to the “Grunt Stagers” tab on the left-hand side.
  3. Click the “Create” button at the top right corner.
  4. Select your desired stager type (e.g., PowerShell, MSBuild, or Regsvr32) and configure the required settings.
  5. Choose the listener you created earlier from the “Listener” dropdown menu.
  6. Click “Create” to generate the Grunt stager.

After generating the Grunt stager, you’ll be presented with a script, binary, or command, depending on the stager type you selected. You can use this output to deploy the Grunt agent on the target system.

Deploying a Grunt Agent

There are numerous ways to deploy a Grunt agent on a target system, depending on the stager type and the available attack vectors. For instance, if you generated a PowerShell stager, you could use a spear-phishing email with a malicious macro to execute the PowerShell script on the victim’s machine.

Once the Grunt agent is deployed and executed on the target system, it will establish a connection with your Covenant server via the configured listener. You can then interact with the Grunt agent and perform various post-exploitation tasks.

Interacting with Grunt Agents After successfully deploying a Grunt agent, you can interact with it through the Covenant web interface to execute tasks, gather information, and pivot to other systems.

Managing Grunt Agents

To manage your Grunt agents, follow these steps:

  1. Log in to the Covenant web interface.
  2. Navigate to the “Grunts” tab on the left-hand side.
  3. Click on a Grunt agent to view its details and interact with it.

Executing Tasks

To execute a task on a Grunt agent, follow these steps:

  1. Select the desired Grunt agent from the “Grunts” tab.
  2. Click the “Task” button at the top right corner.
  3. Choose a task from the “Task Name” dropdown menu.
  4. Fill in any required parameters for the selected task.
  5. Click “Task” to send the task to the Grunt agent for execution.

You can view the task output in the “Taskings” tab under the Grunt’s details.

Real-World Example: Mimikatz

One of the most popular tools for post-exploitation is Mimikatz, which can be used to dump credentials, tickets, and other sensitive information from a compromised system. Covenant includes a built-in Mimikatz task, which allows you to execute Mimikatz commands directly from the Grunt agent.

To run Mimikatz using Covenant, follow these steps:

  1. Select the desired Grunt agent from the “Grunts” tab.
  2. Click the “Task” button at the top right corner.
  3. Choose the “Mimikatz” task from the “Task Name” dropdown menu.
  4. Enter the Mimikatz command you’d like to run in the “Command” field, such as “privilege::debug sekurlsa::logonpasswords”.
  5. Click “Task” to send the Mimikatz command to the Grunt agent for execution.

The Mimikatz output will be displayed in the “Taskings” tab under the Grunt’s details. You can use this output to gather credentials, tickets, and other valuable information from the compromised system.

Developing Custom Tasks

Covenant’s modular architecture allows you to develop custom tasks to extend its functionality. Custom tasks are written in C# and must implement the ITask interface.

To create a custom task, follow these steps:

  1. Create a new C# class that implements the ITask interface.
  2. Implement the required properties and methods, such as Name, Description, Parameters, and Execute.
  3. Compile the custom task into a .NET assembly.
  4. Upload the assembly to the Covenant server using the web interface.

Once the custom task is uploaded, you can execute it on Grunt agents just like any other predefined task.

Conclusion

Covenant is a powerful and versatile C2 framework that has become an essential tool for red teaming and post-exploitation operations. Its advanced features, such as dynamic compilation of .NET assemblies, encrypted communication channels, and multi-user support, make it well-suited for conducting sophisticated engagements.

In this article, we’ve provided an in-depth look at Covenant, covering its architecture, installation, setup, usage, and real-world examples. We’ve also discussed how to develop custom tasks to extend its functionality. With this knowledge, you’re now better equipped to leverage Covenant in your red teaming and pen testing activities.

As security professionals, it’s crucial that we continue to hone our skills and stay updated with the latest tools and techniques. I hope this article has been helpful in introducing you to the power of Covenant and inspiring you to explore its capabilities further. Happy hacking!