Cobalt Strike 4.12 is now available. We are excited to introduce a new look and feel for the Cobalt Strike GUI, a REST API, User Defined Command and Control (UDC2), new process injection options, new UAC bypasses, a new BOF API BeaconDownload for in-memory buffers, and new drip loading Malleable C2 options.

Additionally, we have overhauled pivot Beacons so that they now support the novel Sleepmask introduced in 4.11, fixed the SSH Beacon for newer Mac/Linux distros, and added IPv6 support for SOCKS5.

Note: Cobalt Strike 4.12 has updated the minimum supported version of Java from Java 11 to Java 17. See the “Java Support Updated To Java 17” section for more information. 

New GUI, New Me

In this release, we have added a new modern look and feel to the Cobalt Strike client. You can now select different themes to apply to your client including Dracula, Solarized, and Monokai to name a few. Furthermore, all the Visualizations have been updated, including the Pivot Graph. This will now display the listener name for egress Beacons and type of pivot for ingress Beacons (i.e. SMB/TCP). The screenshots below show the new look and feel in action:

Fig 1: An image carousel showing different themes for Cobalt Strike 4.12

Do Beacons Dream of Electric Sheep?

One of the most important questions facing the security industry today is the use of advanced machine learning models in offensive security and the impact it will have on our defensive thinking. 

There is inevitably a lot of noise in this space, but there are great examples of cutting-edge research emerging. For example, Outflank’s Kyle Avery has published research on using LLMs to generate Cobalt Strike shellcode loaders and to discover trapped COM objects capable of lateral movement. Additionally, the Cobalt Strike Team has released research on utilising ML techniques to aid post exploitation. Furthermore, tools such as Nemesis are already applying data science techniques to aid operator workflows. 

It is worth reiterating that one of the guiding principles of Cobalt Strike’s product philosophy is to aspire to act as a foundation for modern offensive security research and to explore the left and right bounds of our defensive ideas and strategies. We want to support and enable all red team operators to become security researchers and active participants in the security conversation. Therefore, to ensure that Cobalt Strike enables advanced offensive research in the future for areas such as ML/LLMs, we have released a REST API in 4.12 (NB this is in beta for the initial release and we will release a blog post in the next few days going into more detail on the design considerations). 

However, the REST API has benefits far beyond simply enabling offensive research:

  • It makes it possible to script Cobalt Strike with any language for the first time
  • Enables advanced automation
  • Eases operator workflows with server-side storage
  • Starts to enable the development of custom Cobalt Strike clients

Due to the size and scope of the REST API we will release a separate blog post outlining its motivations, design, and how to get started with it in the coming days. However, to demonstrate its power, the demo below shows a Cobalt Strike MCP Server for Anthropic’s Claude

Video 1: A PoC MCP Server for Cobalt Strike

Note: We will release our MCP code demonstrated above in the upcoming weeks.

The REST API documentation can be found here and contains instructions on how to start the REST API server and a list of the available endpoints so you can start playing with it straight away.

User Defined Command and Control (UDC2)

Many on the Cobalt Strike Team remember the release of extc2 and early attempts to pivot Beacon over increasingly esoteric C2 channels. This ushered in a new era of tradecraft for custom egress and P2P channels which highlighted many weaknesses in security controls around network ingress and egress filtering. Moreover, many of these techniques are still actively being used by threat actors today.

However, while still powerful, extc2 has some drawbacks. In particular, its reliance on named pipes to relay frames from an SMB Beacon can make it hard to use operationally. UDC2 addresses these issues by enabling Cobalt Strike users to develop custom C2 channels as BOFs. The UDC2 BOF is patched in on payload creation and is invoked by Beacon to proxy out all its traffic over the custom channel. This makes it possible to combine custom C2 channels with custom UDRLs/transformations

The UDC2 BOF is complemented by a UDC2 server (i.e. a Python script running in the attacker infrastructure) to relay traffic to the UDC2 listener. The high-level architecture is illustrated below: 

Fig 2: The high-level architecture of UDC2. The UDC2 BOF acts as the ‘client’ and proxies Beacon’s comms over a custom channel to the UDC2 server. The UDC2 server then relays these frames to the UDC2 listener.

The video below shows UDC2 in action, demonstrating an ICMP egress channel:

Video 2: User Defined Command and Control (UDC2)

As highlighted in this video, you can ‘pin’ specific BOFs to a given UDC2 listener which gives a native feel to exported payloads for custom C2 channels. 

Furthermore, to aid development of UDC2 BOFs, we have released UDC2-VS. This contains a basic UDC2 TCP implementation demonstrating UDC2’s software contract and can be used to rapidly develop custom C2 channels. For more information on how UDC2 works you can check the documentation here or look at the readme in UDC2-VS.

Lastly, we have also open sourced the ICMP UDC2 channel demonstrated above. The repository contains a quick start guide on how to get up and running with the ICMP UDC2 channel in Cobalt Strike straight away. 

Process Injection Overhaul

