Identify malicious servers / Cobalt Strike servers with JARM

For a new assignment I wanted to use JARM to group servers with a similar configuration. Why JARM? Because it’s an easy way to quickly identify and group servers based on their configuration.

What is JARM?

JARM is an active fingerprinting of TLS servers made available by Salesforce Engineering. It sends 10 TLS Client Hello packets to a server and captures specific attributes of the responses. These responses are then aggregated and hashed. A JARM fingerprint consists of 62 characters where:

  • The first 30 characters cover the ciphers and TLS version chosen by the server;
  • The remaining 32 characters are based on the extensions sent by the server.

Important to realise is that JARM is not an identification if a server is malicious or not, it is just an identification is a server has a configuration corresponding with a specific fingerprint. And although it’s not an identification if a server is malicious, because C2 servers for a specific campaign are often configured similarly, this provides a fingerprint to highlight the malicious servers once you have identified the configuration of one such server.

You can create a JARM fingerprint yourself with the code at Github. But instead of then doing a large network scan and checking the fingerprint of the servers, you can use Shodan. Shodan allows you to query for all the servers with a specific JARM fingerprint with the query


The advantage of using Shodan is obvious. Although JARM is an active fingerprinting tool, by using it via Shodan you can fingerprint the servers passively. You create a JARM fingerprint from one server and then use Shodan to identify which other servers are out there, without sending packets to these servers.

Cobalt Strike servers

Cobalt Strike servers are typically not the type of servers you want to see in your network range.

As an example for identifying servers based on a configuration fingerprint, you can use one of the known JARM fingerprints of Cobalt Strike servers, such as those from Michael Koczwara.

Python script

I wrote a short Python script that takes a list of JARM fingerprints, queries Shodan for these fingerprints and then dumps the hostname and the CN field that was found in the SSL certificate.

In this script

  • Add your Shodan API key in SHODAN_API_KEY;
  • Store the JARM fingerprints in the file jarm.txt;
  • The detailed output of the query is stored in results.txt;
  • The important details of the query, meaning JARM fingerprint, IP and hostname are stored in output.txt.

import shodan
import sys
import json

hits = 0
api = shodan.Shodan(SHODAN_API_KEY)

    f = open('jarm.txt','r')
    f_result = open('results.txt','w')
    f_output = open('output.txt', 'w')

    f_result = open('results.txt','a')
    f_output = open('output.txt', 'a')

    for jarm in f:
        jarm_strip = jarm.strip()
        results ="ssl.jarm:{} country:{}".format(jarm_strip, country))
        #results ="ssl.jarm:{} country:{} network:{}".format(jarm_strip, country, network))
        for result in results['matches']:
            hits += 1
            print("{} {} {} {} {}".format(jarm_strip, result['ip_str'], result['isp'], result['hostnames'], result['ssl']['cert']['subject']))
            f_output.write("{} {} {} {} {}\n".format(jarm_strip, result['ip_str'], result['isp'], result['hostnames'], result['ssl']['cert']['subject']))

    print("Hits: {}".format(hits))

except Exception as e:
    raise e

False positives with JARM

A JARM fingerprint is only a fingerprint indicating a server has a similar configuration. As such, it’s only a first identification for triaging if a server should be further investigated. When I was compiling a list of JARM fingerprints for Cobalt Strike servers I noticed that some of the highlighted servers are related to Zimbra Collaboration servers.

Out of the 90 servers detected with JARM fingerprint 05d02d20d21d20d05c05d02d05d20dd7fc4c7c6ef19b77a4ca0787979cdc13, 24 turned out to be related to a Zimbra Collaboration Server.

(shodan) koenv@ir:~/shodan$ cat output.txt |grep -i zimbra | cut -d ' ' -f 1 | uniq -c
     24 05d02d20d21d20d05c05d02d05d20dd7fc4c7c6ef19b77a4ca0787979cdc13
(shodan) koenv@ir:~/shodan$ cat output.txt | grep 05d02d20d21d20d05c05d02d05d20dd7fc4c7c6ef19b77a4ca0787979cdc13 | wc -l


Once you have identified/created a suitable JARM fingerprint, Shodan is an excellent resource to locate additional servers corresponding to your fingerprint, without having to touch any of these servers.

One thought on “Identify malicious servers / Cobalt Strike servers with JARM

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.