Lee Kirkpatrick

Using RSA NetWitness to Detect Ninja C2

Blog Post created by Lee Kirkpatrick Employee on Apr 9, 2020

A new C2 framework was recently added to the C2 Matrix called, Ninja. It was built on top of the leaked MuddyC3 framework used by an Iranian APT group called, MuddyWater. It can be run on Windows, Linux, macOS, and FreeBSD; the platform is built for speed, is highly malleable and feature rich. As usual, in this blog post will cover the detection of its usage using NetWitness Network and NetWitness Endpoint.


The Attack

Ninja creates a variety of payloads for you upon execution. In this instance, we just chose one of the PowerShell payloads and executed it on the victim endpoint:


A few seconds later we see our successful connection back to Ninja whereby a second stage payload is sent along, as well information about the victim endpoint:


We can see the information sent back from one of the initial HTTP POSTs by listing the agents:


Now we can change our focus to the agent, and start to execute commands against the endpoint:


The Detection Using NetWitness Network

Ninja C2 works over HTTP and currently has no direct support for SSL. This is in an attempt to blend in with the large quantities of HTTP traffic typically already present in an environment: the best place to hide a leaf is in the forest.


Ninja has a somewhat large amount of anomalies in regard to the HTTP requests it makes to and from the C2, a few of these have been highlighted below:

NOTE: While plenty of applications (ab)use the HTTP protocol, focusing on charateristics of more mechanical type behaviour can lead to us to sessions that are more worthy of investigation.


Another interesting element to Ninja is that for each agent a unique five character ID is generated. All requests from or to that agent are then in the form of, "AgentId-img.jpeg" - so from the below, we can tell that two agents are communicating with Ninja. You'll also notice that the requests it is making are for JPEG images, but none are actually returned. We can tell this as the File Type meta key is populated by a parser looking for the magic bytes of files, and it found no evidence of a JPEG in these sessions:



Another interesting artefact from Ninja is that it also returns encrypted commands in GET requests, and the associated encrypted response in POST requests; these can be seen under the Querystring meta key - the initial HTTP POST however, contains information about the system and is sent in the clear delimited by **:


Drilling into the Events view for the Ninja traffic, we can also see a defined beaconing pattern (we set this to two minutes upon setting up Ninja), as well as the fact that the beacons typically all have the same payload size:


Reconstructing the sessions from the beginning, we can see the initial communication with the Ninja C2, whereby it returns a second stage PowerShell payload:


This payload is somewhat large and is setting up the agent itself, the communication with the C2, encrypt and decrypt functions, as well as dynamically generating the AES key that should be used. Payloads such as this should be studied in-depth as they allow you to better understand the C2's function, and in this case, will allow us to decrypt the communication:


The next two pieces of information directly after the second stage payload are of importance, they contain information regarding the agent ID, details of the infected endpoint, as well as the encryption key that will be used; this is not a static key and is dynamically created for each agent:


Continuing the reconstruction of the sessions, we can see some Base64 encoded data, these are the AES encrypted commands and associated responses from them:


If you remember from earlier, we managed to identify the key that was used to encrypt this data. We also identified the second stage payload that was sent, this payload contained the PowerShell code for the agent which included the encryption and decryption functions for this data. We can simply use this to our advantage and create a simple decoder for this data:

#Ninja AES Key Returned From First HTTP POST to C2
#User passed data to decrypt

function CAM ($key,$IV){
try {$a = New-Object "System.Security.Cryptography.RijndaelManaged"
} catch {$a = New-Object "System.Security.Cryptography.AesCryptoServiceProvider"}
$a.Mode = [System.Security.Cryptography.CipherMode]::CBC
$a.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
$a.BlockSize = 128
$a.KeySize = 256
if ($IV)
if ($IV.getType().Name -eq "String")
{$a.IV = [System.Convert]::FromBase64String($IV)}
{$a.IV = $IV}
if ($key)
if ($key.getType().Name -eq "String")
{$a.Key = [System.Convert]::FromBase64String($key)}
{$a.Key = $key}

$b = [System.Convert]::FromBase64String($enc)
$IV = $b[0..15]
$a = CAM $key $IV
$d = $a.CreateDecryptor()
$u = $d.TransformFinalBlock($b, 16, $b.Length - 16)


Executing the script and passing it the encrypted Base64 will decrypt the encrypted commands and associated responses allowing us to see what the attacker executed:


Based on Ninja being over HTTP by default, and the initial communication being in the clear, an application rule to pick up on this would look like the following:

(service = 80) && (action = 'post') && (query contains '**')


To detect further potential communication to and from Ninja C2 we could use the following application rule logic:

(service = 80) && (filename regex '^[a-z]{5}-img.jpeg') && (filetype != 'jpeg')


The Detection Using NetWitness Endpoint

Upon deploying Ninja, NetWitness Endpoint generates four Behaviours of Compromise, runs powershell, runs powershell decoding base64 string, and runs powershell with long arguments:


NetWitness Endpoint also generated meta values for the reconnaissance commands that were executed by the Ninja PowerShell agent:

  • C:\>whoami: gets current username
  • C:\>quser: queries users logged on local system
  • C:\>tasklist: enumerates proceses on local system


This is an important point to note, that even if you miss the initial execution, the malicious process will still have to do something in order to achieve its end goal, and as a defender, you only need to pick up on one of those activities to pull the thread back to the beginning.


Drilling into the Events view for the meta value, runs powershell decoding base64 string, we can see the Base64 encoded PowerShell command to initiate the connection to Ninja, we can also Base64 decode this within the UI to obtain other information such as the C2 IP:


Drilling into the Events view for the other meta values identified, we can see that a FILELESS_SCRIPT, spawned from the initial PowerShell command, is executing the reconnaissance command, tasklist:




New C2 frameworks are constantly being developed but all fall prey to the same detection mechanisms. It just comes down to you, as a defender, to triage the data the system presents to you to look for anomalies in processes doing things they shouldn't.