Skip to content

attack: add WPA3-SAE Transition Mode PMKID discovery via directed probe#70

Open
lasersharkkiller wants to merge 1 commit into
Ragnt:masterfrom
lasersharkkiller:feature/wpa3-sae-transition-discovery
Open

attack: add WPA3-SAE Transition Mode PMKID discovery via directed probe#70
lasersharkkiller wants to merge 1 commit into
Ragnt:masterfrom
lasersharkkiller:feature/wpa3-sae-transition-discovery

Conversation

@lasersharkkiller

Copy link
Copy Markdown

Problem

AngryOxide's M1-retrieval (PMKID) attack only fires when an AP has a confirmed PSK AKM in its RSN IE. Some WPA3-SAE Transition Mode APs advertise only SAE in their beacon RSN IE while still including PSK in their probe response RSN IE — a valid 802.11 configuration. These APs were invisible to PMKID collection because the PSK flag was never set from the beacon alone.

What this PR adds

1. APFlags::is_sae_transition_mode() (src/devices.rs) Helper that returns true when an AP advertises both SAE and PSK AKMs in its RSN IE — the canonical definition of WPA3-SAE Transition Mode. Used by attack code to distinguish transition mode from plain WPA2.

2. build_probe_request_ap_ssid() (src/tx.rs) New frame builder that sends a unicast probe request directly to a specific AP MAC address, carrying the AP's SSID. Unlike the existing build_probe_request_directed (broadcast + SSID) and build_probe_request_target (unicast + no SSID), this variant is addressed to the AP so only that AP responds, and carries the SSID so the AP replies with its full probe-response RSN IE.

3. transition_probe_attack() (src/attack.rs) New attack function that runs in the beacon processing loop. When an AP is seen advertising SAE but PSK support has not yet been confirmed (rsn_akm_psk != Some(true)) and no probe response has been received yet (pr_station.is_none()), a unicast probe request is sent to the AP every 32 beacons (~3 s at typical beacon rates) until a response arrives.

Gate conditions (all must be true to fire):

  • disable_pmkid is false
  • notx is false
  • AP is a target and not whitelisted
  • No complete handshake already collected
  • rsn_akm_sae == Some(true)
  • rsn_akm_psk != Some(true) (PSK not yet confirmed)
  • pr_station.is_none() (no probe response received yet)
  • Has an SSID
  • beacon_count % 32 == 0 (rate limit)

4. m1_retrieval_attack / m1_retrieval_attack_phase_2 (src/attack.rs) Both functions now detect transition mode (is_sae_transition_mode()) and emit distinct status log messages:

  • Phase 1: "M1 Retrieval (SAE Transition) - Sent Authentication Req"
  • Phase 2: "M1 Retrieval (SAE Transition PSK Downgrade) - Sent Association Req"

The association request continues to advertise only PSK AKM (SAE stripped), forcing the AP onto its WPA2 code path which returns an EAPOL M1 that may contain a PSK-derived PMKID crackable offline.

5. Beacon loop call site (src/main.rs)

transition_probe_attack is called just before m1_retrieval_attack on every beacon. For APs that already have PSK confirmed the gate returns immediately with no overhead.

Full event cycle for a beacon-SAE-only transition mode AP

beacon (SAE only, no PSK in RSN)
→ transition_probe_attack fires (beacon_count % 32 == 0)
→ unicast probe request sent to AP with its SSID
→ AP sends probe response (full RSN IE: SAE + PSK)
→ probe response handler: update_with() sets rsn_akm_psk=Some(true),
pr_station=Some(...)
→ m1_retrieval_attack fires immediately (existing hook at line ~1464)
→ OpenSystem authentication request sent
→ AP responds auth_seq=2
→ m1_retrieval_attack_phase_2: PSK-only assoc request (SAE stripped)
→ AP sends EAPOL M1 containing PSK-derived PMKID
→ PMKID written to .hc22000

Discovery and PMKID collection collapse into a single probe/response event cycle rather than requiring a beacon that already contains PSK.

## Problem

AngryOxide's M1-retrieval (PMKID) attack only fires when an AP has a
confirmed PSK AKM in its RSN IE.  Some WPA3-SAE Transition Mode APs
advertise only SAE in their beacon RSN IE while still including PSK in
their probe response RSN IE — a valid 802.11 configuration.  These APs
were invisible to PMKID collection because the PSK flag was never set
from the beacon alone.

## What this PR adds

### 1. `APFlags::is_sae_transition_mode()` (src/devices.rs)
Helper that returns `true` when an AP advertises both SAE and PSK AKMs
in its RSN IE — the canonical definition of WPA3-SAE Transition Mode.
Used by attack code to distinguish transition mode from plain WPA2.

### 2. `build_probe_request_ap_ssid()` (src/tx.rs)
New frame builder that sends a unicast probe request directly to a
specific AP MAC address, carrying the AP's SSID.  Unlike the existing
`build_probe_request_directed` (broadcast + SSID) and
`build_probe_request_target` (unicast + no SSID), this variant is
addressed to the AP so only that AP responds, and carries the SSID so
the AP replies with its full probe-response RSN IE.

### 3. `transition_probe_attack()` (src/attack.rs)
New attack function that runs in the beacon processing loop.  When an
AP is seen advertising SAE but PSK support has not yet been confirmed
(rsn_akm_psk != Some(true)) and no probe response has been received
yet (pr_station.is_none()), a unicast probe request is sent to the AP
every 32 beacons (~3 s at typical beacon rates) until a response
arrives.

Gate conditions (all must be true to fire):
  - disable_pmkid is false
  - notx is false
  - AP is a target and not whitelisted
  - No complete handshake already collected
  - rsn_akm_sae == Some(true)
  - rsn_akm_psk != Some(true)  (PSK not yet confirmed)
  - pr_station.is_none()       (no probe response received yet)
  - Has an SSID
  - beacon_count % 32 == 0     (rate limit)

### 4. m1_retrieval_attack / m1_retrieval_attack_phase_2 (src/attack.rs)
Both functions now detect transition mode (is_sae_transition_mode())
and emit distinct status log messages:
  - Phase 1: "M1 Retrieval (SAE Transition) - Sent Authentication Req"
  - Phase 2: "M1 Retrieval (SAE Transition PSK Downgrade) - Sent Association Req"

The association request continues to advertise only PSK AKM (SAE
stripped), forcing the AP onto its WPA2 code path which returns an
EAPOL M1 that may contain a PSK-derived PMKID crackable offline.

### 5. Beacon loop call site (src/main.rs)
`transition_probe_attack` is called just before `m1_retrieval_attack`
on every beacon.  For APs that already have PSK confirmed the gate
returns immediately with no overhead.

## Full event cycle for a beacon-SAE-only transition mode AP

  beacon (SAE only, no PSK in RSN)
    → transition_probe_attack fires (beacon_count % 32 == 0)
    → unicast probe request sent to AP with its SSID
    → AP sends probe response (full RSN IE: SAE + PSK)
    → probe response handler: update_with() sets rsn_akm_psk=Some(true),
                               pr_station=Some(...)
    → m1_retrieval_attack fires immediately (existing hook at line ~1464)
    → OpenSystem authentication request sent
    → AP responds auth_seq=2
    → m1_retrieval_attack_phase_2: PSK-only assoc request (SAE stripped)
    → AP sends EAPOL M1 containing PSK-derived PMKID
    → PMKID written to .hc22000

Discovery and PMKID collection collapse into a single probe/response
event cycle rather than requiring a beacon that already contains PSK.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant