WGuard β€” WiFi Intrusion Detection System

Passive monitoring only β€” wguard never injects any frames. Running it is invisible to the target network.

CMD> sw                           # scan first to get AP index
CMD> wg <index|bssid> [ch]        # interactive mode
CMD> wg <index|bssid> [ch] bg     # background mode β€” returns to prompt
CMD> wg view                      # enter live view of running bg session
CMD> wg stop                      # stop background session

How It Works

wguard locks onto a single AP (by index from sw, or by BSSID + channel directly) and puts the radio into promiscuous mode on that channel. It captures every 802.11 management and data frame in the air and runs each frame through a set of detection rules.

The channel is fixed for the duration of the session β€” wguard does not hop. This is intentional: hopping would miss the rapid burst sequences that most attacks produce.

Frame counters shown in the header update in real time:

  • Bcn β€” beacon frames from the target AP
  • Prb β€” probe requests seen on the channel
  • Ath β€” authentication frames
  • Dth β€” deauthentication / disassociation frames
  • EAP β€” EAPOL frames (WPA2 4-way handshake)

Display

Interactive mode shows a live cyberpunk-style header, a status line (OK / WARNING / CRITICAL), the frame counters, and a scrollable event log with session-relative timestamps.

[WGRD::IDS]  MyNetwork  ch6  AA:BB:CC:DD:EE:FF
Bcn:420  Prb:31  Ath:4  Dth:210  EAP:8    STATUS: WARNING
────────────────────────────────────────────────
EVENTS [2/5]
00:01:04  WARNING  -36  BCAST DEAUTH AA:BB:CC:DD:EE:FF
00:01:50  WARNING  -47  EVIL TWIN+DTH CC:DD:EE:FF:00:11
00:02:14  CRITICAL -75  HANDSHAKE harvest M1+M2
────────────────────────────────────────────────
[↑/↓]scroll  [s]save  [q]quit

Timestamps are session-relative β€” 00:01:04 = 1 min 4 sec after wg started. rssi_dbm shows the signal strength of the triggering frame β€” useful to estimate attacker proximity.


Detection Algorithms

BCAST DEAUTH

Trigger: 5+ broadcast deauthentication frames from the same source MAC within 5 seconds.

Broadcast deauths (destination FF:FF:FF:FF:FF:FF) disconnect all clients simultaneously. A single deauth is normal (roaming). A burst at this rate is characteristic of a deauth attack script.


DEAUTH Storm

Trigger: 15+ targeted deauthentication frames from the same source MAC within 5 seconds.

Targeted at a specific client MAC rather than broadcast. High-rate targeted deauths are the signature of an active client-eviction attack (forcing re-association to capture a handshake, or as an aggressive DoS).


AUTH Flood

Trigger: 32+ unique source MACs sending authentication frames within 10 seconds.

An authentication flood sends fake auth requests from randomly generated MACs to fill the AP’s association table. A legitimate network sees at most a handful of auth frames in any 10-second window.


PROBE Storm

Trigger: 50+ probe request frames from the same MAC within 5 seconds.

A single device probing at this rate is either a pentest tool actively mapping the channel, or a malfunctioning device. Normal clients probe a handful of times per minute.


PMKID Grab

Trigger: 5+ rapid association requests from the same MAC within 5 seconds.

PMKID attacks send rapid association requests to extract the PMKID from the AP’s response without ever completing the 4-way handshake. Distinguishable from a normal re-association by the burst rate.


EVIL TWIN (two-tier)

Detection is two-tier to reduce false positives from legitimate range extenders.

Tier 1 β€” INFO (pending): A foreign beacon is seen advertising the exact same SSID as the monitored AP, from a different BSSID. This alone fires an INFO event and starts a 3-second observation window.

Tier 2 β€” WARNING (confirmed): If deauthentication frames arrive concurrently with the foreign beacon (the attacker is actively driving clients toward the fake AP), the event is upgraded to WARNING β†’ EVIL TWIN+DTH.

Additional filters:

  • RSSI filter > βˆ’82 dBm β€” distant APs below this threshold are logged as INFO only, never promoted. A legitimate range extender at βˆ’90 dBm won’t false-fire.
  • 3-second beacon silence expiry β€” if the rogue AP disappears and restarts, wguard re-detects it after 3 seconds of silence rather than treating it as a persistent threat.
  • OUI check β€” an AP with the same SSID but a vendor OUI matching a known mesh/enterprise vendor is logged as CO-AP (INFO), not an evil twin.

HANDSHAKE Harvest

Trigger: An EAPOL exchange (M1 + M2 or M2 + M3) is seen following a deauthentication burst within a short time window.

The classic handshake-capture attack: send deauths to force re-association, then capture the EAPOL frames. wguard detects the combination β€” deauth burst followed by EAPOL β€” as CRITICAL.


BSSID Clone

Trigger: The BSS timestamp in beacon frames from the monitored BSSID goes backward (Ξ”ts < 0).

