The Personal Blog of Lennart Koopmann _

Introducing nzyme: WiFi monitoring, intrusion detection and forensics

Today I am releasing my latest open source hobby project: nzyme. It's a Java-based program that puts wireless network adapters into monitor mode, sniffs management frames from all configured 2.4Ghz or 5Ghz channels and writes them into a Graylog instance for monitoring and analysis.



In my previous post, Common WiFi Attacks And How To Detect Them, I laid out the many ways an attacker can attack a wireless network.

With this post, I am introducing nzyme, an open source tool used to detect these attacks or to perform incident response after an attack has happened.

My talk about WiFi security and nzyme at Derbycon 2017 was recorded and can be seen here:

Important: Note that Graylog v2.4 (to be released in about two weeks) has significant visualization improvements that will make the analysis shown in some of the use-cases even easier.



There is a problem with existing approaches. Tools like Kismet are great to detect an attack, but they don’t store all frames that you would need for a proper response to an alert.

OK, there was a targeted rogue AP attack, but I have no way to find out who connected to it, for how long it was there or where it was located physically.

Wireshark/tcpdump can collect the frames but are both falling short on long-term collection and analysis. It's almost impossible to detect a rogue AP by MAC timestamp or signal strength anomalies. Imagine how long it would take to simply load a PCAP file worth a few days of data.

This is where nzyme comes in: By writing the data into Graylog, you can analyze and visualize months worth of data in a few milliseconds - even on modest hardware.

How does it work?

Nzyme reads 802.11 WiFi frames directly from the air using any WiFi adapter that supports monitor mode. It then parses the frames and sends them over the network to a Graylog (free and open source log management) setup.

For example, a recorded probe-response frame would look like this in Graylog:


Noisy environments can easily create hundreds of messages per second, and with all the data collected in Graylog, you can analyze the WiFi traffic in many ways. A set of interesting use-cases follows below.

The more detailed description and installation instructions can be found in the README.


Threat and intrusion detection

This is what Kismet already does well, but nzyme can help with threat hunting approaches.

Deauth flooding

Deauthentication flooding can be an attempt to simply jam and disrupt communications or a stage of an attack, where the attacker tries to get the victim off a legitimate access point so the targeted device may connect to a rogue access point operated by the attacker.

We can detect this by having an eye on the number of deauthentication (deauth) frames in the air:

Graylog query: subtype:deauth

Detecting deauthentication floods

As you can see, there is a usual amount of deauth frames in the air around 10 pm. Set up a threshold alert in Graylog to trigger actions anytime there are too many deauth frames.

BSSID whitelisting

Every access point in a WiFi network has a MAC address that is called BSSID ("Basic Service Set Identifier"). A less sophisticated attacker would not bother to spoof the BSSID of an existing access point, and suddenly you have an unknown MAC address flying around. By keeping a list of the BSSIDs of your access points and searching for any others that are pretending to serve your network (SSID), you can find those less sophisticated rogue access points.

Create a CSV file on your Graylog server that looks like this:

"82:2A:A8:30:94:8D", "Home Main"
"2C:30:33:2A:8D:82", "Home Extender"

Load this CSV file into a Graylog Lookup Table and compare any incoming beacon or probe-response frame for your SSID against this list. Here is an example of how to do this with a Graylog Processing Pipeline:

rule "Nzyme: Enrich beacon"
when $message.subtype == "beacon" && has_field("transmitter")
  let transmitter_name = lookup_value("access_point_macs", uppercase(to_string($message.transmitter)), "unknown");
  set_field("transmitter_name", transmitter_name);

What happens here is that the lookup_value() function compares the transmitter field of the Graylog message against the access_point_macs lookup table. The lookup table is configured to return unknown if it does not match a value from the CSV file or the name of the access point as if it does match.

The result (either unknown or the access point name) is written into a new field called transmitter_name.

Now we can search for all beacon or probe-response frames for our SSID that were sent from a device that is not ours:

Graylog Query: (subtype:beacon OR subtype:probe\-resp) AND ssid:getoffmylawn AND transmitter_name:unknown

As mentioned before, it is easy to spoof a BSSID, so this will not help against more sophisticated attackers. However, given how easy this detection is, it is still a good idea to configure an alert for this in Graylog.

Non-synchronized MAC timestamps

It is important that every access point that spawns the same network has a highly synchronized internal clock. For that reason, the access points are constantly exchanging timestamps for synchronization in their beacon frames. The unit here is microseconds, and the goal is to stay synchronized within a delta of 25µs.

Some rogue access points will not attempt to synchronize the timestamps properly, and you can detect that slip.

You can analyze the timestamp across all access points over time in Graylog with the Generate chart field analyzer:

