Archive for the ‘Cobalt Strike’ Category


Cobalt Strike 3.5 – UNIX Post Exploitation

September 22, 2016

Cobalt Strike 3.5 is now available. This release adds an SSH client with a Beacon-like interface. This client allows you to conduct post-exploitation actions against UNIX targets from Cobalt Strike. In this post, I’ll take you through the specifics.

The SSH Client

Cobalt Strike’s SSH client is a Reflective DLL that receives tasks from and routes its output through a parent Beacon. This allows you to control UNIX targets from a compromised Windows system without interactive communication.

Use ssh [target] [user] [password] to launch an SSH session from a Beacon. You may also use ssh-key [target] [user] [/path/to/key.pem] to authenticate with a key.

The above will spawn Cobalt Strike’s SSH client and it will report any connection or authentication issues to the parent Beacon. If the connection succeeds, you will see a new session in Cobalt Strike’s display. This is an SSH session. Right-click on this session and press Interact to open the SSH console.



Cobalt Strike’s SSH sessions give you a basic set of post-exploitation features to run commands, upload/download files, and pivot.

The shell command will run the command and arguments you provide. The cd command will change the current working directory of future commands that you run. The pwd command will report the current working directory.

The upload command will upload a file to the current working directory. The download command will download a file. Files downloaded with the download command are available under View -> Downloads. You may also type downloads to see file downloads in progress. The cancel command will cancel a download that’s in progress.

SSH sessions support pivoting as well. Use the socks command to create a SOCKS server on your team server that forwards traffic through the SSH session. The rportfwd command will also create a reverse port forward that routes traffic through the SSH session and your Beacon chain.

There is one caveat to rportfwd: the rportfwd command asks the SSH daemon to bind to all interfaces. It’s quite likely the SSH daemon will override this and force the port to bind to localhost. You need to change the GatewayPorts option for the SSH daemon to yes or clientspecified.

Cobalt Strike does not support chaining through SSH sessions yet (e.g., SSH -> SSH or SSH -> Beacon). This is something I plan to investigate in the future. I’m quite interested in this feature.


Cobalt Strike’s SSH client is a Beacon-compatible agent that uses an SSH library to execute its actions. From the perspective of Cobalt Strike’s team server, there’s little difference between an SSH session and a Beacon session. This makes SSH sessions integrate with Cobalt Strike’s logging, reporting, and scripting in a natural way. Yes, SSH sessions are scriptable with Aggressor Script!

SSH sessions fire an event when a new SSH session comes in. This is your chance to respond to new sessions with automated actions.