This release also includes new process injection options. These process injection techniques are implemented as BOFs and use the process inject kit under the hood. These are available via the new GUI option, Advanced Config->Process Injection.  They support both explicit injection (i.e. inject into a specified process) and fork/run injection (i.e. spawn a process and inject into it). The new techniques added are: 

  • RtlCloneUserProcess – This is based on DirtyVanity and leverages cloned processes to break up the typical allocate/write/execute injection primitives used by EDRs to detect process injection.
  • TpDirect– Based on the work of SafeBreach Labs, this technique manipulates a target process’s TP_DIRECT structure to trigger remote thread creation.
  • TpStartRoutineStub – Also based on the same SafeBreach Labs research referenced above, this technique manipulates a target process’s thread pool to trigger remote thread creation.
  • EarlyCascade (Fork/Run only) – This is based on Outflank’s research and manipulates process initialization routines to redirect code execution to an injected payload.

Additionally, Cobalt Strike users can add their own process injection techniques to the GUI. Two new Aggressor hooks, PROCESS_INJECT_EXPLICIT_USER/PROCESS_INJECT_SPAWN_USER have been added which enable adding custom process injection BOFs to the Advanced Config->Process Injection menu.  
 
A short .cna snippet for adding a custom technique to the explicit process injection GUI option can be found below:

set PROCESS_INJECT_EXPLICIT_USER { 
     local('%explicit_injections'); 
     %explicit_injections["MyFavoriteExplicitInjection-x64"] = "/path/to/my/bof.x64.o"; 
     return %explicit_injections; 
}

Loading the script above will make the new option available from the Process Injection dialog: 

Fig 3: A screenshot of the new Process Injection GUI with a custom technique, MyFavoriteExplicitInjection-x64, added.

The demo below shows the new process injection options in action:

Video 3: Process Injection Overhaul

UAC Bypass Refresh

