Analyzing Cobalt Strike PowerShell Payload

Since last year, cobalt strike payloads are everywhere. We saw hackers used Cobalt Strike in many attacks. Some serious cyber incident like SolarWinds supply chain attack [1]. In Proofpoint’s new article, said that Cobalt Strike is the favorite tool from APT to crimeware [2]. Cobalt Strike is a penetration tool which developed by Strategic Cyber. It’s a good framework for collaboration by Red team.

In these days, the executable and dll type of cobalt strike payload are most often used in attack. Other’s payload type like macro or powershell sometimes were also be delivered by attackers. In this article, let’s analysis the cobalt strike powershell payload.


VirusTotal shows there are 28 AV vendors detect this malicious payload. 4 vendors detect it is cobalt strike related malware, and 8 vendors detect it as「PwShell.Rozena」. That’s interesting! After I searched what is Rozena, and I found an analysis report published in 2018 from GDATA [3]. Looks like the malware used some technique of command line to run powershell, performing fileless attacks.


You can choose one of your favorite text editors to open this sample. First, I noticed this sample is not obfuscated, some powershell malware using obfuscation in order to evade AV detection. Then, this sample is a Stageless payload[4], and it was generated by Cobalt Strike attack package directly. In Cobalt Strike Official website description, we know that:

Attacks -> Packages -> Windows Executable (S) generates a Windows executable artifact that contains Cobalt Strike’s Beacon (no stagers, hence a stageless payload!). This package gives you several output options.

One of option is PowerShell:

PowerShell is a PowerShell script that injects a stageless Beacon into memory.

As below powershell script (I bypass the big string part in the middle):

Quickly go through the powershell code, it declares two functions, and there is a big base64 sting in the middle. After the big base64 string, there is a for loop process each item of byte array and doing xor calculation. Finally, we see some suspicious API like VirtualAlloc and Invoke.

At the beginning of the script, use IntPtr Size to confirm whether the system is a 32-bit or 64-bit operating system. If the size is 4, it means that the current operating system is a 32-bit system, and if the size is 8, it means that the current operating system is a 64-bit system.
If the system is 64-bit, the Start-job command means that execute the Powershell in background . The parameter is $DoIt and runs in 32-bit mode. If the system is 32-bit, just executes $DoIt.

Let’s focus on the big base64 sting in the middle. It using Convert FromBase64String to convert base64 string to a byte array.

Then, in the for loop, XOR each item in byte array with 35. -lt is the less than operator, and -boxr is binary XOR calculation.

Let’s dump the byte array! Please comment the code as below first, we don’t want these code been executed.

With Powershell WriteAllBytes method, dump the data to a bin file. Add one line code as below:

After save and execute the script, we got a bin file. Open the static analysis tool: pestudio, and drag bin file into the program. You can directly know that it is a dll file.

The final part is load and run the dll file into memory.

It is worth noting that the dll file we just dumped is the Beacon payload of cobalt strike. At present, many researchers have developed tools that can extract Beacon config information [5]. The config information extracted by the tool is as follows:

It can be known that the Beacon is https type, and the c2 Domain and URI are extractd. If you want to know more about the analysis of Cobalt Strike Beacon, I recommend the article written by T-ek[6], which has more detailed analysis content.


There are some problems that may be encountered in the debugging process.

Your system cannot execute powershell script.

This error comes when the PowerShell execution policy doesn’t allow us to run scripts.

Below is four different execution policies in PowerShell[7]:

Restricted — No scripts can be run.

AllSigned — Only scripts signed by a trusted publisher can be run.

RemoteSigned — Downloaded scripts must be signed by a trusted publisher.

Unrestricted — All Windows PowerShell scripts can be run.

Using Get-ExecutionPolicy to check what current execution policies is.

Using Set-ExecutionPolicy to change the execution policies to unrestricted or others options.