Network Connection Footprinting with WMI and Neo4j

Hey all,

This post is about remotely enumerating established TCP connections via WMI and importing that data into a Neo4j databaseNeo4j is a graph database application which is great for graphically displaying relationships between data. If the name sounds familiar it might be because you have leveraged it while using BloodHound. Nowhere near the same level, this post will be using the built-in Neo4j desktop to display relationships in a simple way. Below is example output of a Neo4j query to determine clients connecting to a WSUS server over TCP/8530.

ThunderQuery3.jpgEnumerating network communications can provide valuable information regardless if you’re on the offensive or defensive side. Offensively, enumerating dataflows can uncover new networks outside initial visibility or establish critical systems as wedge points into other networks. Defensively, enumerating dataflows is good practice to identify all sorts of malicious traffic; however, I would imagine defenders have much more advanced tools than this.

In the past I’ve seen netstat performed remotely using something like PsExec. In my opinion, this is a bit overkill and generates quite a bit of noise, so I tried to take an alternative route. ThunderQuery, is a C# application that will continuously enumerate established TCP connections via WMI. ThunderQuery will poll the provided list of targets and generate two CSV files (locally, so beware): profiles.csv and networkconnections.csv. Profiles.csv has system information of each polled target while networkconnections.csv has established TCP connections and is continuously appended to. See the github page for further details … I wrote a README this time!

Example run of ThunderQuery from Cobalt Strike using execute-assembly.


The contents of profiles.csv  will be the following in CSV format: Hostname,Domain,LoggedOn User,DomainRole,IPAddress. For example,


The contents of networkconnections.csv will be the following in CSV format: SourceIP,SourcePort,DestinationIP,DestinationPort. For example,,52847,,135

Once ThunderQuery runs for the switched poll amount (default is 5 minutes), transfer the populated profiles.csv and networkconnections.csv files to the Neo4j import directory and run the following import commands.

LOAD CSV FROM "file:///profiles.csv" AS row1 CREATE(:DNSHostName:IPAddress{dnshostname:row1[0],domain:row1[1], username: row1[2],domainrole: row1[3],ipaddress:row1[4]})
LOAD CSV FROM "file:///networkconnections.csv" AS row2 MERGE(:IPAddress{ipaddress:row2[2]})
LOAD CSV FROM "file:///networkconnections.csv" AS row3 MATCH (a:IPAddress),(b:IPAddress) WHERE a.ipaddress = row3[0] AND b.ipaddress = row3[2] AND tointeger(row3[3]) < 49152 MERGE (a)-[r:NetConn {DestPort: tointeger(row3[3])}]->(b) return r
LOAD CSV FROM "file:///networkconnections.csv" AS row4 MATCH (a:IPAddress),(b:IPAddress) WHERE a.ipaddress = row4[0] AND b.ipaddress = row4[2] AND tointeger(row4[1]) < 49152 MERGE (b)-[r:NetConn {DestPort: tointeger(row4[1])}]->(a) return r

These commands should populate the database with nodes and their respective TCP connections. IP addresses outside of the scope of the target WMI query will be included but will be lack additional profile information. Running a query like MATCH (n) RETURN n will show all TCP connections and could be a bit noisy.


However, you can narrow that down using Neo4j queries to filter based on TCP port or whatever you would like.

MATCH p=()-[r:NetConn{DestPort: 8530}]->() RETURN p


Leave a Reply

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

You are commenting using your 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