February 24, 2021
Our most popular series of blog posts to date has been our posts on Command and Control (C2) with the open source PowerShell C2 framework, PowerShell Empire. In that series we cover basic command and control principles, PowerShell Empire specific concepts, and how to use the framework modules for various parts of the post-exploitation lifecycle of an attack. For a refresher on any of those concepts, head on over to our previous posts here:
In recent years, PowerShell Empire was retired by its original maintainers as PowerShell itself became more heavily logged and inspected. Defensive tools and EDR solutions in particular were quick to pick up on common malicious PowerShell usage, and alert on or prevent that type of activity. While there are still many great offensive (and defensive) use cases for PowerShell tradecraft, especially in less mature environments, this increased attention has led to a decline in its popularity among Red Teams for stealthy operations.
Since then, BC Security has pick up the mantle and maintains the most current version of PowerShell Empire. They’ve added some great functionality and have some complementary projects on GitHub as well. You can check out the most recent Empire here:
As PowerShell became more heavily monitored, Red Teams transitioned over to other post exploitation frameworks. There are many, but one of the more popular is a C# based framework called Covenant.
Created by Ryan Cobb (@cobbr_io), Covent is:
[…] a .NET command and control framework that aims to highlight the attack surface of .NET, make the use of offensive .NET tradecraft easier, and serve as a collaborative command and control platform for red teamers.
Covenant is an ASP.NET Core, cross-platform application that includes a web-based interface that allows for multi-user collaboration.
Covenant is maintained on GitHub here:
The framework provides many similar features as commercial post exploitation frameworks, and in particular draws resemblance to Cobalt Strike. The rich feature set, easy customization, and cross-platform compatibility make it a great option for Red Teams to run successful adversary simulation campaigns. In this post we’ll go over most of the features of Covenant and draw parallels to PowerShell Empire equivalents where appropriate.
Creating a listener is quite simple. By default, HTTP listeners bind to 0.0.0.0 meaning they will listen on any attached interfaces to the system Covenant’s server is running on. The “ConnectAddress” is an important concept. In more robust C2 infrastructure implementations, it is standard practice to isolate the main C2 server from directly connecting to compromised endpoints by redirecting through a “Redirector”. This ConnectAddress feature lets us quickly and easily configure Grunts to connect back to Covenant through one or more redirectors.
There is also the option to select from default or custom “HttpProfiles”. These control how our Grunt’s network requests appear when they check in with the Covenant server and can be modified/customized to our liking. A common reason for doing this would be to better blend in with existing traffic on the target network to avoid detection.
Once we’ve configured our listener(s), they are convenient listed for us on the Listeners page.
After a listener exists, we’re able to establish Grunts via any of the numerous launchers that Covenant provides out of the box.
In Covenant, a Launcher is any payload that executes an initial stager on the target host to establish a Grunt connection. These come in many flavors and can be easily customized via the Code UI to avoid detection or run as a stageless payload delivery mechanism. Covenant also provides a convenient hosting functionality which allows us to quickly host any launcher/payload we create. This is very handy, but we should be careful to serve payloads directly from our C2 server during engagements where stealth and infrastructure stability are important.
One thing to note about Covenant when discussing launchers is that the framework does not have any functionality designed to help exploit vulnerabilities. Like many of the other Command and Control frameworks available, Covenant is focused entirely on post exploitation; we have to find our own way to run our launchers on target systems. This is in contrast to tools like Metasploit which serve as both exploitation and C2 frameworks.
After running a Launcher on a target host, we’ll hopefully be presented with a Grunt! Grunts are Covenants version of and “agent” or “beacon” - they run in memory on compromised systems and communicate back to our C2 server.
We can interact with Grunts in several ways. The most familiar is through an interactive terminal. This allows us to quickly run commands on our compromised host.
Sometimes, the commands we’re interested in running may have a number of arguments and special characters which can make escaping them from this terminal challenging. In these cases, and to more easily know what arguments the built in Covenant commands take, we can turn to Tasks.
Tasks are Covenant’s prebuilt capabilities that can be run from any Grunt and perform our desired actions on compromised hosts. Examples of common tasks might be lateral movement via WMI and PowerShell, or running Mimikatz’s logonpasswords module to dump credentials from memory. Once a Grunt is tasked with a command, it can be viewed in the list of that grunts Taskings and checked in on periodically for the command output. This method of operating may feel slightly more asynchronous for red teamers used to Cobalt Strike, Meterpreter, or PowerShell Empire. However, we’ve found it quite useful to have this concept of taskings easily accessible to reference when and where we’ve run specific commands.
All of the available Grunt tasks can be found in the main Tasks list, and like most other Covenant features these tasks can be customized or added to. This theme of easy customization runs throughout
The actual Grunt processes that run on compromised hosts are written in C#, and the code for the various types of Grunts can be found in the “Templates” section. The main difference between the Grunt templates is in how they communicate with the Covenant server and with each other.
Again, these can be customized or added to in order to communicate in specific ways, better bypass AV and EDR solutions, etc. One of our favorite parts of covenant is how easy it is to reach this code and make changes on the fly.
Another useful feature of Covenant is the Data store. This page keeps information on things like credentials that have been automatically parsed out of Task which return credential material, indicators we’ve created during our operation, and file downloads and screenshots. The indicators list is especially helpful for cooperating with blue teams, during purple team exercises, and for reporting.
Now that we have a basic understanding of command and control concepts and Covenant specific features, we can go into more detail on how to operate effectively with Covenant during Red Teams and other engagements.
In our next post on Covenant, we’ll walk through Covenant set up in lab and perform common pieces of a Red Team engagement.