Every AP increments its BSS timestamp continuously from boot. If two radios are advertising on the same BSSID (a clone scenario), the timestamps from the two radios will be out of sync β€” wguard sees a backward jump when frames from each radio interleave in the capture.

Clone confirmation uses three-signal logic to avoid false positives in enterprise environments:

Signals seen Severity Event
ts-jump only (0xFD) WARNING BSSID CLONED … ts-jump
ts-jump + beacon compression (0xFA) WARNING BCN COMPRESS+TS-JUMP (no deauth, possible enterprise AP)
ts-jump + beacon compression + deauth burst CRITICAL CLONE CONFIRMED (deauth+ts-jump+bcn-compress)

Why deauth is required for CRITICAL: Enterprise WiFi systems (Fortinet, Cisco mesh) deploy multiple radios on the same BSSID, which produces both a backward timestamp jump and beacon interval compression naturally. These legitimate APs never deauthenticate their own clients. A real evil twin almost always sends a deauth burst to force clients to reconnect to the rogue AP. Requiring deauth as the third signal eliminates false alarms in busy enterprise environments while still catching real attacks.

Clock-skew note: A rebooting AP also resets its timestamp to ~0, triggering both a backward-jump and a clock-skew anomaly simultaneously. Clock skew alone (0xF9) never upgrades the severity β€” it fires as INFO only β€” because it is indistinguishable from a reboot and can be spoofed by an attacker who synchronises their TSF.


BEACON FLOOD

Trigger: 100+ unique BSSIDs seen advertising on the channel within 30 seconds.

The signature of a beaconflood / bf attack. A normal busy environment has at most 20–30 APs visible on any channel.


KARMA Attack

Trigger: The same BSSID responds to 3+ different probe request SSIDs within 60 seconds.

A KARMA attack makes a rogue AP respond affirmatively to any SSID a device probes for, allowing it to impersonate any network. wguard watches for probe responses β€” not just beacons β€” from a fixed BSSID and counts unique SSIDs answered.

Real-world testing note: KARMA detection requires probe-response sniffing. Depending on timing, some KARMA implementations may not trigger the threshold within the 60-second window. Consider this detection experimental.


Rate Limiting

To prevent log and notification spam during sustained attacks:

  • Each detection fires at most once per 30 seconds per source MAC
  • Notification sounds are further throttled: WARNING ≀ 1 per 10s, CRITICAL ≀ 1 per 5s (via notifyThrottled())

The event log still records every individual event β€” rate limiting only affects notifications and screen popups.


Background Mode

wg <idx> bg returns to the command prompt immediately. wguard keeps sniffing in the background while you use other commands.

The shield icon in the status bar reflects the current threat level:

Colour Meaning
Grey Not running
Green Running β€” no threats detected
Yellow WARNING level event detected
Red CRITICAL event detected

When a threat fires in background mode a coloured popup bar appears at the bottom of the screen for 4 seconds and a notification sound plays. INFO events are silent.

wg view enters the live event view from any screen. q returns to the prompt without stopping the session.

WiFi lock β€” while wguard bg is active, other WiFi commands (scanwifi, deauth, eviltwin, etc.) are blocked. Run wg stop first. trackme BLE scanning works alongside wguard bg β€” only the WiFi probe-sniff phase of trackme is skipped automatically.


Session Logs

Each wg run creates a new numbered file: /apps/wguard/001.csv, /002.csv, etc. The number increments on every boot and session start β€” files are never overwritten.

CSV format

# SESSION 3  wguard "MyNetwork"  bssid=AA:BB:CC:DD:EE:FF  ch6  uptime=12s
time,severity,rssi_dbm,message
# CHECKPOINT 1  Bcn=420 Prb=31 Ath=4 Dth=210 EAP=8
00:01:04,WARNING,-36,BCAST DEAUTH AA:BB:CC:DD:EE:FF
00:01:50,WARNING,-47,EVIL TWIN+DTH CC:DD:EE:FF:00:11
00:02:14,CRITICAL,-75,HANDSHAKE harvest M1+M2
# FINAL SAVE  total=3 events  maxSev=CRITICAL  duration=4m22s

Save types

Type When Ring cleared?
AUTO-SAVE Ring hits 128 events Yes β€” continues fresh
CHECKPOINT Every 2 minutes (skipped if nothing new) No
MANUAL (s key) You press s β€” footer shows Saved N events or Nothing new to save No
FINAL Session ends (quit / wg stop) No

Each save block writes only new events since the last save β€” no duplicates across blocks.


Keys (Interactive Mode)

Key Action
Trackball ↑ / ↓ Scroll event history (5 lines per step)
s Save new events to SD
q Quit β€” triggers final save automatically

Resources

Deauth / Disassoc attacks

PMKID attack

WPA2 Handshake Harvest

Evil Twin / Rogue AP

KARMA Attack

BSSID Cloning / BSS Timestamp

Beacon Flood

  • CVE-2019-15126 (β€œkr00k”) β€” flooding as a DoS precursor to force all-zero key decryption
  • mdk4 β€” Linux beacon flood tool (mode b) that wguard’s 100-BSSID/30s threshold was tuned against

AUTH Flood