In addition to the process injection updates, we wanted to refresh Cobalt Strike’s out-the-box UAC bypass options. Cobalt Strike 4.12 adds two new working UAC bypasses (compatible with Win10 – Win11 24H2). The two techniques added are: 

  • uac-rpc-dom – This is based on James Forshaw’s AppInfo ALPC UAC bypass (#59 in UACME).  This is supported by both the elevate and runasadmin commands.
  • uac-cmlua – This is based on Oddvar Moe’s UAC bypass using the ICMLuaUtil elevated COM interface (#41 in UACME). This is supported by the runasadmin command only. 

The video below shows them in action:

Video 4: New UAC Bypass Options

BeaconDownload

Beacon’s download command only supports retrieving files from disk. This can be an issue when trying to dump and exfiltrate credentials (or process memory) as writing to disk first is an unnecessary IOC and can result in an increased risk of detection. This has led to many Cobalt Strike users using undocumented functionality to get round this limitation.

To solve this problem, we have added a new BOF APIBeaconDownload. This opens up Beacon’s native download functionality to support the downloading of in-memory buffers. This approach means that a BOF can ‘offload’ the download to Beacon and carry on executing as normal. In-memory downloads behave the same way as normal file downloads and can be cancelled via the Beacon console.

Note: BeaconDownload currently supports a max download size of 2GB. 

Sleepmask Updates

As part of the Cobalt Strike 4.11 release, we added a new default evasive Sleepmask for HTTP(S)/DNS Beacons and mentioned that we were overhauling the pivot Beacon Sleepmask (i.e. for SMB and TCP Beacons). This work has now been completed as part of the 4.12 release and pivot Beacons will now use the same default evasive Sleepmask released in 4.11.

Prior to this release, the Sleepmask for pivot Beacons was complex; we needed to pass additional information to the Sleepmask such as the action being performed (accept a socket? connect to a pipe?) and any additional arguments needed for those calls. This led to bloated code and made customisation unnecessarily complicated.

In 4.12, we have converted all pivot channels (SMB/TCP) to use asynchronous communication. The consequence of this change is that a ‘sleep’ for pivot Beacons now simply consists of a call to WaitForSingleObject on an I/O event handle (i.e. analogous to Sleep for HTTP(S)/DNS Beacons).  Once there is new data on the pipe/socket, the WaitForSingleObject call will return and Beacon will continue executing as normal. 

This greatly simplifies Sleepmask development, however these changes have necessitated breaking the Sleepmask entrypoint. This is because the original purpose of SLEEPMASK_INFO was to pass information related to pivot beacons (along with Beacon’s masking info). This change means this structure (and the code acting on it) was no longer required. The entry point is now simply:

void sleep_mask(PBEACON_INFO info, PFUNCTION_CALL functionCall) {
        /* invoke beacon gate */
        BeaconGateWrapper(info, functionCall);
}

Where info contains the information required to mask Beacon and the functionCall contains the target function to execute (i.e. Sleep for HTTP(S)/DNS Beacons / WaitForSingleObject for pivot Beacons).

Furthermore, there are multiple open source UDRLs that utilise an IAT hook on Sleep to perform sleep obfuscation. This change now makes it possible to use the same technique to obfuscate pivot Beacons by placing an IAT hook on WaitForSingleObject as well.

We understand a breaking change can be frustrating in a minor release but on balance we thought the benefits from cleaning up the Sleepmask interface and greatly simplifying it outweighed waiting for a major release.

Note: Both the Sleepmask Kit and Sleepmask-vs have been updated to support this breaking change. You will need to migrate any custom Sleepmasks to use this new entry point (and the drip loading change explained below) for them to be compatible with 4.12.

Drip Loading

One approach EDRs can take to detect process injection is through correlating different events for common injection primitives. For example, a very simple flow would involve allocating a large chunk of memory, copying over a payload, and creating a new thread at the start address. Correlating these events over a set period can produce high fidelity detection logic.

One way to subvert event-driven detection is to break up specific primitives and introduce delays between them. For example, drip loading writes a payload in small individual chunks and sleeps briefly between writes. By doing so, it can help break event correlation.

In Cobalt Strike 4.12, we have added support for drip loading during both reflective loading and process injection. You can configure drip loading in the loader via the new Malleable C2 options for the stage block as shown below:

stage {
      set rdll_use_driploading “true”; 
      set rdll_dripload_delay “100”;   //adds a further delay if desired
}

Similarly, drip loading can be configured for process injection via the new Malleable C2 options for the process-inject block as shown below:

process-inject {
        set use_driploading “true”;
        set dripload_delay “100”;    //adds a further delay if desired
}

Note: The drip loader changes have required an update to the ALLOCATED_MEMORY_* structures found in beacon.h. This is because if Beacon lives in drip loaded memory the Sleepmask needs to handle it accordingly. Existing UDRLs will still work, however if you update the USER_DATA.version to 4.12 (0x00041200) you will also need to update the ALLOCATED_MEMORY structures. For Sleepmasks, as previously discussed, we have simplified the entry point so all existing Sleepmasks will need to be updated to support this and additionally will also need to include the new ALLOCATED_MEMORY structures found in beacon.h. Sleepmask-VS contains all the required changes and so is a good template to aid migration.

Java Support Updated To Java 17

We have updated the minimum supported version of Java from Java 11 to Java 17. You will get an error if you attempt to run Cobalt Strike 4.12 with an older version of Java. 

To avoid any issues, please make sure that the version of Java in your environment is at least Java 17 before downloading and running Cobalt Strike 4.12. For more guidance, see the Cobalt Strike installation guide

Also note that the TLS certificates used by our downloads infrastructure have been recently updated as they were due to expire on December 4, 2025. You will need to download and extract the distribution package for your platform to get the latest version of the update program (20251120) in order to run warning-free updates. 

Additional Updates

This release also contains a number of additional QoL updates, including:

  • Prior to 4.12, the SSH Beacon was broken for newer Mac/Linux distros. This has now been fixed.
  • To support the development of tools such as Nemesis, we’ve improved our logging capabilities. Historically, Cobalt Strike did not provide a mapping between a given command and its output, which made integration into tools like Nemesis difficult. In Cobalt Strike 4.12, all commands are now assigned a task_id which is mapped to the specific output of that command. An example of this from the logs is shown below:
11/21 10:49:49 UTC [input] <wb> <task 1cd089c04c42ce78> getuid 
11/21 10:49:50 UTC [task] <wb> <task 1cd089c04c42ce78> Tasked beacon to get userid 
11/21 10:49:54 UTC [checkin] host called home, sent: 16 bytes 
11/21 10:49:54 UTC [output] <task 1cd089c04c42ce78>  
You are DESKTOP-GM7B2QP\wb
  • Additionally, Cobalt Strike’s logs now contain all actions performed from the file and process browser thus enabling searching for any file-listing seen during an operation.
  • Beacon’s SOCKS5 proxy now supports IPv6 (TCP).
  • Beacon’s dynamic function resolution for BOFs is now unlimited (it was previously capped at 128).
  • We have added a beacon_info command (this is similar to the cs_beacon_info BOF found here) which will display Beacon’s in-memory location and heap allocations. This makes it much quicker to sanity check your Beacon’s in-memory OPSEC.
  • UDRL-VS now contains a GUI element which makes it much simpler to apply UDRLs to exported payloads. This update has added udrl-vs.cna to the project folder and consolidated the existing .cna scripts into the ./sleep directory, so that users can easily call the sleep library functions (i.e. RC4, base64) when developing custom loaders. The GUI makes it possible to select either a Beacon Loader or a Postex Loader from the drop down and save the configuration so that it persists across restarts. In addition, “Export Debug Beacon” makes it trivial to export a “Debug Beacon” (i.e. a Beacon without a reflective loader). 
Fig 4: A screenshot showing the new UDRL-VS GUI, which makes it much easier to apply custom UDRLs to exported payloads.

Lastly, we now have a feedback form where you can directly submit feedback on Cobalt Strike. You can find a link to the form on our support page under the “Support” header. You can also access this form directly from your Cobalt Strike client via Help->Support

To see a full list of what’s new in Cobalt Strike 4.12, please check out the release notes.

To purchase Cobalt Strike or learn more, please contact us.