Graylog query: subtype:beacon AND ssid:getoffmylawn

Analyzing MAC timestamps

The screenshot you are looking at has a perfect MAC timestamp pattern, but an unsynchronized (rogue) access point would distort it. Note that I have not found a rogue AP yet that does not synchronize the timestamps and also that a short slip or lag might be really hard to detect. Oh, and the reset that happens from time to time is food for false positive alerts.

Beacon counts

Access points of the same type and in the same BSS (your network) will usually be sharing the same beacon frequency. A rogue access point may not synchronize with that frequency and send at a much higher frequency.

Graylog query: subtype:beacon AND ssid:getoffmylawn

Beacon intervals

(Note that I'm using a workaround here by counting the total frames in a custom chart. Graylog v2.4. will make it possible to chart this directly out of a Quick Values analysis with one click.)

Signal strength anomalies

This is my favorite one because it is so hard to hide without having deep knowledge of signal strength across your campus or being physically extremely close to an access point, while constantly regulating signal strength.

If an attacker spoofs the BSSID (MAC address) of an existing access point and even synchronizes the beacon interval and MAC timestamps, there is one thing he or she can't hide: The signal strength will be different than the signal strength of the spoofed legitimate access point.

Running a Generate chart analysis on the signal quality field for every legitimate access point MAC address should not show significant changes in signal strength over time because access points usually do not move around.

An attacker would leave a pattern like this, where the mean signal quality for a MAC address suddenly changes:

Graylog query: subtype:beacon AND ssid:getoffmylawn

Signal strength analysis

(Note that I'm using a workaround here by counting the total frames in a custom chart. Graylog v2.4. will make it possible to chart this directly out of a Quick Values analysis with one click.)

Unusual behavior

Depending on their configuration, some rogue access points will also behave in unusual ways. For example, a rogue access point that tries to lure as many devices as possible blindly will probably listen for probe-request frames and always respond with a probe-response or beacon frame for the requested SSID. This will lead to patterns you can detect.

One of those patterns is a BSSID that answers in the name of too many SSIDs. Let's take a look at that:

Graylog query: (subtype:beacon OR subtype:probe-resp) AND transmitter:"14:50:2c:a9:78:9d"

Unusual behavior

This is way too many and completely unrelated SSIDs for a single access point and most likely a rogue access point in catch-all mode.

(The stacking functionality in Graylog v2.4 will make this much easier and no longer require to pre-select a BSSID. You'll be able to group the number of different SSIDs per BSSID in one analysis.)

Forensics and incident response

When either a WiFi IDS tool like Kismet raised an alarm or your threat hunting found something interesting, you can use the nzyme data in Graylog to respond.

Who connected to a rogue access point?

The WiFi authentication and association process is performed with management frames so we can follow every single step for every single device on channels we are monitoring. All we need is a list of BSSIDs that rogue access point used.

We can find out with a search for all association requests to the rogue access point and then run a Quick Values analysis on the transmitter field. This will return a list of all devices that asked to associate with the BSSIDs we think were used by the rogue access point, matching on any SSID in case the attacker was spoofing multiple networks.

Graylog query: subtype:assoc-req AND (destination:"2c:30:33:a5:8d:94" OR destination:"82:2a:a8:07:4c:8d")

Who connected?

Did a rogue access point target a specific device or person?

With the same list of BSSIDs that an attacker used, we can also find out if a specific device or individual was targeted. For example, if we look at the beacon and probe-response frames sent by the rogue access point, we might notice that the target's home network SSID was used, too.

Graylog query: (subtype:beacon OR subtype:probe-resp) AND (transmitter:"2c:30:33:a5:8d:94" OR transmitter:"14:50:2c:a9:78:9d")


Here you can see that multiple SSIDs were used. Pick all the SSIDs that are not from your main networks and research further to figure out if there is a targeting pattern. Protip: You could search for all MAC addresses that were sending probe-requests for each of those SSIDs and map them to a device or individual.

Red teams


The WiFi Pineapple is not only used a lot to spin up rogue access point but also for reconnaissance. You can walk around with a Pineapple Nano in your pocket and collect a complete overview of your target's networks and even devices and what other networks they are looking for.

Someone in the audience at my Derbycon talk had a very interesting idea: You could use nzyme for reconnaissance.

Yagi Antenna

Imagine running a Raspberry Pi in your backpack and walking around the target area or pointing a Yagi antenna at another building and collecting hours or days of data that you can then later analyze in Graylog to plan the next stages of your penetration test.

Try it

Follow the README for installation instructions and download nzyme from GitHub. It should not take longer than 5 minutes to get started.

Please report any issues, questions or feature requests in the issue tracker.