One of my favorite Cobalt Strike technologies is Malleable C2. This is a domain specific language for user-defined storage-based covert communication. That’s just a fancy way of saying that you, the operator, have control over what Cobalt Strike’s Beacon looks like when it communicates with you.
When I do red team work, I see the same blue audiences again and again. If the red teams I worked with were to persist the same way or have the same indicators during each engagement, the blue audiences would quickly learn these things and cease to get training value from our activity.
There’s two ways to solve this problem. One way is to use new tools during each engagement. That means the red teams either need to buy or build new tools for each repeat encounter they expect to have. This is expensive and not tractable. The other alternative is to build hacking tools that give their users flexibility to change behavior and indicators during an engagement. This line of thought is what led to Malleable C2.
Malleable C2 Profiles
The heart of Malleable C2 is a communication profile. This profile specifies what Beacon’s communication should look like on the wire. You can do the really easy stuff, like say, “I want my User-Agent to be ___________________”. That’s a simple option.
You can also dress up a Malleable C2 transaction too. The header keyword lets you add arbitrary headers to Beacon’s HTTP client requests and server replies. The parameter keyword lets you dress up Beacon’s HTTP client requests with additional parameters too.
You can also do cooler things, like say, “I want to base64 encode Beacon’s encrypted taskings and store the result inside of an HTML comment” [havex.profile] or “I want to add the encrypted Beacon tasks to a 1×1 pixel GIF file” [webbug.profile]. This is made possible by a Malleable C2 concept that I call a data transform. A data transform is a series of transforms that you may apply to data Beacon has to send. These transforms include append this string, base64 encode the data, prepend this string, and netbios encode the data.
Malleable C2 allows you to chain these transforms together into a program. This program is interpreted to transform Beacon’s data, one instruction at a time, into a string that looks like whatever you want.
Critically, each of these data transforms is trivially reversible. If I base64 encode some data, I simply need to use a base64 decode operation to recover that data. If I append a string to Beacon’s data, I just need to remove that many characters when I receive data from a Beacon to recover the original data.
The presence of an inverse operation for each transform is the magic that allows Cobalt Strike to derive how to send AND receive data from one specification.
The last piece of Malleable C2 is the ability to define where the data you transform is stored. Each data transform ends with a statement like print, which means send this data to the other end. More interesting statements include header and parameter which let you store the transformed data into an arbitrary HTTP header or parameter. The uri-append statement appends the transformed data to the requested URI.
This gives you an additional piece of flexibility. Not only can you define how to transform data that Beacon needs to send, you get to define where in the transaction this data goes.
Virtual Machines for Malware Communication
The challenge of Malleable C2 is that a Beacon needs to both send and receive information. This means Beacon, written in C, needs to transform data and recover data from a transform. The same goes for Cobalt Strike’s Java back-end that services Beacon’s HTTP requests.
To make this work I built a compiler for the C2 profiles. This compiler does all of the things you’d expect a traditional compiler to do. It parses the profile into an abstract syntax tree, it checks for errors, and it outputs a simple set of instructions that I wrote an interpreter for.
In effect, the Beacon payload and its server have built-in virtual machines to transform strings in different ways. Instead of CPU registers or a stack, this virtual machine operates on buffers. The active buffer maps directly to a part of a communication request. If I’m sending data from Beacon, there are buffers for parameters, headers, the URI, and in the case of a POST request–the data the client wants to send. Instructions in this Malleable C2 machine language allow the profile to set which buffer is the active one and populate/transform the data in this active buffer.
Likewise, to recover data, the Malleable C2 machine has instructions to populate a buffer with data from the transaction and to conduct inverse transforms on the data.
I could have built a simple XML format or made a few options to change static strings in Beacon’s communication. I went with this approach to give my users flexibility to look like other malware or legitimate traffic with very high fidelity. This isn’t possible with a few configuration options to change static strings. It really requires the ability to rewrite how the client and server expect to send and receive data from each other.
How I use Malleable C2
You may ask, what’s the use of Malleable C2? I’ve had a prototype of this technology since early 2014. I pushed it into production in July 2014. Now, after some time with it, I can offer some use cases.
I do use Malleable C2, for its stated use case, to emulate specific actors. The Malleable C2 Github repository has several example profiles that re-create the C2 traffic of known malware. I tend to use profiles tied to known malware when I want to get caught or when I want to exercise a blue team’s ability to analyze the attack.
Just as often, I will also modify a profile to make myself look like a variant of known malware. I do this to avoid getting caught with default signatures, but to make my activity identifiable as malicious for training audiences doing traffic analysis.
When I stand up red team infrastructure, I always diversify my indicators. My long-haul persistence servers have different indicators from my staging and post-exploitation servers. If you use Cobalt Strike, I highly recommend you do this too. If one Beacon gets caught, you don’t want its traffic pattern to make it easy to identify all of your other Beacons. Malleable C2 makes it trivial to have indicator diversity with one tool.
Malleable C2 has helped defeat “blinky box” appliances as well:
One red team I worked with had to deal with a network appliance that whitelisted which sites clients could browse to. In this situation, we could use a client system to seed our access and troubleshoot our outbound communications. It was still our responsibility to figure out something that would work though. On a whim, we modified our profile’s HTTP GET and POST components to add a parameter with a whitelisted host in it:
parameter "q" "www.youtube.com";
parameter "q" "www.youtube.com";
And, it worked. We were able to get a fully-staged HTTP Beacon past the device. Apparently this vendor didn’t check whether or not we were visiting a whitelisted domain, they just cared that a whitelisted string existed in the URL.
I’ve seen several situations where a proxy server allows certain browsers out and denies other browsers the opportunity to leave the network. These situations represent the real power of Malleable C2. If some specific part of the Beacon payload is holding you back, Malleable C2 gives you the flexibility to do something about it. I consider that a huge win for empowering my end users to get the most out of the Cobalt Strike toolset.
Malleable C2 isn’t hard to learn. I recommend grabbing an example and tweaking it. You can also read the documentation to get a feel for what Malleable C2 can do.