In my previous blog post, I created an Active Directory (AD) lab environment in AWS that I wanted to use to test/practice various redteam concepts and tools. One of the tools I was interested in testing is the new version of Covenant C2.
Covenant is a command-and-control (C2) framework. What this means is if you get a Covenant agent to run on a victim system, that Covenant agent will connect back to your C2 server. The agent will periodically check with the C2 server to see if there are any jobs or tasks assigned for the agent to perform. If the C2 server does have a task assigned for the agent, the agent will perform that task on the victim server, and then communicate back the results to the C2 server. If you have never been introduced to C2 frameworks before, this might not make a whole lot of sense to you, but hopefully by the end of this post it will be (slightly) clearer.
Note: This post will NOT describe how to setup a C2 infrastructure for a real world redteam engagement. This is meant only as a demonstration of how to get Covenant up and running in a lab environment. If you setup a real world C2 infrastructure like this, you’ll get burned quickly.
Creating the C2 Server in AWS
Covenant uses the .NET framework and runs on Windows. To create the C2 server, create a new Windows Server 2016 instance in AWS. This will follow the same process as creating the servers and workstations in the AD lab. The main difference is that the C2 server will be in a different security group that only allows HTTP/HTTPS communication between the AD lab and the C2 server.
To create a new instance in AWS, click on “Launch Instance” under the Instances tab.
Search for the “Windows Server 2016 Base” AMI, click select, and then click through the windows until you get to “Configure Security Group.” Here, you will define what can and cannot interact with the C2 server. You will first want to make sure that your own IP address can access the C2 server over RDP (I also included SSH in case I use a Linux server in the same security group later). You will then also want to make sure that the AD lab network can access your C2 server over HTTP and HTTPS. For this lab, this is how the Covenant agent will reach out to the Covenant C2 server. My security group configuration looks like this:
I initially tried to configure my C2 security group to only allow connections from my AD lab security group, which is why you see “sg-0#########” under “Source” for two entries. For some reason this didn’t work, but when I added in the “172.31.16.0/20” subnet for the source, connections worked. For your setup, you can probably ignore added the security groups as a source and stick with the subnet, or try and succeed where I failed…
Once the security group for the C2 server has been created, launch the instance and decrypt the local administrator password. You should then be able to connect over RDP to the system.
Installation instructions for Covenant can be found on github here. I will briefly cover it here as well.
First, I started by installing git for Windows, which can be downloaded here. This will be used later to download Covenant to your system, and to use whenever you want to download other tools from github.
The next thing you’ll need to install is the .NET Core runtime and SDK onto the C2 server. Both can be downloaded here from Microsoft. You will need to build Covenant on the system, so the SDK will need to be downloaded and installed to do so.
The next thing I did was created an “Exclusions” directory on my system and add it to Microsoft Defender as an AV exclusion. This allows me to download whatever tools I want to the Exclusions directory without having to worry that Defender will remove it. Alternatively, you could just turn off defender. I prefer the exclusion setting because in my experience Defender likes to turn itself back on after you turn it “off” and remove all your tools.
Search for “Defender” in the start menu and select “Windows Defender Settings.” Then, select “Virus and Threat Protection.” This will open a new window. Halfway down the screen you should see a section for “Virus & threat protection settings.” Click on “Manage settings.” Scroll down until you see “Exclusions”, and then click on “Add or remove exclusions.” Select the directory you want to be excluded from Defender detection and removal. For me, it looked like this:
Now, you can download and install Covenant. Open a command prompt as an Administrator and change directories to your exclusion directory.
Then, use “git” to download Covenant.
git clone --recurse-submodules https://github.com/cobbr/Covenant
Next, change directories to the Covenant directory, and use dotnet to build Covenant.
cd C:\Exclusions\Covenant\Covenant dotnet build
If you get the “Build succeeded” message, you should be good to startup Covenant. This is done with dotnet run. This will likely generate a lot of “warn” messages. This shouldn’t be an issue. As long as you see the “Now listening on https://0.0.0.0:7443” message, Covenant should be up and running.
When Covenant is run, it will listen on all interfaces on port 7443. This will be the port you use to connect to the management interface for Covenant. Open a browser and enter “https://localhost:7443/” into the URL bar and press enter. This will bring you to the login page for Covenant’s management interface.
When Covenant is run for the first time, you will need to create an initial user and provide a password. This initial user will be an “Administrator” on Covenant. If you want, more users with varying privilege levels can be added later. This is useful when multiple people are using the same C2 server (typical for a real world redteam engagements), but for this lab just the one Administrator user will work. I created my “fatrodzianko” user.
After the initial user is created, you should be presented with the Covenant C2 server interface.
Configuring the Victim System
Before going further with Covenant, I want to make sure that my victim system is configured correctly. For this test, I want to launch a Covenant agent on the wkst01 system and connect back to the C2 server. To better reflect how this would work in the “real” world, I want the agent to be running in the context of a domain user and not the local Administrator user I have been connecting to all the systems as. The reason for this is that the local Administrator user is not a member of the AD domain. If the Covenant agent ran in the context of the Administrator user, the agent would not be able to query AD directly. There are ways around this (such as using the local Administrator’s privileges to launch a second agent as SYSTEM, which would access AD as the AD computer account), but to make things easy, I am going to add a domain user to the “Remote Desktop Users” group on wkst01.
First, RDP to wkst01 as the local Administrator. Open a command prompt, and use the “net locagroup” command to add a domain user to the local “Remote Desktop Users” group.
net localgroup "Remote Desktop Users" "murph\regularuser" /add
After the domain user has been added to the “Remote Desktop Users” group, connect back to the system over RDP and specify the “murph\regularuser” (or whatever you named the domain user) instead of “Administrator.” You should be able to RDP as the domain user and interact with the system.
Creating a Listener in Covenant
Back on the C2 server, you will want to create a “Listener” in Covenant. Listeners are what is used to allow for agents to communicate with the C2 server. As the name suggests, they “listen” for agent connections. Covenant allows for listeners over HTTP and HTTPS. The listener will start up a web server that the agents can connect to. More information on Covenant listeners can be found on the github wiki.
To start, click on “Listeners” on the sidebar and then “Create.”
For testing purposes, the default configuration for the listener will work. “UseSSL” can be set to “False” for now. Plaintext HTTP will work for our purposes. In a future post I may demonstrate how to set up SSL for encrypted communications. In a real engagement, you would never want to use unencrypted communications. Click on “Create” to start the listener.
You should now see the listener listed under “Listeners.”
To test that the listener is working and that the AD lab system can access it, you can host a file on the listener. For this, I created a text file with the word “test” in it to host on the listener. Click on the listener in the Listeners page. It is the series of numbers listed under “Name” in the above screenshot. Then, click on “Hosted Files.”
On the “Hosted Files” page, browse to your test file location and click on “Create.”
Afterward, you should see the file hosted.
Connect back to the victim system wkst01. Open up a browser and enter the URL for the listener and the path to the test file. The URL should be the Private IP address of the C2 server listed in the AWS management console.
If you are able to access the file from the wkst01 system, you should be good to continue with setting up the C2 server.
Creating a Launcher for Covenant
“Launchers” are how the Covenant agent is launched on the target system. Covenant provides several options to create a launcher. More information on launchers can be found on the github wiki.
For this test, you will create a PowerShell launcher that will execute the agent by running a PowerShell command on the wkst01 system. Click on “Launchers” on the sidebar, and then on “PowerShell.”
The “ValidateCert” and “UseCertPinning” settings can be set to “False”, because we will not be using SSL for this test. The defaults will be fine for the rest of the configuration. Click on “Generate” to generate the PowerShell launcher.
After you click generate, you should see two PowerShell commands created at the bottom of the screen. One is the normal PowerShell command, and the other is a encoded command. Either will work for this test. On the right side of the command, there is a copy button you can click to copy the whole command.
Now that the launcher is created, you can launch a Covenant agent, or “Grunt” on the wkst01 system. Switch back over to the wkst01 system and open a PowerShell prompt. Paste in the launcher command, and then press “Enter.” When the launcher runs, the PowerShell prompt should disappear.
Back on the C2 server, click on “Grunts” on the sidebar. If the launcher executed successfully, you should see a Grunt with an “Active” status.
Interacting with the Grunt
After a Grunt has checked into the C2 server, you can start issuing the Grunt commands to execute on the wkst01 system. First, click on the name of the Grunt. This will bring up the Grunt information page.
To interact with the Grunt and provide it tasks/jobs to execute, click on “Interact.”
This will bring up the Grunt interaction window. Here is where you can enter commands/tasks for the Grunt to execute. You type in the commands at the bottom, and see the results in the top. As you type in a command, you will see suggestions for available commands. Typing in “kerber” brings up commands related to Kerberoasting and Kerberos tickets.
As an initial test, I selected the “Rubeus kerberoast” command for the Grunt to execute. This will use the tool “Rubeus” to perform a kerberoasting attack. I will (hopefully) go into more detail about what kerberoasting is and how it works in a later post. After the “Rubeus kerberoast” command/task finishes, you will see the results above the command prompt.
You can also see what commands/jobs/tasks have been assigned in the “Taskings” tab under Grunts. This will show you the task that was request, its status, and what Grunt it executed from.
If you click on the task “Name”, you will be provided details of that task and the results of the task (if it has completed).
Covenant has a large number of built in tasks that can be viewed under the “Task” tab in Grunts. Covenant also allows you to import your own PowerShell scripts or .NET assemblies to be executed through a Grunt.
To import a PowerShell script, go back to the “Interact” tab and type in “PowerShellImport.” When you press enter you will be prompted to browse to the script you want to import. In the below example, I am importing the “PowerView.ps1” script from PowerSploit.
After the PowerShell script has been imported, you can use the “PowerShell” command to execute cmdlets from your PowerShell script through the grunt. As an example, I used “get-domainuser” to get information on a user.
powershell get-domainuser -identity 'regularuser2'
That’s it for now on getting started using Covenant in the AWS AD lab. In future posts, I plan to write-up how to attack some of the weaknesses I built into the lab environment all through Covenant. I might also write a post on how to configure the C2 infrastructure to more closely reflect something that might be used in the real world. Until next time…