h1

Broken Promises and Malleable C2 Profiles

June 4, 2018

Red Team infrastructure is a detail-heavy subject. Take the case of domain fronting through a CDN like CloudFront. You have to setup the CloudFront distribution, have a valid SSL configuration, and configure your profile properly. If any of these items is wrong, your C2 will not work.

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…

One of my favored ways to quickly setup an SSL-enabled Cobalt Strike is with Alex Rymdeko-harvey‘s HTTPsC2DoneRight.sh script. This script asks a few questions, requests a LetsEncrypt certificate, and sets up a modified Malleable C2 profile that uses this certificate.

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:

http-get {

    set uri "/s/ref=nb_sb_noss_1/167-3294888-0262949/field-keywords=books";

    client {

        header "Accept" "*/*";

        metadata {
            base64;
            prepend "session-token=";
            prepend "skin=noskin;";
            append "csm-hit=s-24KU11BB82RZSYGJ3BDK|1419899012996";
            header "Cookie";
        }
    }

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.

http-get {

    set uri "/s/ref=nb_sb_noss_1/167-3294888-0262949/field-keywords=books";

    client {

        header "Accept" "*/*";

        metadata {
            base64;
            prepend "session-token=";
            append "csm-hit=s-24KU11BB82RZSYGJ3BDK|1419899012996";
            append "; skin=noskin";
            header "Cookie";
        }
    }

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.

h1

PowerShell Shellcode Injection on Win 10 (v1803)

May 24, 2018

Cobalt Strike’s process to inject shellcode, via PowerShell, does not work with the latest Windows 10 update (v1803). While it’s possible to work without this capability, a lot of CS automation uses PowerShell.

I’ve pushed an out-of-band update to Cobalt Strike 3.11 with a fix for this issue.

What happened?

The PowerShell shellcode injection scripts in Cobalt Strike use PowerShell internal methods that map directly to GetProcAddress and GetModuleHandle. The latest PowerShell build (included with the latest Windows 10) includes a second GetProcAddress mapping. This made my ask for GetProcAddress ambiguous. The fix? Refresh the PowerShell scripts to ask for a GetProcAddress binding with a specific signature.

Get the latest…

Use the built-in update program to get the latest. This out-of-band update includes a few other fixes and improvements as well. Check out the release notes for the full list.

h1

Fighting the Toolset

April 23, 2018

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.

 

h1

Cobalt Strike 3.11 – The snake that eats its tail

April 9, 2018

Cobalt Strike 3.11 is now available. This release adds to Cobalt Strike’s in-memory threat emulation and evasion capabilities, adds a means to run .NET executable assemblies without touching disk, and implements the Token Duplication UAC bypass attack.

In-Memory Threat Emulation

One of the things that makes Cobalt Strike different is its ability to emulate multiple toolsets with one agent and one platform. Malleable C2 (2014) was the start of this. Malleable C2 focused on wire indicators because that’s what defenders could most easily observe. Today, wire indicators have their place, but defenders are just as likely to rip a DLL from memory to extract indicators and understand what they’re up against.

Cobalt Strike 3.7 introduced Malleable PE to give Beacon indicator flexibility in-memory. Cobalt Strike 3.11 takes this further.

1. Malleable C2 profiles now have the ability to specify the checksum, entry point, exported DLL name, and rich_header of the Beacon DLL.

2. This release also adds a peclone utility to Cobalt Strike’s Linux package. The peclone utility parses a DLL and reports a ready-to-use Malleable C2 stage block. This allows red teams to quickly extract and apply indicators from a malicious executable or DLL to Cobalt Strike’s Beacon.

3. The stomppe option controls whether or not Beacon’s loader stomps the MZ, PE, and e_lfanew values after loading. This option controls a common in-memory evasion tactic. Set this option to false and Beacon becomes a more obvious in-memory target.

4. Of course, flexible indicators have little utility without ground truth to give to the blue team. The Indicators of Compromise report in Cobalt Strike 3.11 now includes more information about the profiles used during the engagement. Each profile is presented as a unique “malware sample” with a summary of PE headers, contacted hosts, an HTTP traffic sample, and interesting strings.

Here’s the IOCs report with the HaveX Malleable C2 profile loaded:

In-Memory Evasions

February 2018’s In-memory Evasion course discusses heuristics to find injected DLLs in memory, explains why these heuristics work, and offers strategies to push back on these defenses. Cobalt Strike 3.11 adds more options to challenge and train defenders that use memory hunting techniques.

Less DLL, Please

One way to avoid detection as a memory injected DLL is to not look like an injected DLL at all (go figure). Cobalt Strike’s existing Malleable PE obfuscate option provides some help here. It masks Beacon’s import table and other fields in Beacon’s DLL. Cobalt Strike 3.11 takes this to the next level. Now, when obfuscate is set to true, Beacon’s Reflective Loader will situate Beacon in its new memory without bringing over any of its DLL headers.

Of course, the above raises a problem. It’s nice that the final Beacon DLL is better disguised. What about the memory that contains Beacon and its self-bootstrapping Reflective Loader? That package still has the MZ, PE, and e_lfanew values.

Set the cleanup option to true. This hint asks Beacon to release the memory associated with its loader. When this operation succeeds, your Beacon will live in-memory without the package that put it there.

Together, obfuscate and cleanup allow Beacon to live in-memory without content that screams memory-injected DLL.

Module Stomping

The above does raise another problem. What about the permissions of that memory? We still have pages with execute permissions that are not tied to a loaded module. These permissions exist in legitimate applications, but these properties are a warm flame that attracts the hunters from their cyber blinds.

Cobalt Strike 3.11 also adds module stomping to Beacon’s Reflective Loader. When enabled, Beacon’s loader will shun VirtualAlloc and instead load a DLL into the current process and overwrite its memory.

Set module_x86 to a favorite x86 DLL to module stomp with the x86 Beacon. The module_x64 option enables this for the x64 Beacon.

While this is a powerful feature, caveats apply! If the library you load is not large enough to host Beacon, you will crash Beacon’s process. If the current process loads the same library later (for whatever reason), you will crash Beacon’s process. Choose carefully.

In-memory .NET Assembly Execution

In Modern Defenses and YOU!, I advised that operators who depend on PowerShell should brush up on working without it. I also advised that payload developers, myself included, would do well to embrace the use of .NET assemblies in their platforms.

Cobalt Strike 3.11’s execute-assembly command makes good on this. This command accepts a path to a local executable assembly and runs it on the target in a temporary process. This temporary process benefits from all of your session prepping steps (e.g., ppid, spawnto, etc.). You may pass arbitrary arguments, quoted or not, to this program as if you ran it from a command shell. Scripters may build on execute-assembly with &bexecute_assembly.

This video demonstrates the Internal Monologue attack with help from execute-assembly:

Token Duplication UAC Bypass

But wait, there’s more! Cobalt Strike 3.11 adds a module that implements the Token Duplication UAC Bypass discovered by James Forshaw and originally weaponized by Ruben Boonen.

This UAC loophole allows a non-elevated process to use a token, stolen from an elevated process, to launch an elevated process of the attacker’s choosing. This loophole requires the attacker to remove several rights assigned to the elevated token. The abilities of your new session will reflect these restricted rights (e.g., you can’t interact with processes outside of your current desktop session).

This attack can bypass Always Notify. This requires that an elevated process is already running in the current desktop (as the same user). This attack also works on Windows 7 and later.

Use elevate uac-token-duplication [listener] to bypass UAC and get a session. This module does run a PowerShell one-liner to run a payload stager. Optionally, use runasadmin [command] [arguments] to bypass UAC and run an arbitrary command in an elevated context. The runasadmin command does not use PowerShell.

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

h1

Beware of Slow Downloads

March 9, 2018

I often receive emails that ask about slow file downloads with the Beacon payload. Here are the symptoms:

  • It takes multiple hours to grab a few megabytes
  • The sleep time makes no difference
  • File uploads are fast and not affected by this “slowness”

When I get these emails, I usually ask the user about their Malleable C2 profile. Malleable C2 is a technology to change the network and memory indicators for Cobalt Strike’s Beacon payload. In some cases, it can alter the tool’s behavior too.

I sometimes get a reply that the operator is using a custom profile derived from one of the Malleable C2 profiles on my Github repository. Inevitably, I’ll learn that the base profile is a profile that uses HTTP GET requests to download tasks from AND send data back to Cobalt Strike’s team server.

Cobalt Strike’s Beacon payload downloads tasks from its team server via an HTTP GET (or POST) request. The payload limits itself to 1MB of encrypted data per request. This is enough to download most task packages in one request.

By default, Cobalt Strike’s Beacon payload sends data back to Cobalt Strike’s team server with an HTTP POST request. In this default, the Beacon payload embeds its encrypted data into the body of the POST request. Here, the limit is again, 1MB. If you’re downloading a file, Beacon will deliver it in 512KB pieces. This 1MB limit is enough to send a 512KB file piece and some output in one HTTP POST request.

The default is what most Cobalt Strike users are used to and it’s the behavior most Cobalt Strike users expect when they use the HTTP and HTTPS Beacon payloads.

Cobalt Strike 3.6 extended Malleable C2 to allow operators to change where, in the HTTP request, Beacon embeds data it sends back to the team server. The default is still to embed data into the body of an HTTP POST request. But, you also have the flexibility to embed Beacon’s data into the URI, an HTTP header, or a URI parameter. You can also change the HTTP verb associated with this request too. This is amazing flexibility to put into an operator’s hands.

The above flexibility has consequences though. I can stick 1MB of data into the body of an HTTP POST request, no problem. I can’t stick 1MB of data into a URI, an HTTP header, or a URI parameter. That won’t work. What does Cobalt Strike’s Beacon do in these situations? Beacon chunks its output.

The chunker will divide any data, destined for the team server, into ~100 byte chunks. Each piece is sent back to the team server in its own HTTP request. This is where the behavior change comes.

I can send a 512KB file piece in the body of one HTTP POST request. That same file piece requires over 5,240 HTTP requests when divided into 100 byte chunks. Beacon does not make these HTTP requests in parallel. Rather, it makes one request, and waits for the response. It then makes the second request and waits for its response. This happens until all needed HTTP requests are made. The latency associated with each request is the thing that affects your download speed.

If you’ve seen this behavior in your use of Cobalt Strike, I hope this blog post helps clarify why you’re seeing it.

h1

In-Memory Evasion

February 8, 2018

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.

h1

Cobalt Strike 3.10 – Хакер vs. 肉雞

December 11, 2017

Cobalt Strike 3.10 is now available. This release adds Unicode support to the Beacon payload, introduces a built-in report based on MITRE’s ATT&CK matrix, and performs endodontics on the Beacon payload.

A Strategy for Unicode

One of Cobalt Strike’s limitations is its ham-fisted handling of text. Cobalt Strike treats everything sent to and received from Beacon as binary data. This creates headaches for Cobalt Strike users that come across non-ASCII characters in usernames, passwords, file names and other data.

Cobalt Strike 3.10 addresses this problem. Beacon now encodes text input and decodes text output with a character encoding appropriate to the target and situation.

The end result is on systems with a Chinese locale, Cobalt Strike will display Chinese output and accept Chinese input. On systems with a Japanese locale, Cobalt Strike will display Japanese output and accept Japanese input. The same goes for other languages.

Be aware that your font may not have definitions for the characters in your target’s language. If you see boxes where you expect characters, try changing your fonts:

Go to Cobalt Strike -> Preferences -> Cobalt Strike to edit the GUI Font value. This will change the font Cobalt Strike uses throughout its GUI, dialogs, and tables. This option is new in 3.10.

Cobalt Strike -> Preferences -> Console and Graph change the fonts used by Cobalt Strike’s console tabs and pivot graph.

Integration with MITRE’s ATT&CK Matrix

Cobalt Strike 3.10 integrates The MITRE Corporation’s ATT&CK Matrix into its reporting engine. ATT&CK is a project to describe adversary post-exploitation behaviors with their detection and mitigation strategies. Each behavior is assigned a Tactic ID.

Cobalt Strike 3.10 associates Beacon actions with one or more ATT&CK tactics. Scripts have the option to do this with the &btask function too.

Cobalt Strike uses this information to generate a Tactics, Techniques, and Procedures report. This report presents your Cobalt Strike activity on a tactic-by-tactic basis. Each tactic includes a description, mitigation, and detection narrative.

A Root Canal for the Beacon Payload

This release took many steps to remove functionality from the Beacon payload and restore that functionality with changes in the Beacon controller.

One such change removed the logic to spawn cmd.exe and powershell.exe from inside the Beacon payload. In their place is a more generic primitive to run programs and send output to Cobalt Strike. The updated shell and powershell commands use this primitive instead. The &beacon_execute_job function builds on this primitive too. Here’s a script that re-implements Beacon’s powershell command:

alias powershell {
	local('$args $cradle $runme $cmd');

	# $0 is the entire command with no parsing.
	$args   = substr($0, 11);

	# generate the download cradle (if one exists) for an imported PowerShell script
	$cradle = beacon_host_imported_script($1);

	# encode our download cradle AND cmdlet+args we want to run
	$runme  = base64_encode( str_encode($cradle . $args, "UTF-16LE") );

	# Build up our entire command line.
	$cmd    = " -nop -exec bypass -EncodedCommand \" $+ $runme $+ \"";

	# task Beacon to run all of this.
	btask($1, "Tasked beacon to run: $args", "T1086");
	beacon_execute_job($1, "powershell", $cmd, 1);
}

These changes remove a few unique strings from the Beacon payload. This is where the root canal analogy comes in. A root canal not only removes (signs of) infection, it replaces the infection with something benign. That’s here too!

Cobalt Strike 3.10 extends Malleable PE with options to add ASCIIZ and wide character strings to the Beacon payload. This example adds several havex specific strings to Beacon’s havex Malleable C2 profile:

stage {
	# strings gathered from Yara rules and sandbox string dumps
	stringw "%s <%s> (Type=%i, Access=%i, ID='%s')";
	stringw "%02i was terminated by ThreadManager(2)\n";
	stringw "main sort initialise ...\n";
	stringw "qsort [0x%x, 0x%x] done %d this %d\n";
	stringw "{0x%08x, 0x%08x}";
	stringw "Programm was started at %02i:%02i:%02i\n";
	stringw "a+";
	stringw "%02i:%02i:%02i.%04i:";
	stringw "**************************************************************************\n";

These changes recognize the fact that some analysts use tools driven by YARA rules to detect and identify payloads in an environment. These rules often target unique strings observed by the rule’s creator. Knowing these strings, red teams have an opportunity to deliver more interesting adversary simulations and exercise another aspect of their blue team’s detection and response capability.

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

NOTE: An in-place update of Cobalt Strike with live sessions is never recommended. With Cobalt Strike 3.10, this is especially true. Cobalt Strike 3.10 cannot control sessions from previous versions of Cobalt Strike.