on ssh_initial {
   if (-isadmin $1) {
      binput($1, "cat /etc/shadow (initial)");
      bshell($1, "cat /etc/shadow");

You’ll notice that I use &bshell from Aggressor Script to task the SSH session in the above example. This is possible because the SSH client expects the same task format as the Windows Beacon. SSH sessions only implement a subset of Beacon’s command set.

The ssh_alias keyword defines new commands for use within SSH sessions. These are similar to the Beacon aliases you might define with the alias keyword.

ssh_alias survey {
   bshell($1, "last -a");
   bshell($1, "uname -a");
   bshell($1, "id");

The above is a taste of what you can do with SSH sessions and Aggressor Script. I recommend consulting the Aggressor Script manual for more information.

The SSH client for post-exploitation is part of Cobalt Strike 3.5. Check out the release notes to see a full list of what’s new in Cobalt Strike 3.5. Licensed users may use the update program to get the latest. A 21-day Cobalt Strike trial is also available.


What happened to my Kill Date?

August 24, 2016

Cobalt Strike 3.4 introduced a Kill Date feature. This is a date that Cobalt Strike embeds into each Beacon stage. If a Beacon artifact is run on or after this date, it immediately exits. If a running Beacon wakes up on or after this date, it immediately exits. I don’t see kill dates as a replacement for tracking artifacts and cleaning up after an engagement. I see them as an extra piece of assurance.

To use Cobalt Strike’s kill date feature, you must specify a kill date when you start the team server. Here’s the help for the teamserver script:


Here’s an example of starting a team server with a kill date embedded in it:


You’ll notice that it is mandatory to specify a Malleable C2 profile, if you want to take advantage of kill dates. I’ve had a few folks ask if there is a way around this. The answer is no, not right now. The default profile isn’t anything special. It looks like a simple piece of malware on the wire. Specify a profile. 🙂 You’re better off for it.

I want to call your attention to one detail though. Notice that the team server acknowledges both the profile and the kill date. This is Cobalt Strike telling you that it sees these parameters and it’s using them as you asked it to.

If you do not see this acknowledgement, Cobalt Strike is not using your custom profile, and it does not have a kill date embedded into the Beacon stage.

You may wonder, how is this situation possible? If you specify the parameters correctly, why wouldn’t Cobalt Strike use them? This is a good question and it’s the real reason for this blog post.

Cobalt Strike 3.0 and 3.1 shipped with a teamserver script that passed either two or three arguments to the Cobalt Strike software. The teamserver script shipped with these versions of Cobalt Strike would not pass an arbitrary number of arguments. The update program that ships with Cobalt Strike does not update the teamserver script.

If you have a teamserver script from Cobalt Strike 3.0 or 3.1, Cobalt Strike will not use the kill date you specify or the profile you specify when a kill date is present. If this applies to you: download the trial for the latest Cobalt Strike Linux package, update it to the licensed version with the built-in update program, and you’re set again.

The teamserver script with Cobalt Strike 3.2 and later will work fine.


Cobalt Strike 3.4 – Operational Details

July 29, 2016

Cobalt Strike 3.4 is now available. This release focuses on the DNS Beacon and a few additions to Malleable C2. Here are the highlights:

New Malleable C2 Options

This release extends the Malleable C2 feature with several useful options. The dns_idle option allows you to change the IP address the DNS Beacon uses to signal that it’s idle. The default value is and this is an indicator some use to zero-in on Cobalt Strike’s DNS Beacon payload. I recommend you set this option in your Malleable C2 profiles.

This release also adds a dns_sleep option. This option forces the DNS Beacon to sleep before each of its DNS requests. This is guaranteed to make DNS data channels very painful to use! This option is now available for those of you who asked for it.

The pipename option allows you to change the name of the named pipe SMB Beacon uses for peer-to-peer communication.


DNS IPv6 AAAA Record Data Channel

The DNS Beacon received a few enhancements beyond the Malleable C2 options above. The mode dns6 command now sets your DNS Beacon to use AAAA records as a data channel. This is similar to the mode dns option, which asks Beacon to use A records as a data channel. The benefit is that the AAAA records give you more data per request.

Kill Dates

By popular request, Cobalt Strike now allows you to embed a kill date into the Beacon payload. Beacon will automatically exit, when run, on or after its kill date. Beacon also checks the kill date each time it wakes up and exits if it’s on or after the kill date.

To take advantage of this feature, simply specify a kill date when you start your Cobalt Strike team server. Your team server will propagate the specified kill date to all payload stages it generates. Here’s the format:

./teamserver [ip address] [malleable C2 profile] [YYYY-MM-DD]

Check out the release notes to see a full list of what’s new in Cobalt Strike 3.4. Licensed users may use the update program to get the latest. A 21-day Cobalt Strike trial is also available.


Why is rundll32.exe connecting to the internet?

July 22, 2016

Previously, I wrote a blog post to answer the question: why is notepad.exe connecting to the internet? This post was written in response to a generation of defenders zeroing in on the notepad.exe malware epidemic that was plaguing them. Many offensive actions require spawning a new process to inject something into. In the Metasploit Framework (and ancient versions of Cobalt Strike), notepad.exe was the default process to spawn for these actions.

Today, rundll32.exe is the process Cobalt Strike will spawn when it needs a one-off process to inject something into. I’ve had many people write and ask: “Raphael, why rundll32.exe?” Others ask, “how do I switch from rundll32.exe to something else?” This blog post aims to answer these questions.

User-driven Attacks

Several of Cobalt Strike’s user-driven attacks automatically migrate the payload stager to a new process and then run it. I do this for two reasons:

First, the user-driven attack might land code execution in an x64 process. We can’t run an x86 payload in an x64 process. The solution here is to migrate. Cobalt Strike’s Java Applet attacks and the Microsoft Office macro attacks both migrate to rundll32.exe (by default).

Cobalt Strike’s user-driven attacks migrate for another good reason. What happens if the user closes the application we used to get code execution? If our payload ran within that application, our access would go away with it. If our payload lives elsewhere, our access is safe. This is another reason Cobalt Strike’s attacks migrate.

So, why rundll32.exe? Why not something else? Honestly, it doesn’t matter what I pick. Anything I pick is now the default. Because people rarely change defaults, it will show up enough that someone will notice. The right thing here, for all parties, is to know how to change the defaults. Fortunately, this isn’t too hard to do.

Cobalt Strike does not provide a way to override the default macro attack. Fortunately, its choice of rundll32.exe is a string inside of the macro that you can edit. If this choice does not work for you, change this to another process. Many times, I have edited Cobalt Strike’s VBA macro to spawn Internet Explorer and inject my stager into it. I found this was necessary for security postures that restricted which applications could make outbound connections.

The Java Applet is also easy to fix. If you’re using the Java Signed Applet attack with Cobalt Strike, chances are you’re familiar with the Applet Kit. This is the source code to Cobalt Strike’s Java Applet attack and the scripts necessary to build it. You’ve probably downloaded this kit to sign Cobalt Strike’s Applet with your code signing certificate. If you want the Java Applet to migrate elsewhere, edit src/injector.c, change rundll32.exe to something else, and rebuild the Applet Kit. This will require that you have the mingw-w64 package installed.

Executable and DLL Artifacts

Cobalt Strike’s options to export an x64 DLL to deliver an x86 Beacon also migrate to rundll32.exe. I do this for good reason. I can’t host the x86 Beacon inside of an x64 process! Again, the answer here is to migrate and I migrate to a default: rundll32.exe.

Cobalt Strike also generates executables that respond to commands from the Windows Service Control Manager. Cobalt Strike uses these executables with its psexec command and it lets you export them as well. These service executables automatically migrate your payload or stager. Why? I do this to make the service easier to cleanup. In the case of psexec, I can’t get rid of the executable until it stops running. If the service executable didn’t migrate, Cobalt Strike’s psexec command would have to wait until your session stopped to clean up the executable it put on target. That’s no good! This is why the service executables migrate.

Fortunately, changing the rundll32.exe indicator is pretty easy to do as well. Cobalt Strike allows users to change it process to generate executables and DLLs. This is possible through the Artifact Kit. The Artifact Kit is source code to Cobalt Strike’s executable/DLL templates and it’s a script to override Cobalt Strike’s internal process to patch shellcode into these templates.

If you edit src-common/patch.c, you can change the migrate process from rundll32.exe to something else. Rebuild the artifact kit, load its script into your Cobalt Strike client, and from that point on—you’re free of rundll32.exe in your service executable and x64 DLL artifacts.

Spawning Sessions

rundll32.exe rears its ugly head in other places too. A favorite workflow in Cobalt Strike is the ability to right-click a session, select Spawn, and send a session to another listener. This command spawns a process and injects a payload stager for the chosen listener into it. I spawn a process because stagers do crash from time to time. Injecting the stager into another process protects your access from that crash.

When Beacon spawns an executable for session passing, which one does it spawn? Why our friend, rundll32.exe. Of course!

You may ask, how do I change this? There are a few answers to this question. The first answer is to reconsider your use of the spawn command. The spawn command creates a child process off of your Beacon process. This child process makes outbound network connections. If a hunt team is watching process creates and network connections, your access will stand out like a sore thumb. I recommend using the inject command to pass sessions instead.

That aside, let’s say you want to continue to use the spawn command. Your choice! Here’s how to move away from rundll32.exe: First, you may change which command Beacon spawns with the built-in spawnto command. This command will change the spawn process for that Beacon instance to something else.

You may also change the default for all of your Beacon sessions with a Malleable C2 profile. Malleable C2 is Cobalt Strike’s technology to allow you to change indicators and behaviors in the Beacon payload. It’s quite handy if you want to make Beacon look like other malware or blend-in to look like something totally innocuous. Malleable C2 has an option, spawnto, that changes this default to something else.

Post Exploitation Jobs

Let’s cover the last place rundll32.exe likes to show itself, post-exploitation jobs. Beacon is a very small payload. It’s single threaded. It’s designed to do a few very simple things. It calls home, it executes a few base things, and it monitors jobs.

Post-exploitation features such as hashdump, mimikatz, screenshots, keystroke loggers, and others run as jobs. In Beacon parlance, a job is a post-exploitation task that lives in another process. This design serves a few purposes. First, it makes it possible for you to inject a capability (e.g., the screenshot tool) into a process of your choosing. This allows you to get results from the right place without migrating your access. That’s nice! Second, some post-exploitation tasks absolutely must run from a process that matches the operating system’s architecture. This scheme allows an x86 Beacon to seamlessly run x64 post-exploitation jobs without any bother to the operator. Things just work! Third, this scheme protects your access. If, for some reason (heaven forbid!) a post-exploitation task were to crash, this scheme isolates your access from that failure.

Anyways, you have the option to inject some jobs into a process of your choosing. Others jobs just kick off a process, inject the capability, let it run, get results, and tear the process down. These jobs that kick off a process happen to spawn, our old friend, rundll32.exe.

You may ask, how do I change this? Fortunately, there’s not a lot of new advice to offer here. Post-exploitation jobs use the same spawnto process that the spawn command uses. If you edit your Malleable C2 profile to ask that Beacon spawn another placeholder, your post-exploitation jobs will use this placeholder as well.

There is one caveat here. The spawnto command only affects which x86 process the x86 Beacon kicks off. If x86 Beacon has to kick off an x64 process, it doesn’t change this. I do not have a means to change the x64 spawnto process, yet. I’ll take care of this.

And, for the sake of completeness: the spawnto command does not affect which x86 process the x64 Beacon kicks off, when it needs to run an x86 job. If x64 Beacon has to kick off an x86 process, it will use rundll32.exe. I do not have a means to change this yet either. Again, this is one of those todo items.

Update 13 December 2016: Cobalt Strike 3.6 allows you to set the x86 and x64 spawnto value via the spawnto command and Malleable C2.

You’re now empowered!

This post was a lovely stroll through the migrate and spawning behavior of Cobalt Strike 3.0 and later. There are three take-aways for this post:

1. Cobalt Strike migrates stagers and tasks to other processes. It does this a lot. Usually for good reasons!

2. The default process Cobalt Strike migrates to is rundll32.exe.

3. You have the power to change this behavior in most cases.


HOWTO: Reset Your Cobalt Strike License Key

July 15, 2016

Time to time, I hand out Cobalt Strike license keys to non-customers. Sometimes these are to support an event (e.g., the National CCDC Red Team). Other times, these license keys allow a potential customer to evaluate Cobalt Strike without the deliberate tells present in the trial.

Cobalt Strike’s license key is primarily used with the built-in update program. My server uses this key to verify that you’re still licensed to use the Cobalt Strike product and receive updates for it.

The built-in update program asks for this key once. Afterwards, it does not ask for this key again.

This presents a small problem. ☺ When you go from evaluator to customer, you’ll want to remove your evaluation key. If you don’t, Cobalt Strike will continue to use this key instead of the one tied to your license. Once that key expires, you can’t update Cobalt Strike or access the Cobalt Strike Arsenal.

With all that out of the way, let’s get to the question that prompted this post. How do you reset your Cobalt Strike License Key? Easy.

Cobalt Strike stores your license key in the .cobaltstrike.license file in your home directory. Simply remove this file and the update program will ask you for a new key when you run it next.

rm –f ~/.cobaltstrike.license

That’s it!


Who let the logs out? Woof.

June 29, 2016

Logging is an important feature in any red team operations platform. Logs serve multiple purposes. Good logs aid reporting. If an operator needs output for some action or forgot what they did and when, logs help refresh the operator’s memory. Good logs also help with ground truth. Anyone who has worked red operations long enough knows that red teams get accused of all kinds of things. Good logs help put these matters to rest. Finally, good logs help with deconfliction. You want to know which activities are attributable to your operators and which ones are not theirs. Heaven forbid an adversary is already present in your customer’s network. Deconfliction matters.

With these points in mind, I put a great deal of effort to re-design Cobalt Strike’s logging in the 3.0 release. This blog post will take you through the information you need to get the most from these changes.

Where do the logs live?

Cobalt Strike 3.0 and later log everything on the team server. This is a departure from previous releases where logs lived with the client. The advantage to this scheme is twofold: (1) Cobalt Strike logs, whether a client is connected or not, and (2) the ground truth activity for a team server lives in one place.

Cobalt Strike’s logs are in the logs/ folder co-located with your team server’s current working directory. If your team server was run from /root/cobaltstrike, then the logs are in /root/cobaltstrike/logs.

Cobalt Strike organizes all of its logs by date. In the logs/ folder you’ll see folders with a YYMMDD format. For example, the folder logs/160629/ contains the logs from June 29, 2016.

Cobalt Strike has multiple types of logs to capture the different types of activity in the tool. Let’s go through these.


Beacon Session Transcripts

Cobalt Strike logs Beacon sessions to [target]/beacon_[session ID].log within the logs folder. These logs capture everything that occurred during a Beacon session. Each item in the log includes a date and timestamp, an entry type, and the information Cobalt Strike knows about the item.


Here are the types of session events Cobalt Strike logs:

The metadata entry provides information about the session. This information is usually found at the top of a Beacon log file. Consult this entry to see who the session ran as, which process it lived in, the computer name, and IP address of the target.

The input entry indicates that a command was issued. The log includes the command, its arguments, and the operator that issued the command.

The task entry is Cobalt Strike’s acknowledgement of input. This information shows you how Cobalt Strike interpreted the command given to it. These entries make a great running narrative of what happened in a Beacon session. In fact, I use this information quite heavily in Cobalt Strike’s reports.

The checkin entry documents when Beacon called home to grab tasks that were in its queue. This is helpful if you need to approximate when a queued command was run.

The output entry is the output of a command or action taken with Beacon.

Finally, Cobalt Strike tracks indicators made by some of it commands. For example, if you upload a file, Cobalt Strike will generate the MD5 hash of the file, and store this in its data model. Cobalt Strike also tracks these indicators as indicator entries in its log file. This information is helpful if you need to quickly de-conflict whether or not a file was put on target by one of your red team members.

Beacon’s logs surround the entry type with square brackets. This makes it easy to grep for different types of log entries. For example, if you want to find all of the indicators in your logs, use grep –r “\[indicator\]”. from the logs folder.



The events.log file documents activity from Cobalt Strike’s event log. The event log is essentially an operator chat and a central place to push notices to members of your team.

Keystrokes (Session Specific)

Keystrokes captured by Beacon are stored in the [target]/keystrokes/ folder within that day’s logs folder. Cobalt Strike stores these in keystrokes_[Session ID].txt. The Session ID is the Beacon’s session ID. The contents of these files is the same information you see when you go to View -> Keystrokes in Cobalt Strike.

Phishing Information

Cobalt Strike also tracks information about each of your phishing engagements too. These are located in phishes/campaign_[unique ID].log. Each phishing salvo from Cobalt Strike is assigned a unique campaign ID and each salvo gets its own log file. This file documents meta-information about the campaign, who you sent the phish to, when, and whether or not the message was accepted by the mail server.


Screenshots (Session Specific)

Screenshots taken with Beacon are stored with the logs as well. Cobalt Strike stores these in the [target]/screenshots folder. The naming convention of these files is screen_HHMMSS_SessionID.jpg. The HHMMSS represents the time the screenshot was reported by your Beacon. The Session ID part of the filename is the Beacon session the screenshot came from.

Screenshots (Global)

Cobalt Strike has several keyboard shortcuts to take screenshots while you use Cobalt Strike. Ctrl+P takes a screenshot of the current active visualization. Ctrl+T takes a screenshot of the current tab. Ctrl+Shift+T takes a screenshot of the entire Cobalt Strike window.

Cobalt Strike pushes these screenshots to the team server and they live in the screenshots/[operator name] folder within the logs directory. The screenshots are named HHMMSS_[screenshot title].png. The HHMMSS part is the time the screenshot was taken. The title is dependent on the type of screenshot taken and where. For example, in the case of Ctrl+T, the title part of the filename is the tab’s title.

Website Hits

The weblog.log file tracks hits on Cobalt Strike’s web server. This file follows Apache’s logging conventions.

Website Keystrokes

Cobalt Strike’s Website Clone Tool has an option to log keystrokes on the cloned website. These keystrokes show up under View -> Web Log in Cobalt Strike’s user interface. The webkeystrokes.log file captures these keystrokes in a central place for review after the engagement.


The logs in Cobalt Strike 3.0 and later are a vast improvement over the tool’s previous logging implementation. The new logs make it easier to get ground truth on red team activity, to perform deconfliction, and to revisit key information from your engagement (commands, keystrokes, screenshots, output) to make better reports. I hope this post helps you get the most from this very important feature.


Talk to your children about Payload Staging

June 22, 2016

Time to time, I find myself in an email exchange about payload security and payload staging. The payload security discussion revolves around Beacon’s security features. Once it is running on target, Beacon takes steps to authenticate its controller and establish a session-specific key to decrypt tasks and encrypt output. I discuss these security features at the end of the Infrastructure lecture in Advanced Threat Tactics. Questions on this topic are usually easy to field.

Payload Staging is a different animal though. Payload Stagers are tiny programs that connect to a controller, download a payload, and run it. Payload Staging is helpful to pair large payloads (e.g., Beacon, Meterpreter, etc.) with attacks that have size constraints. The payload stagers in Cobalt Strike do not authenticate the controller or verify the payload they download. Questions on this topic usually spawn discussion.

In this post, I’ll explain why Cobalt Strike’s stagers are the way they are. I’ll also discuss ways you can adapt your use of Cobalt Strike to limit payload staging over a hostile network.

The Threat Model

People who ask questions about staging and payload security have a threat model in mind. They assume that there is an actor present in the communication path between their targets and their Cobalt Strike controller. They also assume that this actor has the ability to observe and manipulate data that traverses this communication path.

This is a fair assumption. A traceroute between a target system and an externally hosted Cobalt Strike team server will yield many systems that you and your customer do not control.

A malicious actor, present in your payload communication path, could man-in-the-middle the staging process and deliver their payload stage to your target. This would give the malicious actor access to your target. That’s no good!

A payload stager could mitigate this problem in one of two ways. The stager could authenticate the server that hosts the stage. Or, the stager might take steps to verify that the stage it receives is the one you intended to send.

Simple enough. Why don’t Cobalt Strike’s stagers authenticate their controllers or verify the payload stage after staging completes? Let’s discuss that.

Size Matters

My first excuse to deflect this discussion is size. The larger a payload stager becomes, the fewer attacks you can use it with. This limits our ability to stick security features into a payload stager.

The above statement is true, but the excuse is somewhat thin with my product. Why? Cobalt Strike isn’t an exploit development framework. Cobalt Strike does have size constrained attack vectors, but the size constraints I deal with are nothing like what you’d see in an unforgiving memory corruption exploit.

Ok, if that’s all true, then why does Cobalt Strike use small stagers with no security features? Cobalt Strike uses these stagers to stay compatible with the Metasploit Framework. Remember, until 3.0, Cobalt Strike was a collection of features built on top of the Metasploit Framework. The easiest way to make Beacon work with the Metasploit Framework’s exploits and modules was to stay compatible with the Metasploit Framework’s staging process.

Even with Cobalt Strike as a separate platform, this compatibility with the Metasploit Framework has its benefits. For example, it’s quite easy to use a Metasploit Framework exploit to deliver a Cobalt Strike Beacon payload. Just set PAYLOAD to a Meterpreter payload that uses the same stager, point LHOST/LPORT at Cobalt Strike, and fire away!

The Chicken and the Egg

You may not buy the size excuse, that’s fine. Earlier, I mentioned that the purpose of payload staging is to pair a large payload with a size-constrained attack. Let’s assume that we have a stager with amazing security features. Let’s also assume that this attack is a file that the target downloads from your controller.

To reach your target, the attack with your secure stager must travel over a potentially hostile network. If we apply the same threat model to the attack delivery process, we find ourselves in a hopeless position. The attacker might choose to replace our secure stager in the attack with another stager that acts according to their wishes. We lose anyways.

This is the chicken and the egg problem. If we can’t securely deliver the stager that securely downloads our payload, then how can we trust the stager?

Sometimes there’s a Chicken. Let’s protect the Egg.

If you’ve read this far, you might feel the discussion is getting a little academic. Sure, if an attacker is at the vantage point where they can manipulate the stager, then all bets are off. There are situations where the “chicken and the egg” assumptions don’t apply.

Many of my customers work assume breach engagements. These engagements focus on the target’s detection and response capability, not their patch management or phishing awareness. In an assume breach engagement, the red team is often given a foothold to work from. It’s quite feasible to deliver an attack package over a channel that bypasses our hostile network described above.

If the red team’s foothold was setup in a secure way AND the red team’s payload is up to the task, then we can assume the red team has a safe channel to work with. In this case, the chicken and the egg problem doesn’t apply. The open question is, if these assumptions are in play, what are the best ways to operate with less staging risk? Let’s dig into that.

HOWTO: Reduce Network Staging in Your Operations

Last week, I wrote a blog post about stageless payloads and discussed why you might find this feature valuable. I mentioned that stageless payloads are attractive when the risks of payload staging are not acceptable to your organization. Here’s why: A stageless payload artifact contains Cobalt Strike’s Beacon payload and its configuration in one file. Stageless payloads don’t use stagers. If you can securely deliver and run a stageless payload artifact on your target, you benefit from Beacon’s security features right away.


In assume breach engagements, use a stageless payload artifact to seed your foothold. Attacks -> Packages -> Windows EXE (S) exports a stageless payload artifact. Cobalt Strike has several stageless payload artifact options. You can export Beacon as an executable, a DLL, a service executable, a PowerShell script, or shellcode. One of these options is bound to work for your target. Once a stageless Beacon is on target, you have a (presumably) secure channel to work with.

Staging isn’t just initial access though. Staging is a very convenient tactic and it’s present in many post-exploitation workflows. Multiple toolsets use staging in their session passing, privilege escalation, and lateral movement workflows. With some adjustments, it’s possible to perform these actions without staging a payload over a hostile network.

Session Passing

Let’s start with session passing. This tactic is a way to use an active payload to spawn another payload. Beacon’s spawn and inject commands are designed to pass sessions via stagers. It’s possible to pass sessions in Cobalt Strike without staging. Go to Attacks -> Packages -> Windows EXE (S) and export a raw stageless payload artifact. This file is essentially a large-blob of shellcode that contains the Beacon payload. Use the shinject command in Beacon to inject this shellcode into a process and run it. You can export and use shinject with the x86 and x64 raw stageless payload output.

Privilege Escalation

What about privilege escalation? Beacon’s elevate, spawnas, and bypassuac commands target a listener. These commands do not have alternatives to work with a stageless payload artifact. How do we avoid the risks of staging an elevated payload over a hostile network? Create a listener for Cobalt Strike’s SMB Beacon payload. For actions on the local target, this payload will use a stager that sets up a listening socket bound to localhost. The Beacon, running on the target, will then connect to that stager’s listening socket, send the payload stage, and the stager will clean itself up and run the stage. The stager and the stage communicate through Beacon’s existing communication channel. If you’re worried about the risks of staging an elevated payload over a hostile network, this is one way to work. Bonus: the SMB Beacon is the preferred payload to use with Beacon’s privilege escalation features anyways.

Be aware, there is a potential race if an adversary is co-habitating with you. An adversary, on the same system, might connect to the stager socket first and elevate their payload instead of yours. This isn’t part of the original threat model that provoked this discussion. 🙂

What about privilege escalation based on misconfigurations? For example, you might find that you have an opportunity to elevate via a service with weak permissions. One way to take advantage of this is to drop a service executable to disk, reconfigure the service, and start it with your executable. How do you avoid staging in this case? Use a stageless windows service exe artifact.

Lateral Movement

How about lateral movement? You have options here too. Cobalt Strike’s psexec, psexec_psh, winrm, and wmi commands each depend on payload stagers. That said, you do not have to use this built-in automation for lateral movement. I do most of my lateral movement by exporting a stageless payload artifact, dropping it to an intermediate session, and using built-in Windows capability to copy the artifact to my target and run it. This plays very well with Cobalt Strike’s ability to steal tokens and create tokens from various types of credential material.

What are options to run a payload on a remote system? Look at PowerShell’s Invoke-Command, wmic, sc, schtasks, and at. There’s more, but this is a good starter set of options. I wrote a blog post with various lateral movement recipes a few years ago. The material is still relevant. If you use stageless payload artifacts for lateral movement, you can avoid staging a payload over a hostile network.

Update 8 December 2016

Cobalt Strike 3.5.1 added a host_stage option to Malleable C2. Set this option to false and Cobalt Strike will not host a public HTTP/HTTPS/DNS stage. This option will also remove HTTP/HTTPS/DNS stagers from Cobalt Strike’s workflows.

The Talk

Some of you will read this post and scratch your head. “What is Raphael talking about? I stage payloads all day long, and I like it”. The point of this post is twofold.

First, I hope to get you thinking about your tools, how they work, and the potential risk associated with that. This will allow you to evaluate the risk and make the best decision for your situation. You may decide that the one-off risks of payload staging are worth the benefits. That’s fine.

You may decide otherwise though. This gets to the second point. I have customers who care a great deal about this particular risk. They adjust their operations to work without it. This post is my opportunity to disseminate best practices for future and existing customers with this particular need. If this is you, I hope you found this post useful.

Epilogue: What about TLS Certificate Pinning?

This section doesn’t fit into the narrative of this post, but I field questions on this too:

Earlier, I mentioned that one way to add protection to the staging process is to authenticate the staging server. Last year, the Metasploit Framework gained an optional HTTPS stager that does this. This stager ships with the expected hash of the staging server’s SSL certificate. When the stager connects to the staging server, it checks the server’s SSL cert hash against the value it expects. If they don’t match, it doesn’t download and act on the payload. If they do, it assumes things are good. Pretty neat, right? Ignoring the chicken and the egg problem, this is a way to solve this problem for one protocol.

Occasionally, I get asked, “Raphael, why don’t you add this to Cobalt Strike?” While I think this technique is interesting, I don’t feel this is the right approach for Cobalt Strike. Here’s why:

This technique applies to only one protocol: HTTPS. The HTTPS Beacon isn’t as heavily used as other Beacon options. The HTTPS Beacon’s default self-signed certificate is likely to stick out like a sore thumb. It’s possible to bring a valid certificate into Cobalt Strike, but this is a barrier to fully benefiting from the HTTPS Beacon payload. My customers tend to rely on the HTTP Beacon much more. Thanks to Malleable C2 it’s easy to disguise your Cobalt Strike HTTP traffic to look like something innocuous. The HTTP Beacon isn’t “less secure” than the HTTPS Beacon either. After staging, Beacon’s payload security features are in effect, no matter which data transport you use. If I were to tackle the problem of secure staging, I’d rather focus on an implementation that is transport agnostic.

This verification technique relies on an API specific to WinHTTP. Windows has two APIs for easily making HTTP requests: WinHTTP and WinINet. The Beacon payload and its stagers use WinINet for communication. This is the preferred option for desktop applications. The Metasploit Framework offers the WinHTTP stager (with the verification option) and WinINet stagers with no verification built-in. The Metasploit Framework offers both options because there are certain types of proxy servers that the WinHTTP APIs don’t do well with. Consult The ins and outs of HTTP and HTTPS communications in Meterpreter and Metasploit Stagers for more on this. I don’t believe the benefits of this choose-the-right-stager-API approach outweigh the complexity it would add to Cobalt Strike. Again, this is an opinion specific to my product and user community.