cobaltstrike beacon

Realize the detection of CobaltStrike default modules through named pipe analysis

0x00 overview

In recent years, the CobaltStrike framework has been widely welcomed by red team members and threat actors. Due to its strong functionality, flexibility and stability, it has naturally become the leader of the commercial command and control framework.

At the same time, defense personnel have conducted a lot of research and efforts in order to construct a reliable signature of CobaltStrike and its implant Beacon. This article mainly studies some previously unknown threat indicators (IoC). Since a large number of researchers have done research on the signature of CobaltStrike’s default configuration, we will not repeat this aspect here, but focus on some built-in modules of CobaltStrike’s post-exploitation functions, such as keyloggers. , Mimikatz and screenshot modules.

It should be noted that the threat indicators and behavioral characteristics involved here are based on the information provided by the author of CobaltStrike, which can be customized by the attacker in the 4.2 version of the Malleable configuration file.

I hope this article can help blue team members to enhance their detection capabilities, and at the same time promote red team members to use more complex and customized technologies.

0x01 analysis

We know that CobaltStrike uses a specific mode when executing certain commands, which is called “Fork-n-Run”. Fork-n-Run mode will generate a new process (also known as Sacrificial Process) and inject functions into it. This mode has many advantages, one of which is that it can perform long-running tasks without blocking the main Beacon thread. Keylogger is a good example. Under normal circumstances, these functions need to be implemented in a reflective DLL.

The latest version of the framework provides with a lot of flexibility, allowing them to customize the function of the injection process. But other places have not changed much, and these places are where we need to focus.

More specifically, what has not changed is the ability to retrieve the output of the injected module. For example, the Keylogger module can send keystrokes back to the main Beacon process. However, the keylogger module is fileless, so how does the communication with the main Beacon process happen?

The answer is-through the pipeline.

Pipes are shared memory used for communication between processes. They can be divided into two types-named pipes and unnamed pipes.

As the name implies, named pipes have a name and can be accessed by quoting the name.

The unnamed pipe needs to pass its handle to other communication processes to exchange data. This process can be done in many ways.

CobaltStrike uses both named pipes and unnamed pipes to exchange data between Beacon and Sacrificial Process.

0x02 named pipe

We found that when some CobaltStrike modules are used to inject the reflective DLL into the Sacrificial Process, a named pipe with predictable rules will be created.

Please note that these named pipes are not SMB named pipes used for lateral movement and can be customized via Malleable configuration files. Before version 4.2, the name of this named pipe could not be modified by an attacker.

Specifically, once the job (Job) is started, Beacon will create a named pipe. The name of the pipe contains only hexadecimal characters, and the length is equal to the length of the module name (for example: screenshot module screenshot, the length is 10 characters). We found that the following modules meet the above characteristics:

1、Keylogger

2、Screenshot tool Screenshot

3 、 Mimikatz (dcsync 、 dpapi 、 logonpasswords)

4、Powerpick

5、Net (netview)

The following screenshots show examples of Sysmon event ID 17 and 18 (pipe creation and pipe access respectively) after executing the “keylogger” command:

sysmon event log

powershell event log

We have conducted some experiments and found no other legitimate applications will create named pipes with the same characteristics. We later intend to use this feature to create a Splunk search, using Sysmon and Yara rules to scan the process memory during the search.

0x03 anonymous pipe

Not every CobaltStrike command creates a named pipe, and some of them also use anonymous (unnamed) pipes to achieve the same goal. The following figure shows the pipeline created after issuing the “execute-assembly” command:

sysmon event log

We can debug the Sacrificial Process generated by starting the long-running assembly to confirm this:

beacon

We set a breakpoint on the “ntdll!NtWriteFile” function. You can see that the handle Sacrificial Process is trying to write is associated with an unnamed file belonging to the Pipeline File System (NPFS):

process handle

We found that commands such as “execute-assembly” are not as trivial as the above example. So, what can we do with pipelines?

In theory, we can establish a baseline for processes that use anonymous pipes. It is worth noting that local Windows processes usually do not use anonymous pipes. Therefore, we can look for the Windows process connected to the anonymous pipe and start investigating from there.

The reason why the Windows process is mentioned here is because often use the local Windows binary file as the Sacrificial Process in the Malleable configuration file. We can find some already listed binaries from the C2Concealer repository, which is a project for creating random Malleable configuration files. From the following default configuration of C2Concealer, we can find executable files:

