Cobalt Strike Visualizations

NOTE: This post is not entry-level. This will be a deep dive into complex Aggressor scripting, and undocumented functionality. Fair warning — even I don’t understand visualizations fully, and there’s a lot more to explore. This is just scratching the surface.

If you saw my blog post a couple weeks ago, you know that I like writing Aggressor scripts for Cobalt Strike. Aggressor allows you to add functionality to the framework, and make it even more useful for your purposes. This can be done in many different ways, but one thing that has caught my interest recently is the possibility offered by Cobalt Strike visualizations.

What are Visualizations?

Visualizations are the different views that Cobalt Strike offers to an operator, found in the View menu. The default visualizations are what you’re used to seeing in the top pane of Cobalt Strike: Sessions view, Targets view, and the Pivot Graph. Basically, they’re there to give you information about the engagement, and the current state of Cobalt Strike. But what if we could display more information to operators? What information is kept within the framework that isn’t as easy to see? More importantly, how can we display that to operators to allow them to use that information?

Visualizing Success

A few months ago, I was playing around with some Aggressor, and while browsing the official reference, I stumbled across a function I had never really paid attention to: addVisualization. My interest was piqued, because the Aggressor function reference only gives this:

Register a visualization with Cobalt Strike.
$1 - the name of the visualization
$2 - a javax.swing.JComponent object
$label = [new javax.swing.JLabel: "Hello World!"];
addVisualization("Hello World", $label);

Not much to go on. I wanted to find out more. What else could I do with addVisualization? Could I create anything useful? There was one problem… There weren’t any other examples of visualizations in Cobalt Strike. None. I looked exhaustively. There were Aggressor scripts that dealt with GUI elements — notably from @bluescreenofjeff and @harmj0y, both of which were extremely helpful for certain parts — but there were no scripts that I could find that actually created visualizations. Without other code to reference, I was in uncharted territory. Rather than give up, I fired up Cobalt Strike and started tinkering.

Hello, world!

The first step was to create a very simple visualization. I just wanted to make sure that I could add a visualization to the framework and display it. From there, I could build on that to make a visualization that actually displays useful data.

The code for this was fairly simple, and most of it is in the little snippet in the docs. First, you have to create a JComponent object. The example in the docs (posted above) uses a JLabel, so that’s what I started with. Here’s my first working visualization:

And here’s what that looks like when you load the script into Cobalt Strike:

My very first visualization!

Aggressor and Java

Before we go through this simple script, we need to talk a little bit about Java inside of Aggressor. If you haven’t dealt with Java in Aggressor before, Aggressor scripts can import any Java packages or libraries you want, and you can access them from within Aggressor with a slightly different syntax compared to what you might do in Java.

For example, to make a new JLabel in Java, we would use this syntax:

vis = new JLabel(“Hello, world!”);

To do this in Aggressor, we use the following syntax, as seen in line 6 of the helloworld.cna script:

$vis = [new JLabel: “Hello, world!”];

Converting Java constructors to Aggressor is fairly straightforward. Instead of new Object(arg1, arg2), you can use [new Object: arg1, arg2]. You use a similar syntax when calling methods on Java objects. I’ll show an example of that here, because we’ll use that later. Consider a Java object that we’ve created in Aggressor like this:

$obj = [new someObject];

Let’s say the someObject class has a doStuff(“argument”) method that will return a string. To get this string in Java, we’d do something like:

String str = obj.doStuff(“argument”);

To do the same thing in Aggressor, it looks like this:

$str = [obj doStuff: "argument"];

This syntax will let us convert Java to Aggressor, and thus create more advanced visualizations. Back to our simple visualization.

Creating and Displaying Visualizations

As seen in the docs for addVisualization, once we’ve created a visualization, we use addVisualization to register the visualization within Cobalt Strike. This still doesn’t display it to the user, though! The syntax for addVisualization that our script uses is this, on line 7:

addVisualization("hello", $vis);

In this case, “hello” is a label that we can use to reference our visualization now, and we use this label to display the visualization with showVisualization:


Pretty simple, right? …Right?

Making Useful Visualizations

While creating my first test visualization was pretty easy, the rest wasn’t so easy. Working without a good reference, I turned to the source code for Armitage, Raphael Mudge’s precursor to Cobalt Strike. Many parts of Cobalt Strike are based on Armitage, and luckily still utilize many similar components. By looking through the various Cortana scripts (the precursor to Aggressor), I managed to cobble together a basic visualization that allowed me to display a table of Beacons alongside a simple console display, vis.cna.

