Covenant C2 Infrastructure with Redirectors

In my previous post, I wrote about getting started with Covenant C2. In that post the infrastructure I setup for the C2 communications was very simple: The C2 agents connected directly to the C2 server over a private subnet. This works for a lab environment, but for a real world redteam engagement having your C2 agents connect directly to your C2 server is going to get your infrastructure caught and burned quickly. That’s bad news!

This post will describe a very simple C2 infrastructure setup using one redirector. The C2 communications will now look like this:

C2 Agent -> Redirector Server -> C2 Server

If someone were to investigate a system you had a C2 agent running on, they would only see the domain name and IP address of your redirector server. They shouldn’t see any information about your C2 server. This setup is simple and straightforward, and can leave a lot to be desired, but should showcase some concepts used in C2 infrastructures.

The following will be covered:

  • Choosing a domain for your C2 communications
  • Getting the domain categorized
  • Creating an SSL certificate for secure C2 communications
  • Configuring the redirector to proxy C2 communications to your C2 server

A lot of this information can also be found at HoldMyBeerSecurity’s blog post here. I recommend reading their write-up over mine. It’s very good and thorough!

Choosing Your Domain

Before, my C2 agents were configured to reach out to an IP address directly. This was performed over HTTP requests. The C2 agents are meant to look like normal user activity to try and remain undetected. When a user accesses a website, they typically type in the domain name, not the IP address. So, we will want to have a domain registered for our C2 agents to call out to.

When choosing a domain name, you should consider what “category” the domain could potentially fall under. Many organizations use web proxies that all user HTTP/HTTPS traffic goes through. These proxies will categorize domains users visit, and can potentially take actions depending on the category. If a user visits a domain that is categorized as “Malicious”, the proxy will likely block the user’s web requests. If the domain is new the proxy may not have a category for it yet. Many organizations block traffic to all “uncategorized” domains, so you will want to make sure yours is categorized.

Another thing to consider is if organizations use SSL decryption at their perimeter to inspect web traffic. If an organization does this, they may be able to inspect and investigate your C2 traffic even if it is encrypted. However, some organizations won’t decrypt traffic to potentially sensitive domain categories. Traffic to domains categorized as finance or healthcare may contain sensitive information such as bank account numbers or PHI. If an organization decrypts traffic to those domain categories, their proxy/decryption devices may then store that sensitive information, which could be a liability if those systems are ever compromised. To avoid this, some (but not all) organizations won’t decrypt traffic to sensitive domains even if they have the means to do so.

This is all to say that when I went looking for a domain to use in my C2 infrastructure, I wanted one that would be categorized as “finance” so that it might avoid being decrypted in the imaginary organization I would be targeting.

To find my domain, I searched for “texas bank” on This showed that the “” domain had expired and was available for purchase.

I then went to NameCheap to purchase the domain. The domain was available for $8.88.

Create the Redirector Server

With the domain name purchased, I needed a new server to point the domain at. The redirector will run a web server and proxy requests to it to my C2 server and an external domain (more on that later). The redirector doesn’t need to do a whole lot. In AWS, I launched a new instance using a Ubuntu AMI.

I created a new security group in AWS for the redirector that allowed for SSH connections from my home IP address, and allowed for HTTP and HTTPS traffic from anywhere on the Internet.

Install a Web Server

After the Ubuntu instance is spun up, you can connect to it over SSH. The process to connect to this is different than how you connect to Windows AWS instances. You don’t need to decrypt a password like for Windows. Instead, you use the .pem file you created to connect to the redirector server over SSH.

ssh -i aws-ad-lab.pem ubuntu@<your IP address>

Once you are connected to the redirector, switch from the “ubuntu” user to root. You should not have to enter a password.

sudo su

Now, install your web server of choice. For this post I will use Apache, but Nginx or something like that would work just as well. After installing Apache, you will also want to use “a2enmod” to install/enable Apache modules necessary for SSL communications and proxying requests.

apt-get update -y && apt-get upgrade -y
apt-get install apache2 -y
a2enmod ssl rewrite proxy proxy_http
a2ensite default-ssl.conf
a2enmod proxy_connect
service apache2 stop
service apache2 start

The web server should be up and running, but the domain name you purchased won’t point to it yet. You will need to configure the DNS records for your domain to point to the redirector public IP address. I used NameCheap’s DNS to do this, but you could use other DNS options like DigitalOcean or whatever. I configured A records for “@” and “www” to point to my redirector IP.

Changes to the DNS records may take some time to update. Once they have been updated, you should be able to access your web server using the domain name in your browser.

Configure SSL Certificate

Right now, the redirector is configured for plaintext HTTP traffic. You could easily generate a self-signed certificate and do SSL over that, but you’d get errors about the certificate not being trusted. NameCheap provides several options for certificates that cost anywhere from $8 to $100+, but the easiest way to get a trusted certificate that will be trusted by browsers is using Let’s Encrypt.

Let’s Encrypt allows you to generate a trusted and FREE certificate for your domain. Instructions for how to do this can be found here. I’ll cover the steps in my post as well.

To begin, connect to the redirector server over SSH. Let’s Encrypt provides a tool called “certbot” to create and install the certificate. Install certbot with the following commands:

sudo apt-get update -y
sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update -y
apt-get install certbot python-certbot-apache

Certbot can then be used to generate and install the certificate for Apache. The below command will generate certificates for the “” and “” domains, and create an Apache configuration file that references the certificates.

certbot -d, --apache

After this is complete, you should see the new configuration file in the “/etc/apache/sites-enabled” directory. My configuration was called “000-default-le-ssl.conf.” Restart the Apache service, and you should be able to access the webserver on the redirector and see a valid certificate.

