How to Build a Command & Control Infrastructure with Digital Ocean: C2K Revamped

Lee Kagan* //

Expanding upon the previous post in this series, I decided to rewrite C2K (find it here) to change its behavior and options for the user.

In this post we will walk through the changes to C2K as well as re-deploy a demo C2 infrastructure with all the new features. It is worth noting that not everything demonstrated is automated or part of the C2K script. There are also more capabilities being added into C2K that are currently in-progress.

C2K a.k.a. Command and Control Kit, is a bash script I put together to speed up the process of repeat C2 builds and tasks. The new design allows for users to easily and quickly remove, add or edit the features they require to get the job done. Currently C2K provides the following capabilities:

  • Deploy Cobalt Strike team servers
  • Deploy Apache mod_rewrite redirectors for HTTP C2 instances
  • Add HTTPS support to HTTP C2 instances
  • Configure firewall rules for C2 traffic
  • Lockdown SSH access to C2 instances
  • Configure terminal logging
  • Configure Logwatch on C2 instances

In this post, we will use all of the above features as well as some manual additions such as:

  • Integrate Cobalt Strike beacon events into Slack
  • Integrate Digital Ocean performance alerts into Slack
  • Use Digital Ocean doctl CLI to create global infrastructure firewalls

In order to use C2K (and the manual alerting setup), there are some requirements you will need before using it:

  • Digital Ocean account
  • Digital Ocean API key
  • Cobalt Strike license
  • Slack
  • Create Slack app for incoming webhook
  • Domain and DNS management (i.e. GoDaddy)

The New C2K Walkthrough

Let’s take a look at the code and how C2K can be used.

The C2K pack contains 3 items which can pulled from GitHub:

  • – The main script to execute
  • – script from @Killswitch_GUI to setup HTTPS support
  • sshd_config – custom SSHD configuration template for locking down SSH access

NOTE: You are responsible for your own copy of Cobalt Strike. Leave the unpacked archive in the same folder as the above once you’ve downloaded everything.

Go ahead and open up and let’s take a look inside.

Everything in the script is broken down into sections, buckets and functions to allow the user to quickly and easily modify any of the content. In the above image you’ll need to set the following variables:

  • DOTOKEN – place your Digital Ocean API key between the quotes
  • NEWUSER – place a username you will be using to log into the new droplets with over SSH between the quotes

Everything for here on in is broken down by functions. This makes it very easy to add/remove/edit commands and features.

The function “func_getDependencies” is a basic update and install some requirements. In the odd event you don’t have python installed, it will add that too. ☺

The function “func_createUser” will create the new user for SSH access and add that account to the sudoers group.

The function “func_setupSSH” will make the necessary changes to setup SSH access for the new user and move the existing key already on the droplet over to that user (the existing SSH key is what you’re using to login to the new droplet over root for the first time).

The function “func_createDroplets” is where the droplet creation magic happens. It leverages the Digital Ocean API. In the above image I’ve shown how to create multiple droplets at once. If you wish to create one at a time, just remove the second and third blocks starting with curl.

You’ll need to set the “YOUR_DROPLETS_HOSTNAME” field for each droplet. You can also set the region, size and image as you require (this has only been tested on Ubuntu 16.04). Finally, you’ll need to add your SSH key fingerprint in the “YOUR_SSHKEY_FINGERPRINT” field. This can be obtained in the Digital Ocean control panel when you add your SSH key (as we’ll see later).

Because this script revolves around using Cobalt Strike, the functions in the above image are all related to it but can be modified for your preferred framework i.e. MSF or Empire.

The function “func_getCSDependencies” installs the Java requirement for Cobalt Strike. The function “func_installCobaltStrike” unpacks and runs the installer which will prompt you for your license. The function “func_getMalleable” will pull down Malleable C2 profiles into the unpacked Cobalt Strike directory. The function “func_addHTTPSSupport” will run the script.

It is important to restrict connectivity to your team servers. In the above image, there’s a simple function called “func_createFirewall” to setup what ports are accessible. This is not a rock solid firewall so it is encouraged to restrict access as needed (NOTE: we will also be looking at a global infrastructure firewall with doctl later on).

