Real-Time Feed of Red Team Activity

January 13, 2016

There are several research projects to collect raw data from red team activity, process this data, and try to turn it into information. In this blog post, I’ll show you how to instrument a Cobalt Strike team server and generate a real-time feed of engagement activity.

Aggressor Script is the scripting engine in Cobalt Strike 3.0 and later. Aggressor Script uses the on keyword to hook different events generated by Cobalt Strike. The * event is a special event baked into Aggressor Script. The * event fires for every Cobalt Strike event.

Here’s a simple script to hook the * event and write its arguments to the events.txt file:

on * {
	$handle = openf(">>events.txt");
	println($handle, "[EVENT] $1");
	foreach $index => $argument (subarray(@_, 1)) {
		println($handle, "[Argument $index $+ ] $argument");

The first parameter to the * event is the event name. Each parameter after that are the fired event’s original parameters.

To load this script: save the example in events.cna. Go to View -> Script Console in Cobalt Strike. Type load /path/to/events.cna. The script is now loaded.

As new events come in, this script will append them to the events.txt file. What gets fired as a Cobalt Strike event? Everything! Input to a Beacon, by any user, is an event. Output to a Beacon is an event. New content hosted on Cobalt Strike’s web server is an event. You get the idea.

Feel free to modify this script to feed your local data collection monster.


  1. Recording every event generated by CS would likely disrupt performance of CS. Having any clues/benchmarks about that please?

    • I appreciate your concern, but we’re not talking about a “big data” application here. I can’t imagine a scenario where one Cobalt Strike team server is generating more than tens to hundreds of events each second. Even if we go above that, Cobalt Strike’s scripts do not run in the team server itself. They always run in a client. The team server is architected to receive information from a client or Cobalt Strike feature (e.g., Beacon’s controller) and to broadcast this information to all clients. Clients do not get to opt out of this information. They all receive events from the team server, whether the script described in this post is loaded or not.

      Now, maybe you’re concerned about slowing down your Cobalt Strike client. Sure, I worry about that too. I designed the script event dispatcher in Cobalt Strike to queue events and to process them in their own thread. This design decision allows scripts to react to events without blocking the rest of the application. For the [very unlikely] situation where events come in faster than the client can process them, the event dispatcher queue is designed to purge old events as a fail-safe.

      But, the above is moot for this example. You can use a headless Cobalt Strike client [agscript] to host your event recorder script without disrupting any of your operators. This client connects to the team server, subscribes to events, and gets a chance to process them.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s