Vis.cna in all its glory.

As you can see, it was fairly minimal, but it provided a good way to test out various things within Cobalt Strike visualizations. This visualization pulls information from the Cobalt Strike data model to populate the table of Beacons on the left, and displays web log hits and new Beacon events in the console on the right. There was one major issue with this visualization, but first let’s go through how it’s constructed.

Vis.cna Deconstructed

I started my work on a custom visualization by attempting to build a simple table, and to pull Beacon data into that table. To create a table, it first requires a GenericTableModel, which is what will populate our table with data. GenericTableModel is provided by the table package, built in to Cobalt Strike. To create a GenericTableModel, you provide an array of column names, a column to use as the lead column, and an expected size for the table.

$model = [new GenericTableModel: @(“user”, “host”, “bid”), “bid”, 16];

The next question is: How do we pass data into our GenericTableModel? In vis.cna the function that does that is updateTable(). This function is fairly straightforward. First, we clear the model. Next, we have to iterate through the Beacons that Cobalt Strike has information about, and create a hash with the appropriate user, host, and ID for each one.Then, we use the addEntry method of GenericTableModel to add the entry to the model. We’re not quite done yet, because we have to tell the ATable we’re populating with this GenericTableModel that the model has changed. That’s where fireListeners comes in.

Now that we’ve created our GenericTableModel to populate it with data, let’s create our ATable. First, we create a new ATable, with the GenericTableModel as an argument.

Next, we have to tell the ATable how to sort the data in the GenericTableModel, so that you can click the column headers to sort based on the data in those columns. First, we need to create a TableRowSorter to control how the data is sorted. Next, we need to use the setComparator method of this TableRowSorter to tell it how to sort each column. We have three columns: username, hostname, and Beacon ID. Usernames and hostnames are sorted alphabetically, but we need to sort Beacon IDs numerically. To sort the first column alphabetically, we need this snippet:

[$sorter setComparator: 0, { return $1 cmp $2; }];

To sort the Beacon ID numerically, we use this snippet:

[$sorter setComparator: 2, { return $1 <=> $2; }];

With that, we’ll be able to change the sort order of the table by clicking the column headers. After making sure we can sort the table, let’s add a secondary component to display certain events in the Cobalt Strike console. I chose a Display from the built-in console package in Cobalt Strike, because it will give us nice formatting options for the text, and it matches with the way information is displayed in the rest of the framework. Creating this is pretty simple:

$console = [new console.Display];

After we’ve created our ATable and Display, we need to create something to house both of these, because addVisualization takes a single object. For this, I chose a JSplitPane, which will allow us to have both components side by side, with a divider that we can drag to resize the size of either component. Here’s how we do that:

$content = [new JSplitPane: [JSplitPane HORIZONTAL_SPLIT], [new JScrollPane: $table], $console];

You might have noticed that we didn’t put $table directly into the JSplitPane. Instead, we first put it into a JScrollPane, to allow the table to be scrolled if there are more items than fit in the pane. We also specified the direction of the split as the first argument, using [JSplitPane HORIZONTAL_SPLIT]. In Java, this would be JSplitPane.HORIZONTAL_SPLIT, but we need to use Sleep’s Java syntax in this case. To make things look a little nicer, I chose to set the default divider location to have a bit of an offset with this line:

[$content setDividerLocation: 450];

The last thing we need to do before adding our new visualization is call our updateHosts function to populate data into the GenericTableModel. Then, we can finally add our visualization to Cobalt Strike with addVisualization(“Custom”, $content). Note that this doesn’t do anything with the visualization, it just registers it with the framework.

To actually view our new visualization, we can use showVisualization, like this:


Visualizations are referenced by their title in Cobalt Strike, so we choose the title that we used in addVisualization as the argument in showVisualization. At the bottom of vis.cna, I have a short snippet to add the visualization to the View menu in the Cobalt Strike interface, which will allow us to quickly access the new visualization.

Wrapping Up

Hopefully this post has been useful if you’re interested in Cobalt Strike visualizations! This is just scratching the surface of what is possible, and I’m working on exploring these possibilities, but I wanted to share what I’ve learned so far in the hopes that others will see this post and decide to experiment as well. At the most basic, visualizations are just JComponent objects, and they can allow you to customize how information is displayed to operators in Cobalt Strike. I haven’t seen other public examples of Cobalt Strike visualizations, but check out my logvis.cna script for another example, and please let me know if you make anything with visualizations!