When selecting the HTTP redirector option in C2K, the function in the above image, “func_createHTTPRedirector” makes use of an excellent script courtesy of @n0pe_sled. This script will automate the process of configuring your HTTP redirection instance. It is highly encouraged to visit the authors GitHub page ( to see all the options available.

In the above example, the function will pull down the script as well as Malleable C2 profiles. The script supports using Malleable profiles for redirection although in the above example it is not used. The important fields to edit before using are the “—block_url” and “—allow_url”. Add a domain which you wish to send traffic to that should not touch your team server or does not meet the redirection criteria. Then add the C2 domain that traffic should be proxied to (this is your HTTP C2 instance).

Finally, the last function is “func_installDefensiveTools”. This function is a starting point to add some defensive measures into your C2 instances. First it installs lterm, a great utility once again from @Killswitch_GUI that records console activity and writes it out to file. It will also install Logwatch and email you reports on what has been happening on your servers. In the above image, you will need to edit the 2 fields for your email address (shown as [email protected]). You can also adjust any of the settings above for your preferred means to be notified, when, and what level of detail.

C2K Preparation

Before executing C2K, let’s prepare everything we need to begin creating the infrastructure. Here’s the plan:

  • Domain(s) – I’ll be using ilikedemos[.]com for this demonstration
  • Need to set the A records for our different hosts
  • 4 droplets – these will be our simulated C2 instances
  • Payload host – Cobalt Strike instance for hosting downloads, scripts, implants etc.
  • HTTP host – Cobalt Strike instance for receiving reverse HTTP beacons
  • HTTP redirection host – Apache mod_rewrite instance for proxying
  • HTTPS host – Cobalt Strike instance receiving reverse HTTPS beacons
  • SSH Key – will create a new SSH key and add to Digital Ocean
  • Slack channel and webhook
  • Cobalt Strike and Slack integration Aggressor script from @bluscreenofjeff (

Let’s begin.

Starting with Digital Ocean, log in to your account and we’ll obtain the API key and add an SSH key to our profile.

Click “API” at the top of the page and create a new API key if you do not already have one by clicking “Generate New Token”.

Give your token a new name. When it’s created, be sure to note down the key as it will only be displayed to you once. If you lose it, you’ll need to generate a new token.

Next, in your profiles security settings section, create a new SSH key by clicking “Add SSH Key” or note down your existing SSH keys fingerprint.

Now would be a good time to update and add your Digital Ocean API key and SSH fingerprint.

We can now run the script and create the droplets for our C2. I’m going to create 4 droplets with the following settings:

  • All will be in nyc3 for this demo
  • All will be 2gb although I recommend more for actual operations
  • Hostnames for each will be:

Select option 1 to automatically deploy the droplets you configured inside the script.

Once finished running, check your Digital Ocean droplets page and you should see the newly created droplets.

Now would be a good time to update your A records for the domain(s) you will be using with the C2 infrastructure.

Next, we need to transfer the C2K folder contents over to each machine (you actually don’t need to transfer Cobalt Strike over to the redirector). In the image below repeat the SCP process for each droplet.

Once you’re finished copying over the C2K pack to each droplet, SSH in normally as root which will use the SSH key to login.

Before running the C2K script on the droplets I like to set a root password. Because we’ll be logging in over SSH later with the new user in the sudoers group, should you want to directly elevate to root you’ll have a password to do so (although not really necessary).

Not all of the 4 droplets in this demonstration require the same selections in to be run. Here’s a breakdown of what I’ll be executing on each.

  • Payload host – Install Cobalt Strike, install logging and defensive tools.
  • HTTP host – Install Cobalt Strike, install logging and defensive tools.
  • HTTPS host – Install Cobalt Strike, install HTTPS support, install logging and defensive tools.
  • Be sure to have your A records set before running
  • Note this script will use by default the amazon.profile Malleable C2 profile with HTTPS support. Be sure to edit this or run your HTTPS team server with that profile
  • Once done stop Apache from running otherwise it will conflict with Cobalt Strike from standing up a listener.
  • HTTP redirector host – Install HTTP redirection, install logging and defensive tools.
  • Be sure to set the apache_mod_rewrite_setup flags in the script before running this option

Also make note of the settings in the sshd_config template. There’s a custom SSH port and username set that you will need to change. SSH port is up to you but be sure the NEWUSER variable in matches the AllowUser directive in the sshd_config template. Once the script completes you will have to login over SSH once you disconnect using newusername@droplet_address -p 7654 (or whatever custom port you chose).

Once the script completes with the selections mentioned above, disconnect and log back in with the new user account.

Once you’ve finished all the script options for each of your droplets, let’s add some more monitoring and alerting.

First, let’s add Digital Ocean Slack integration for droplet performance monitoring. In your Digital Ocean control panel, click “Monitoring” at the top navigation.

This should be blank to start with but also pay attention to the bottom of the above image. There’s a command we’ll need to execute on each droplet we want to monitor performance on. Before creating a new policy, execute that command (will integrate this into script soon).

Once done, click “Create alert policy”.

Select a metric to alert on such as CPU then the threshold settings you desire. Add your droplets by name or tag, then select “Connect Slack” under the alerts section. You’ll need to authenticate to your Slack account and select a channel you wish to receive alerts to. Once done, click “Create alert policy”. The images below show the result on Digital Ocean and Slack.

Great. Now we’ll integrate alerts from Cobalt Strikes beacon into the same Slack channel as well. You’ll need to create a new Slack app and note down the webhook to add into Cobalt Strike. This process can be followed along with the excellent post from @bluescreenofjeff here:

Go to your Slack accounts app page and select “Create an App”.

Give your app a name and the Slack channel you wish to receive alerts in the click “Create App”.

In the next page that will appear select “Incoming Webhooks”.

On the Webhooks page you’ll need to toggle it on in order to activate the feature.

Once enabled, towards the bottom of the page you’ll want to select and create a new Webhook. Click “Add new Webhook to Workspace” and in the popup window select the same channel (or different if you prefer) in Slack to receive the alerts to.

Once done, your new Webhook URL will be displayed. Make a note of this as you’ll need it to enter into the Aggressor script for Cobalt Strike.

Now all that’s left is to test out our C2 infrastructure and make sure it’s all working as expected.

After connecting my Cobalt Strike client to all the active team servers, I add the eventlog-to-slack.cna Aggressor script and enter the appropriate settings.

This integration can be confirmed in the appropriate Slack channel.

Next I created two listeners. One on the HTTP host which is also set to have its beacons call back to the HTTP redirector. The second, on the HTTPS listener which is straight connection back to it (no redirection).

On the payload host, I hosted a PowerShell web delivery script which stages to the HTTP host which will be proxied through the redirector.

After executing the PowerShell payload on a victim machine, everything successfully stages through the redirector and access is obtained via the HTTP host.

By tailing the Apache logs on the redirector we can also see the redirector in action.

Finally, I’m spawning a new beacon from the access we have on the HTTP host to call back to the HTTPS host.

Great. Looks like everything is now fully operational and we also have our Slack notifications of new beacons that came in.

Global Firewall

Lastly, I wanted to come back to the doctl utility mentioned at the very beginning. This is a CLI tool installed locally on your physical host (but doesn’t have to be) that allows you to access and configure nearly every option that Digital Ocean provides.

What I had in mind for this was to use the Digital Ocean firewall feature to create a firewall that restricts access to and from the entire infrastructure. One reason for this is to set up rules that allow only you and your customers for example to touch the infrastructure.

When you first run doctl you’ll need to authenticate using your API key.

After that, all the options are now available.

In the image above, you can see how with a few commands you can query various information from your Digital Ocean account.

Let’s create a firewall that we will then apply to all droplets. The idea here is to demonstrate how you can restrict traffic not only to and from your instances, but also between them should the need arise.

In the above image I’m creating a demo firewall called “c2-infra-firewall” and defining the inbound and outbound rules. For the inbound, you would want to change the to your originating IP and perhaps the IP address(es) that could originate from who you are testing.

A few other advantages of restricting traffic to such a degree would be if your target is on a different network than the blue team. Also, restricting internet noise and potential unwanted visitors from touching your C2.

Once you’ve created the firewall you can list it and its settings and start adding droplets to it globally. You’ll just need the firewall ID and droplet IDs as seen in the above image. These setting are also reflected in your Digital Ocean control panel.

Closing Thoughts and Mentions

Before wrapping up this post a few thoughts on the design above:

  • From an OPSEC perspective, hosting your entire C2 on a single provider can prove problematic should the entire range for Digital Ocean get blocked.
  • Also regarding OPSEC, having all your C2 traffic call to a single domain is not great either. Mix it up and spread it out ☺
  • The eventlog-to-slack Aggressor script may not be something you or your customers are happy with if certain and potentially sensitive information is posted to Slack. Take this into consideration.
  • There’s been some Twitter debates lately regarding attack infrastructure on cloud VPS and systems you will not actually have true control over and the ethics of this. It’s a valid point and something to consider so be sure you and your customers are aware of the how and where their data will be protected

C2K is far from a finished project. There’s many new additions I’m still working on adding such as DNS team servers and redirectors, more defensive settings and phishing instance with SMTP relay automation.

I’d like to give some special thanks to those who have authored the tools I’ve integrated into C2K as well as some people who have influenced me a lot and helpful resources:

  • @Killswitch_GUI for lterm and
  • @bluscreenofjeff for creating the Red Team Infrastructure Wiki
  • BlackHills Infosec staff for allowing me to post on their awesome blog.
  • @armitagehacker for Cobalt Strike

Thank you all so much for reading and happy hacking ☺ _________   *Lee Kagan is a guest blogger from RedBlack Security. He is an offensive security professional with almost a decade in IT and InfoSec. A penetration tester, red teamer and currently lead for RedBlack Security’s Rogue Team specializing in threat and adversary emulation in Toronto, Canada. Lee’s focus on the team and in practice is offensive infrastructure support, post-exploitation of Windows and Active Directory environments, PowerShell and C# weaponization.

Ready to learn more?

Level up your skills with affordable classes from Antisyphon!

Pay-What-You-Can Training

Available live/virtual and on-demand