Domain Categorization

Now that the web server is configured, it’s time to get the domain categorized. Domain categorization is based on the content hosted at the web application at the domain. If I wanted my domain to be categorized as “finance”, I could create a phony finance looking web application. An easier way though is to use the redirector as a web proxy that forwards all requests to to a legitimate banking web applcation.

I googled “texas bank” and found the website “”, which appears to be a real bank in Texas. using web proxying, it’s possible to configure my redirector to redirect all requests to This is done by navigating to the ” /etc/apache/sites-enabled/” directory, and then editing the “000-default-le-ssl.conf” configuration file. When Apache was first installed, we used a2enmod to enable “proxy”, “proxy_http”, and “proxy_connect.” These will allow you to proxy all traffic to the redirector to a different site. To do so, the bottom of the “000-default-le-ssl.conf” should looke like this:

Now, when you access, it appear like it is hosting real content and is a fully functioning website. This is all done by proxying the web traffic to a different site.

Please note that while this looks like it is now hosting the “” web application at “”, if a user were to click on any of the links on the page, they would see the address in the URL bar change from to

With the web proxying setup, the domain can be submitted for categorization. Two URL categorization services that you can access without creating an account are Symantec (previously Blue Coat) and Palo Alto.

When I checked my domain on Symantec before doing the web proxying, it was categorized as “unavailable” since it didn’t resolve to an IP address yet. After configuring the web proxying, it then categorized as “Finance.”

Palo Alto still categorized the domain as “unknown” after the web proxying.

However, Palo Alto does allow you to submit for the site to be re-categorized with a category you provide. This can take a few days to be approved after you submit it. I didn’t submit the re-categorization request for this test because it requires an email address to be submitted and I didn’t have a burner one handy, but the request looks like this:

With the domain now categorized, your C2 traffic should now pass through an organizations web proxy without being blocked (cross fingers).

Configure Covenant Listener to use Redirector

With the redirector configured, it’s now time to create a listener in Covenant so that all traffic from a Covenant agent (grunt) passes through the redirector before hitting the C2 server.

Because I created my redirector server in the same VPC as my C2 server, my C2 server should allow for the redirector to communicate with the C2 server over TCP port 443 and private IP address. This should probably be configured differently so they are on a different VPC than the AD lab network, but it works so I am going to leave it for this test.

To use HTTPS for a listener, you need to provide Covenant with a certificate in .pfx format. Let’s Encrypt provided us a certificate in .pem format. To convert the certificate to .pkx, navigate to the directory of the Let’s Encrypt certificates and keys (/etc/letsencrypt/live/ on my system) and use openssl to convert them to certificate.pfx.

openssl pkcs12 -export -out certificate.pfx -inkey privkey.pem -in cert.pem -certfile chain.pem

You will be prompted to enter an “export password.” Remember this password as you will need it when you use the certificate in Covenant.

Now you need to get the certificate from the redirector to the Covenant C2 server. I first copied certificate.pfx to the /home/ubuntu folder and modifed its permissions.

cp certificate.pfx /home/ubuntu
chmod 666 /home/ubuntu/certificate.pfx

I then used scp on my host system to copy it from the redirector.

scp -i aws-ad-lab.pem ubuntu@ .

Connect to the C2 server over RDP, and drag and drop the file certificate to copy it.

On the C2 server, access Covenant at https://localhost:7443/. Go to listeners, and stop and delete the old listener. Then, create a new one. This time, set the “BindPort” to “443” and “UseSSL” to “True.” Set the “URL” to include your domain name, and the “ConnectAddress” to be the public IP of your redirector. Be sure to include the export password for the certificate under “SSLCertificatePassword.”

The listener should now be created and active. To test it, host a text file on the listener like you did in the previous C2 setup. This time, though, in order to access the text file from a remote host, the redirector’s Apache configuration file must be modified. Right now it proxies ALL traffic to The configuration must be changed so that that traffic to the text file, which I hosted a /test/test.txt, should be proxied to the C2 server’s IP address. The new configuration file should look like this.

Restart the Apache server, and you should be able to access the test file from wkst01.

Covenant’s grunt communicates back to the C2 server over specific endpoints at the domain you provided it. This endpoints can be found in the “listener profile” you selected for the listener. In this setup, I used the default listener profile “CustomHttpProfile.yaml.” When you click on the listener in Covenant, there will be a tab up top to view the listener profile. The listener profile page will list the Url endpoints used by C2 grunts.

Following the same procedure to make the redirector proxy traffic to the test.txt file to the C2 server, the redirector’s Apache configuration file needs to be modified to proxy traffic from “/en-us/index.html”, “/en-us/docs.html”, and “/en-us/test.html” to the C2 server. The redirector’s new Apache configuration should look like this:

After the Apache service is restarted, the redirector should proxy all Covenant C2 traffic to the C2 server, and all other traffic to

A launcher can be generated the same as before. I used a PowerShell launcher on wkst01, and successfully received a grunt connection.

I then checked the network connections on wkst01, and confirmed that it was connecting to the public address of my redirector server over HTTPS.

There we go, a successfully C2 connection over a valid, categorized domain using proxy redirection!

Next steps…

Next, I hope to go into some of the actual attacks that can be performed against my AD lab using Covenant.

Also, I believe the C2 infrastructure I described in this post violates AWS’s TOS. On a real engagement, you need to get permission from AWS to perform this kind of activity. Since this was all internal to my lab, it isn’t really an issue. However, I am tearing this all down and going forward I will be setting up my C2 to connect directly from my AD lab to the C2 server without a redirector or domain. It just makes things easier for testing.