''

##############################################

Data set containing post_ex block data, including

spawn-to processes.

##############################################

'''
#CUSTOMIZE THIS LIST#

spawn_processes = ['runonce.exe','svchost.exe','regsvr32.exe','WUAUCLT.exe']

It can be seen that the above process is used for post-vulnerability exploitation operations. They usually do not use anonymous pipes to communicate with different processes. Therefore, you can use this to search, and finally establish a detection rule.

During the experiment, it was found that the following Windows binary files use anonymous pipes for inter-process communication:

· wsmprovhost.exe

· Ngen.exe

· splunk.exe

· splunkd.exe

· firefox.exe

The above method is also applicable to the custom reflective DLL executed through CobaltStrike’s dllspawn API, because the basic communication mechanism is the same. A corresponding example is Outflank’s Ps-Tools repository. Ps-Tools is a collection of rDLLs fully compatible with CobaltStrike, allowing to monitor activities. We try to execute the “psw” module, which is used to enumerate active Windows as follows:

beacon command

After executing this module, we can recognize the same anonymous pipeline behavior we saw before:

powershell event log

0x04 detection rules

There are many ways to detect abnormal named pipes. As a proof of concept, we developed Yara signatures that can be used to scan process memory and find active instances, and Splunk search that can be combined with Sysmon.

The Yara rules are as follows:

rule cs_job_pipe
{

meta:
description = "Detects CobaltStrike Post Exploitation Named Pipes"
author = "Riccardo Ancarani & Jon Cave"
date = "2020-10-04"

strings:
$pipe = /\\\\\.\\pipe\\[0-9a-f]{7,10}/ ascii wide fullword
$guidPipe = /\\\\\.\\pipe\\[0-9a-f]{8}\-/ ascii wide

condition:
$pipe and not ($guidPipe)

}

Example executed for Sacrificial Process:

. \ yara64.exe. \ cs-job-pipe.yar -s 9908

cs_job_pipe 9908

0x13372b7b698:$pipe: \\.\pipe\928316d80

0x13372bf3940:$pipe: \\x00\\x00.\x00\\x00p\x00i\x00p\x00e\x00\\x009\x002\x008\x003\x001\x006\x00d\x008\x000\x00

The following Splunk search can be used to remind the creation of named pipes that match the above pattern:

index="YOUR_INDEX" source="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=17 PipeName!=""   | regex PipeName="^\\\\[a-f0-9]{7,10}$"

In the process of automated detection of named pipes, this method may be more prone to false positives. However, it can be used in conjunction with other threat indicators to obtain more accurate results.

The example of Splunk search can be used to obtain the process of creating an anonymous pipe, which will be sorted from low to high frequency:

index=”YOUR_INDEX” source=”XmlWinEventLog:Microsoft-Windows-Sysmon/Operational” EventCode=17 PipeName=””| rare limit=20 Image

0x05 Precautions for evading detection

From the perspective of the red team, CobaltStrike 4.2 can modify the rules of the above named pipes. In fact, the “pipename” parameter can be configured in the “post-ex” block, and the name should preferably be similar to the pipe used in the environment.

An example of a “post-ex” block is shown below:

post-ex {
set spawnto_x86 "%windir%\\syswow64\\dllhost.exe";
set spawnto_x64 "%windir%\\sysnative\\dllhost.exe";
set obfuscate "true";
set smartinject "true";
set amsi_disable "true";
set pipename "pipe\\CtxSharefilepipe###,";
}

In addition, in the “spawnto_x86” and “spawnto_x64” parameters, you can select a binary file that legally uses an anonymous pipe to reduce the probability of detection.

You can refer to the official Malleable command description and ThreatExpress’s jQuery sample configuration file to learn more about CobaltStrike’s Malleable configuration file options.

0x06 summary

This article shows two different strategies for identifying the use of CobaltStrike on the terminal. First, we analyze the abnormal named pipes associated with the default module, and then shift the focus to statistical methods to identify more complex attacks.

For the red team members, not to use the default settings and default modules becomes even more critical. For blue team defenders, we hope to provide some practical suggestions on how to discover this tool, so that everyone can use Sysmon and other tools to monitor pipeline abnormalities more widely.