Wireless IDS Evasion
Definition
Section titled “Definition”Wireless IDS evasion is the study of how adversary operations stay inside (or outside) the detection envelope that Wireless Intrusion Detection Systems define — and, run in reverse, it is the most effective methodology for testing that envelope. WIDS products key on specific frame shapes and statistics: deauth/disassociation storm rates, rogue-beacon signatures, probe-response anomalies (KARMA/MANA fingerprints), association-rate bursts, and profile mismatches against known APs. Each detection class has an evasion shape: pacing (a single deauth instead of a storm — below rate thresholds), positioning (operating on channels or in positions the sensor plan doesn’t cover), cloning depth (replicating the legitimate beacon’s full IE profile so profile-diff detection sees nothing), identity reuse (spoofing known AP MACs so rogue detection attributes frames to your own fleet), and client-side preference (attacks that happen at the client — evil-twin harvesting — where the only network-side evidence is an association the sensors may never correlate). The module’s discipline is dual: for the assessor, building evasion-shaped drills that measure which WIDS rules actually fire; for the defender, understanding which of your detections are rate-based (pacing-evasive), signature-based (cloning-evasive), coverage-based (position-evasive), or correlation-based (the only class that survives all three).
Why It Matters
Section titled “Why It Matters”A WIDS that has never been evasion-tested is a compliance checkbox with unknown coverage: vendors publish detection categories, but your deployment’s sensor density, channel plan, and alert thresholds determine what actually fires — and the gap between “the product detects X” and “our deployment detects X” is exactly where real adversaries live. The failure modes are systematic and worth naming: rate-based deauth detection dies to single-deauth pacing (which is all WI2’s handshake forcing needs); rogue detection dies to cloning depth and MAC spoofing (the twin that looks like your fleet until the inventory diff catches it); coverage dies to channel and position gaps (the sensor plan that watches 1/6/11 while the twin sits on 44); and everything dies to low-volume patience — an adversary who does one thing per hour produces a stream of single events that no rate rule aggregates. Running evasion drills against your own WIDS converts the product’s promise into a measured coverage map (which shapes fire, which don’t, at which sensor), and that map drives the three real fixes: sensor density/placement (coverage), baseline correlation (pacing), and inventory joins (cloning). For the assessor, the evasion drill is also the honest way to test client-side attacks: the evil twin whose beacon is never flagged, whose harvest produces only EAP failures on the RADIUS side, is the scenario that proves your detection story’s weak edge — and it is better discovered by your own drill than by a report from an incident.
Detailed Explanation
Section titled “Detailed Explanation”Each WIDS detection class maps to an evasion shape and a defender counter:
WIDS DETECTION CLASSES vs EVASION vs COUNTERS [deauth storm alert] rate-based evasion: single deauth, minutes apart, rotating source counter: correlation (any unexplained deauth from non-BSS MAC = event, not just storms) [rogue AP alert] signature/identity-based evasion: clone legit AP MAC + full IE profile counter: inventory join (BSSID in survey, not in inventory list) + physical RF localization [KARMA/probe anomaly] behavior signature evasion: targeted responses (only probed SSIDs), low volume, quiet modes counter: client-side posture (probing policy) + response-frame rate baselines per area [association flood] rate-based evasion: one association per client, spread over time counter: per-client history (association never seen before from this MAC/position = event) [channel jamming] RF-level evasion: n/a (jamming is loud by nature) counter: spectrum monitoring, noise-floor alerts THE PATTERN: every single-signal rule dies to pacing or cloning; the surviving detections are CORRELATIONS — frame x inventory x position x time.The pacing evasion is the most operationally important: WI2’s handshake forcing needs exactly one deauth per attempt, and “one deauth” is indistinguishable from a roaming glitch unless the defender correlates source MAC against AP inventory — a frame from a MAC that is not one of your APs, targeting your client, is an event at any volume. The cloning evasion escalates the rogue-detection arms race: a twin that copies the legitimate BSSID and the full IE set defeats every frame-level check, and detection moves to physics (the same BSSID on two channels simultaneously — a physical impossibility for one radio, trivially detectable by two sensors seeing it on different channels) and to inventory (BSSID seen where your AP isn’t installed). The position/coverage evasion is deployment-shaped: sensors are placed where cabling is easy, attackers operate where coverage is thin — the counter is the coverage map (the tool below) that turns sensor density from a deployment accident into a design artifact. The client-side split is the structural asymmetry: evil-twin harvesting produces its only network-side evidence on the RADIUS (failure bursts) and endpoint (association to unknown AP) — WIDS sees only the twin’s beacon, which cloning can hide — so the mature detection architecture pairs WIDS with RADIUS analytics and endpoint posture, exactly the join the T7/WI4 workflows validate. The legal line stays load-bearing: jamming (RF DoS) is illegal in nearly every jurisdiction and is not an assessment technique — detection of it (noise-floor monitoring) is defensive coverage, not a red-team tool.
Common Techniques
Section titled “Common Techniques”| Evasion shape | Defeats | How | Defender counter |
|---|---|---|---|
| Single-deauth pacing | Rate-based deauth alerts | 1 frame, minutes apart, rotating sources | Source-inventory correlation |
| Full-profile cloning | Signature rogue detection | Copy BSSID + complete IE set | Same-BSSID-two-channels physics check |
| MAC spoofing of own AP | Rogue detection | Transmit as known BSSID | Inventory join + localization |
| Channel-gap operation | Coverage-based detection | Sensor-blind channels (chanstat) | Coverage map + sensor adds |
| Position-gap operation | Coverage-based detection | Weak-signal corners, floors | Density design, not accidents |
| Quiet MANA | Probe-anomaly signatures | Respond only to selected probes | Client posture (probing policy) |
| Long-horizon patience | All rate-based rules | One event per hour | Trending over rate alerting |
| Encrypted-transport ops | Content inspection | All C2 inside legit TLS | Endpoint + volume stats |
| Sensor-area DoS (jamming) | The sensors themselves | RF flooding | Noise-floor alerts; ILLEGAL to do |
| Twin-at-client harvesting | Network-side WIDS entirely | No rogue frame needed | RADIUS + endpoint joins |
Full Working Code
Section titled “Full Working Code”widsdiffer.py — the WIDS coverage differentiator: joins drill-shaped capture events (the evasion-shaped frames you transmitted in an authorized drill) against the alerts your WIDS/SIEM recorded for the same window, and computes per-shape detection coverage — which evasion shapes fired which rules, which were missed, and which sensor (if any) saw them. The drill-and-measure loop from T1/T9, applied to the wireless detection estate. stdlib only.
#!/usr/bin/env python3"""widsdiffer.py — WIDS drill-coverage differentiator.Usage: python widsdiffer.py --drill drill_events.json \ --alerts wids_alerts.csv [--window 120] [--out cov.md]drill_events.json: the frames your authorized drill sent [{"shape": "single-deauth", "t": 1710000000.0, "src": "emu:01", "dst": "client:07", "channel": 6}]wids_alerts.csv: timestamp,rule,sensor,detailsstdlib only."""import argparse, csv, json, sysfrom collections import defaultdict
def load_drill(path): try: return json.load(open(path, encoding="utf-8")) except (OSError, json.JSONDecodeError) as e: sys.exit(f"drill file error: {e}")
def load_alerts(path): alerts = [] try: with open(path, encoding="utf-8", newline="") as fh: for row in csv.DictReader(fh): try: alerts.append({ "t": float(row["timestamp"]), "rule": row.get("rule", "?"), "sensor": row.get("sensor", "?"), "details": row.get("details", "")}) except (KeyError, ValueError): continue except OSError as e: sys.exit(f"alerts file error: {e}") return alerts
def correlate(drill_events, alerts, window): """For each drill shape: any alert within window?""" per_shape = defaultdict(lambda: { "sent": 0, "detected": 0, "sensors": set(), "rules": set(), "missed": 0}) alerts.sort(key=lambda a: a["t"]) for ev in drill_events: shape = per_shape[ev.get("shape", "unknown")] shape["sent"] += 1 t0 = ev.get("t") hit = None for a in alerts: if abs(a["t"] - t0) <= window: hit = a break if hit: shape["detected"] += 1 shape["sensors"].add(hit["sensor"]) shape["rules"].add(hit["rule"]) else: shape["missed"] += 1 return per_shape
def report(per_shape): lines = ["# WIDS drill coverage", "", "| shape | sent | detected | missed | " "rules | sensors |", "|---|---|---|---|---|---|"] rows = [] for shape, s in sorted(per_shape.items(), key=lambda kv: kv[1]["missed"], reverse=True): cov = s["detected"] / s["sent"] if s["sent"] else 0 rows.append((cov, shape, s)) lines.append( f"| {shape} | {s['sent']} " f"| {s['detected']} | {s['missed']} " f"| {', '.join(sorted(s['rules'])) or '-'} " f"| {', '.join(sorted(s['sensors'])) or '-'} |") lines += ["", "## Coverage summary", ""] total_sent = sum(s["sent"] for s in per_shape.values()) total_det = sum(s["detected"] for s in per_shape.values()) lines.append(f"- overall: {total_det}/{total_sent} " f"drill events detected " f"({total_det/total_sent:.0%})" if total_sent else "- no events") blind = [(sh, s) for cov, sh, s in rows if cov == 0] if blind: lines.append("- **blind shapes** (never detected):") for sh, s in blind: lines.append(f" - {sh} ({s['sent']} sent)") return "\n".join(lines) + "\n"
def main(): ap = argparse.ArgumentParser() ap.add_argument("--drill", required=True) ap.add_argument("--alerts", required=True) ap.add_argument("--window", type=int, default=120) ap.add_argument("--out") args = ap.parse_args() drill = load_drill(args.drill) alerts = load_alerts(args.alerts) if not drill: sys.exit("empty drill events") per_shape = correlate(drill, alerts, args.window) text = report(per_shape) print(text) if args.out: open(args.out, "w").write(text) print(f"[+] {args.out}")
if __name__ == "__main__": main()Code Walkthrough
Section titled “Code Walkthrough”- The correlation window (lines 42-55) is the join’s heart: each drill event is matched against alerts within ±window seconds (default 120 — telemetry latency between your transmission and the sensor’s alert is real, and the window is a documented parameter, not an assumption). First-match scoring keeps the per-shape counters honest about events rather than alerts.
- Per-shape aggregation (lines 34-41) builds the coverage view: sent vs detected vs missed per evasion shape, with the sensor and rule names captured — the report’s columns tell you not just whether a shape was caught but which sensor and which rule did it, which is the operational detail that drives placement and tuning.
- The blind-shapes summary (lines 66-73) is the report’s punchline: shapes with zero detection are the estate’s wireless blind spots, named and counted — the artifact that turns “we have WIDS” into “these four shapes sail through.”
- The drill-event contract (lines 9-14) deserves emphasis: the JSON records what you transmitted (shape, timestamp, source, channel) — the ground truth the correlation needs. Without drill-side ground truth, coverage measurement degrades to alert counting, which measures sensor volume rather than detection coverage.
How It Reaches The Target
Section titled “How It Reaches The Target”The drill reaches the WIDS estate exactly as the T-series’ other drills reach their targets: authorized, windowed, emu-marked frames transmitted into your own airspace, with the drill manifest as ground truth. Each shape reaches a different detection layer: paced deauths reach the rate rules (and should be caught only by correlation), cloned beacons reach signature rules (and should be caught only by inventory joins), channel-gap operations reach the coverage map (and should be caught by nothing — which is the finding), and twin-at-client harvests reach the RADIUS logs (which is where the join to endpoint telemetry lives). The differentiator’s output reaches the program as the coverage matrix’s wireless rows: shapes detected (validated), shapes missed (gaps with the exact evasion shape named), and sensors that saw nothing (placement findings). Those rows reach three owners: detection engineering gets the correlation-rule backlog (source-inventory deauth correlation, same-BSSID-two-channel checks), facilities/infra gets the sensor-placement findings (channel and position gaps), and the SOC gets the drill-window alert review (which of your alerts were emu artifacts, and how fast were they classified). The trend reaches leadership as the wireless coverage line — validated shapes per quarter, rising as correlations and sensors land — the same honest metric shape the whole program runs on. And the absence of detections during a drill reaches the report as its most valuable row: the evasion shape that sailed through is exactly the one an adversary will use, now known to you first.
Exploitation Chain
Section titled “Exploitation Chain”- Plan — authorized drill: 5 evasion shapes, own airspace, WIDS + SIEM logging confirmed
- Baseline — 24h quiet capture: alert noise floor recorded (what does normal look like)
- Execute — paced deauth (1/5min), cloned beacon (full IE), ch-44 op, quiet MANA, twin harvest
- Capture — drill manifest records every frame: shape, time, channel, source
- Correlate — widsdiffer.py joins drill events vs WIDS alerts within 120s window
- Measure — 2/5 shapes detected (deauth by correlation, twin by RADIUS join), 3 blind
- Diagnose — blind shapes map to sensor gaps (ch 44) + missing inventory-join rule
- Fix — sensor added to ch 44, correlation rules deployed; re-drill next quarter: 4/5
Building Your Own Tool
Section titled “Building Your Own Tool”sensorcover.py — the sensor coverage analyzer: from sensor positions (floor-plan coordinates) and capture data (per-channel signal visibility from WI1/WI6 captures), computes the per-channel/per-position coverage grid, flags blind spots, and recommends sensor additions — turning sensor placement from cable-convenience into a coverage design.
Design decisions
Section titled “Design decisions”- Channel × position grid, not floor-plan art. The deliverable is a grid (which channels are visible from which positions) because WIDS coverage is per-channel: a sensor at position P that doesn’t hop to channel 44 provides zero coverage there regardless of its floor position.
- Captures as truth. Coverage comes from what sensors actually saw in drill captures (sensor alert metadata + channel), not from radio-propagation models — measured coverage survives building changes that models don’t.
- Recommendations as gaps, not placements. The tool reports where coverage is missing (channel + position cells) and lets humans choose placements — placement optimization is a facilities conversation with constraints the tool doesn’t know.
- WIDS-vendor-agnostic. The input is the drill/alert CSV shape from widsdiffer — any vendor’s alerts normalize into the same coverage math.
Full source
Section titled “Full source”#!/usr/bin/env python3"""sensorcover.py — WIDS sensor coverage grid from drill captures.Usage: python sensorcover.py --sensors sensors.json \ --alerts drill_alerts.csv [--channels 1,6,11,36,44,149]sensors.json: [{"name":"s1","x":10,"y":5,"channels":[1,6,11]}]alerts CSV: widsdiffer shape (timestamp,rule,sensor,details)stdlib only."""import argparse, csv, json, sysfrom collections import defaultdict
def load_sensors(path): try: return json.load(open(path, encoding="utf-8")) except (OSError, json.JSONDecodeError) as e: sys.exit(f"sensor file error: {e}")
def alert_channels(alerts): """Extract channels seen per sensor from alert details.""" per_sensor = defaultdict(set) for a in alerts: s = a.get("sensor", "?") details = a.get("details", "") # convention: details contain 'ch=<n>' from drill tags if "ch=" in details: try: ch = int(details.split("ch=")[1] .split()[0].strip(",")) per_sensor[s].add(ch) except (ValueError, IndexError): continue else: per_sensor[s].add(-1) # unknown channel marker return per_sensor
def main(): ap = argparse.ArgumentParser() ap.add_argument("--sensors", required=True) ap.add_argument("--alerts", required=True) ap.add_argument("--channels", default="1,6,11,36,44,149") ap.add_argument("--out") args = ap.parse_args() sensors = load_sensors(args.sensors) alerts = [] with open(args.alerts, encoding="utf-8", newline="") as fh: for row in csv.DictReader(fh): alerts.append(row) seen = alert_channels(alerts) channels = [int(c) for c in args.channels.split(",")] print("== sensor channel coverage ==") print(f"{'sensor':<12} {'pos':<10} " f"{'channels seen (of plan)':<26} gaps") print("-" * 70) grid = defaultdict(set) # channel -> sensors covering for s in sensors: saw = seen.get(s["name"], set()) planned = set(s.get("channels", channels)) observed = saw & set(channels) gaps = sorted(planned - observed) for ch in observed: grid[ch].add(s["name"]) print(f"{s['name']:<12} " f"({s.get('x','?')},{s.get('y','?')}) " f"{sorted(observed) if observed else 'NONE':<26} " f"{gaps if gaps else '-'}") print("\n== channel-level coverage ==") for ch in channels: cov = grid.get(ch, set()) state = "covered" if cov else "BLIND" print(f" ch {ch:<4} {state:<8} " f"sensors: {sorted(cov) or '-'}") blind = [ch for ch in channels if not grid.get(ch)] if blind: print(f"\n[!] blind channels: {blind} — " f"add sensors or hop plans; drills on these " f"channels are invisible by construction") if args.out: json.dump({"channels": {str(c): sorted( grid.get(c, set())) for c in channels}, "blind": blind}, open(args.out, "w"), indent=2) print(f"[+] {args.out}")
if __name__ == "__main__": main()Walkthrough
Section titled “Walkthrough”- The channel extraction (lines 21-35) parses the drill-tag convention (
ch=<n>in alert details) — the drill manifest writes the channel into its frames, the WIDS echoes it in alert details, and the coverage math gets per-sensor channel truth without vendor API dependencies. - The grid (lines 55-63) inverts the per-sensor view into per-channel coverage: for each planned channel, which sensors actually observed it — the WIDS coverage question, answered from measured drill traffic rather than vendor datasheets.
- The blind-channel summary (lines 66-69) is the deliverable: channels no sensor saw during the drill are invisible by construction, and the finding text says exactly that — drills on blind channels are the estate’s undetectable airspace, known now by name.
- The per-sensor gaps column (line 59) distinguishes planned-but-unobserved channels (hop-plan or hardware issues) from observed coverage — the operational detail that separates “add a sensor” from “fix the hop config”.
Compilation and test procedure
Section titled “Compilation and test procedure”run the authorized drill across shapes and channels
Section titled “run the authorized drill across shapes and channels”$ python drillkit.py —shapes paced-deauth,cloned-beacon
—channels 6,44 —window 300 # (from your lab toolkit)
WIDS + SIEM capture the window’s alerts
Section titled “WIDS + SIEM capture the window’s alerts”$ cat > sensors.json <<‘EOF’ [{“name”:“s1”,“x”:10,“y”:5,“channels”:[1,6,11]}, {“name”:“s2”,“x”:30,“y”:5,“channels”:[36,149]}] EOF
$ python widsdiffer.py —drill drill_events.json
—alerts wids_alerts.csv —out cov.md
| shape | sent | detected | missed | rules | sensors |
|---|---|---|---|---|---|
| paced-deauth | 12 | 4 | 8 | corr-rule | s1 |
| cloned-beacon | 6 | 0 | 6 | - | - |
- blind shapes (never detected):
- cloned-beacon (6 sent)
$ python sensorcover.py —sensors sensors.json
—alerts wids_alerts.csv —channels 1,6,11,36,44
== channel-level coverage ==
ch 1 covered sensors: [‘s1’]
ch 44 BLIND sensors: ’-’
[!] blind channels: [44] — add sensors or hop plans
Detection considerations
Section titled “Detection considerations”The drill-and-differentiate loop is the wireless version of T9’s atomic suite: scheduled, measured, trended — and its findings feed the three real fixes (correlation rules, sensor adds, inventory joins) rather than threshold tweaking. Your own tooling hygiene: the differentiator and coverage tools read CSV/JSON only; the transmission steps are the drill kit’s, gated by the same authorization architecture as every T-series exercise. The vendor relationship matters: share the blind-shape findings with your WIDS vendor (their rules may need your deployment’s specifics) and require the drill as an acceptance test at procurement — “detects rogue APs” is a claim your clone-drill verifies in an afternoon. Wazuh/SIEM ingestion of WIDS alerts [verify per vendor] is the join that makes RADIUS + endpoint + WIDS correlation possible — the only detection class that survives pacing and cloning. The standing metrics: drill coverage percentage per shape, blind-channel count, and mean time-to-classify drill alerts (the SOC’s tag-and-close speed from T2’s convention) — three numbers that make the wireless detection estate as measurable as the malware one.
Improvements to add
Section titled “Improvements to add”- Physical localization join: multi-sensor RSSI triangulation of drill sources — coverage and position finding in one drill.
- Alert-latency profiling: distribution of transmit-to-alert delay per shape/sensor — the tuning data for the correlation window.
- Client-side posture join: correlate drill twin-associations with MDM/endpoint network-join logs (the client-side half of the story).
- Continuous drills: lightweight scheduled probe-shape drills (passive-only) feeding the coverage trend weekly.
- WIDS-rule mapping: vendor rule IDs → ATT&CK-ish wireless technique mapping in the inventory CSV, completing the program matrix.
Detection — Defender View
Section titled “Detection — Defender View”| Signal | Source | ID | Notes |
|---|---|---|---|
| Deauth from non-inventory MAC | Correlation rule (SIEM) | source-inventory join | Survives pacing evasion |
| Same BSSID on two channels | Multi-sensor correlation | physics check | Survives cloning |
| Drill shapes detected | widsdiffer | coverage matrix | Validated vs blind |
| Blind channels | sensorcover | coverage grid | Placement findings |
| Alert latency distribution | widsdiffer | per-shape timing | Correlation-window tuning |
| RADIUS failure bursts (drift) | RADIUS analytics | per-BSSID | Twin-harvest signature |
| Client assoc to unknown AP | MDM/EDR joins | endpoint posture | Client-side half |
| Noise-floor anomalies | Spectrum monitor | jam detection | Precursor signature |
| Alert classification latency | SOC drill windows | tag-and-close timing | Marker discipline check |
| Wazuh wireless rule coverage | HIDS/SIEM | [verify rule IDs per deployment] | The correlation layer |
Evasion Techniques
Section titled “Evasion Techniques”This module’s evasion catalogue is the point — but the meta-evasion, the one that outlasts every specific shape, is operating below the aggregation floor: every WIDS rule has an implicit volume assumption (storms, floods, bursts), and an adversary who accepts patience — one frame, one association, one harvest per hour — presents the telemetry with single events that only correlation can score. The defender’s counter-evolution is structural: rate rules are the cheapest to write and the cheapest to evade, so the mature WIDS architecture moves value into joins — frame × inventory (source MACs that aren’t yours), frame × physics (same identity, two channels), frame × position (signal from where nothing should be), frame × identity-history (client associated to an AP it has never seen). The cloning arms race converges to the same place: frame-level checks die to depth-cloning, but the physics check (one radio, two channels) and the inventory check (BSSID where your AP isn’t) survive any clone. The coverage asymmetry is the defender’s structural weakness: sensors sit where cabling allows, adversaries operate where coverage doesn’t — countered by making coverage measured (the grid) instead of assumed, and by client-side telemetry (RADIUS, MDM network-join logs) that covers the air your sensors don’t. And the legal asymmetry runs the defender’s way at the extremes: jamming is loud and illegal, so the jam-based evasion class is bounded — which is worth knowing when threat-modeling: the adversary who stays legal is the adversary your correlations can catch.
⚠️ What caught me: our first WIDS drill scored 5/5 shapes detected, and I nearly filed the coverage matrix green — then I noticed all five detections came from one sensor and one rule (the deauth storm rule), and the “detected” clones were caught by the legacy ‘MAC OUI mismatch’ heuristic, not by anything that would survive a fleet-matched clone. The drill had measured that our sensors see the airspace; it hadn’t measured that our rules understand it. The redesign split the score: per-shape × per-detection-class coverage (rate / signature / correlation / coverage), and the honest number — correlation-class coverage — started at 20%. That number, not the 5/5, is what got the sensor budget approved; a green matrix that hides which class caught what is just noise with formatting.
Lab Practice
Section titled “Lab Practice”- Run the authorized 5-shape drill against your lab WIDS (or a SIEM-fed sensor): paced deauth, cloned beacon, blind-channel op, quiet MANA, twin harvest — then
widsdiffer.pyfor the coverage matrix. - Implement the correlation rules the drill exposes (source-inventory deauth join, same-BSSID-two-channel check) in your SIEM and re-drill — the coverage delta is the correlation class’s value, measured.
- Build the sensor grid with
sensorcover.pyfrom your sensor inventory + drill alerts; identify the blind channels and physically verify one (walk there with a client and confirm the invisibility). - Clone-depth experiment: beacon-clone your lab AP at two depths (SSID-only, full-IE) and observe which detector layer catches each — the arms race, calibrated on your own estate.
- Trend it: schedule a lightweight monthly drill (passive shapes only) and trend the coverage line for a quarter — the wireless version of the T9 regression loop.
Interview Questions
Section titled “Interview Questions”- Technical: For each WIDS detection class (rate, signature, coverage, correlation), name its evasion shape and the defender counter that survives it.
- Technical: Why does the same-BSSID-on-two-channels check survive full beacon cloning, and what deployment requirement does it impose?
- Scenario: Your drill scores 5/5 detected, all by one rate rule. What does that actually measure, and how do you redesign the score?
- Conceptual: Why is correlation-based detection the only class that survives pacing and cloning — and what data joins does it require?
- Conceptual: Where does client-side telemetry (RADIUS, MDM) cover the gaps that WIDS coverage cannot, and what join makes that real?
- Deep-dive: Design the annual wireless detection validation: drill shapes, sensor grid, per-class scoring, and the procurement acceptance test.
- Practical: Leadership sees “WIDS: deployed” on the compliance matrix. What does your drill coverage number say, and how do you present the gap without triggering vendor-defensive pushback?
Related Modules
Section titled “Related Modules”WI1 (Wireless Fundamentals & Recon (802.11)) · WI2 (WPA2-PSK Cracking (Handshake Capture)) · WI4 (Enterprise Wi-Fi & Evil Twin) · WI6 (RF & SDR Fundamentals) · BT12 (Wireless IDS)