Cobalt Strike is a commercial adversary simulation software that is marketed to red teams but is also stolen and actively used by a wide range of threat actors from ransomware operators to espionage-focused Advanced Persistent Threats (APTs). Many network defenders have seen Cobalt Strike payloads used in intrusions, but for those who have not had the opportunity to use Cobalt Strike as an operator, it can be challenging to understand the many components and features included in this framework.
In this blog post, we will walk through important definitions and concepts to help defenders understand Cobalt Strike and, hopefully, identify new ways to hunt for, respond to, and attribute malicious actors using this tool.
Cobalt Strike is the command and control (C2) application itself. This has two primary components: the team server and the client. These are both contained in the same Java executable (JAR file) and the only difference is what arguments an operator uses to execute it.
Loaders are not BEACON. BEACON is the backdoor itself and is typically executed with some other loader, whether it is the staged or full backdoor. Cobalt Strike does come with default loaders, but operators can also create their own using PowerShell, .NET, C++, GoLang, or really anything capable of running shellcode.
Listeners are the Cobalt Strike component that payloads, such as BEACON, use to connect to a team server. Cobalt Strike supports several protocols and supports a wide range of modifications within each listener type. Some changes to a listener require a "listener restart" and generating a new payload. Some changes require a full team server restart.
Arsenal Kits are available for download, with a valid license, and for use with licensed (or cracked) installations only. Arsenal kits are sometimes distributed with cracked copies of Cobalt Strike. The full list of kits (as of October 2021) is:
Malleable Profile is the final part of Arsenal Kit, and it allows operators to extensively modify how their Cobalt Strike installation works. It is the most common way operators customize Cobalt Strike and has thus been heavily documented.
Aggressor Scripts are macros that operators can write and load in their client to streamline their workflow. These are loaded and executed within the client context and don't create new BEACON functionality, so much as automate existing commands. They are written in a Perl-based language called "Sleep" which Raphael Mudge (the creator of Cobalt Strike) wrote. For an example, check out the "An Operator's View" section.
Beacon Object Files (BOFs) are a fairly recent Cobalt Strike feature that allows operators to extend BEACON post-exploitation functionality. BOFs are compiled C programs that are executed in memory on a targeted host. In contrast to Aggressor Scripts, BOFs are loaded within a BEACON session and can create new BEACON capabilities. Additionally, compared to other BEACON post-exploitation commands like execute-assembly, BOFs are relatively stealthy as they run within a BEACON session and do not require a process creation or injection.
An operator accessing a team server through the Cobalt Strike client would see a view like the following. The top pane shows a list of active beacon sessions with basic metadata including the current user, process ID, internal and external IP addresses, and the last time the host checked in with the team server. The bottom pane includes a tab for each session where operators can send commands to the victim hosts and see a log of past commands and output. The client interface also allows operators to build payloads, execute plugins, and generate reports.
Within the client, operators can import Aggressor Scripts to customize their commands, menu options, and interface. Aggressor Scripts vary in complexity, from adding a new menu shortcut to chaining multiple attack steps. The following is an excerpt from credpocalypse.cna, an Aggressor Script that checks active beacon sessions on a schedule and runs Mimikatz, an open-source credential dumper, if a new user logs in.
Beacon Object Files are single file C programs that are run within a BEACON session. BOFs are expected to be small and run for a short time. Since BEACON sessions are single threaded, BOFs will block any other BEACON commands while they are executing. The following is an example from the Cobalt Strike documentation that uses Dynamic Function Resolution to look up the current domain.
Earlier, I mentioned there are "two types of BEACON", one of them being a stager. Operators can have stagers for multiple listener types (e.g. a DNS stager, an SMB stager, an HTTPS stager). In those cases, when the stager shellcode is executed, it will pull the final BEACON payload over the relevant protocol and execute it, establishing a connection using the defined listener method.
An important note for defenders is that, by default, defenders can download a Cobalt Strike HTTP/S stager payload from a team server even if the operator is not using staged payloads in their operations. This will allow defenders to 1. confirm something is hosting a team server with a listener on that port and 2. extract additional configuration artifacts from the payload.
This works because Cobalt Strike was designed to be compatible with Metasploit's Meterpreter payload. Metasploit (and thus Cobalt Strike) will serve an HTTPS stager when a valid URL request is received. A valid URL is any 4-character alphanumeric value with a valid 8 bit checksum calculated by adding the ASCII values of the 4 characters.
Operators can prevent defenders from retrieving stagers by setting the host_stage Malleable Profile value to "false". More commonly, they may use reverse proxies to filter out unwanted traffic like stager requests. As a protection feature, Cobalt Strike will ignore web requests with blacklisted User-Agents, such as curl or wget. Starting in Cobalt Strike 4.4, operators can also whitelist user agents with the .http-config.allow_useragents Malleable Profile option. These caveats are important to remember, since a team server may not always function as expected by scanners that automate stager requests.
As an operational security note, operators can also detect any web request to a team server, as it will be visible to the operator in their logs. They will also be able to see in the "Web Log" view if a stager has been pulled, along with all HTTP request details like source IP.
Differentiating cracked versions of Cobalt Strike from legitimately licensed versions can be difficult. If the watermark was statically defined as part of the cracking process, it may be possible to tie that to a shared/distributed copy. Some cracked copies of Cobalt Strike also contain backdoors to provide third-party access to a team server. In these cases, malware analysts may be able to identify illegitimate copies through static analysis.
Instead of having beacons connect directly to a team server, operators will sometimes use a redirector (or several) that accepts connections and forwards them to the team server. This has several advantages for operators, including being able to:
Operators can also use redirectors to filter out "suspicious" traffic, like scanners or hunting tools, to protect their team server, however there are typically still easy wins to track down team servers and redirectors. See the "Hunting for Team Servers" section for more details.
Sometimes "redirectors" are as simple as a cloud instance with an nginx proxy, but another highly effective redirector method is "domain fronting". Domain fronting is a technique by which an operator may hide the true destination of a network connection by redirecting it through the infrastructure of a Content Delivery Network (CDN). The technique was first documented as a means of bypassing internet censorship and has also been used by threat actors, such as APT 29, to disguise C2 traffic.
There are multiple public guides to test if a domain is frontable. This repo also includes a pre-compiled list of frontable domains by CDN provider. Please note, public lists may be out of date and manual validation will likely still be necessary.
Another way operators can establish connections is by chaining beacons. Once an operator has a single compromised system, for example beaconing back to an HTTPS listener, they can pivot internally to other systems.
The most common reason an operator will chain beacons is to bypass network segmentation and restrictions. If they target a server that doesn't have outbound internet access, they can proxy their connection through another beacon with network connectivity to the targeted system and receive the callback on their team server. If the operator loses access to the parent system, they will also lose access to chained beacons.
SMB listeners and SMB staged beacons were the original method for chaining. Cobalt Strike now also supports a raw TCP listener. In environments where the SMB stager is detected (increasingly common for Endpoint Detection and Response products), an operator can use a raw TCP chain over port 445. This will allow them to still leverage the fact that SMB is rarely blocked between internal hosts but avoid using the more heavily signatured SMB listener.
Cobalt Strike logs are invaluable for understanding the activities conducted using a team server. Defenders may not frequently have access to this log data, but in the event that logs are available, it is useful to understand what data can be extracted from them.
Cobalt Strike stores logs in two primary formats: full, plaintext beacon logs and Java serialized bins. These are stored in the team server working directory and duplicated in client working directories when a client is connected to a team server. They are also updated when items change, such as new credentials being captured.
c80f0f1006