Raw 802.11 frame injection on ESP-IDF v5.x / v6.x. A one-command,
reversible patch that re-enables the full set of 802.11 frame types
(Authentication, Deauth, Assoc, Reassoc, Disassoc, RTS/CTS/ACK, …) for
transmission via esp_wifi_80211_tx(), which Espressif's shipped
libnet80211.a restricts to a short whitelist (Beacon, Probe
Req/Resp, Action, non-QoS Data).
Includes:
- The patch itself (
patch/patch_libnet80211.sh) —objcopy --weaken-symbolon one symbol, with backup and--revert. - A minimal demo firmware (
example/) that injects five frame variants and reports results over serial. - Pcap, Hostapd log, and serial-log evidence that the patch enables SAE Commit (Authentication subtype 11) injection on ESP32 — the motivating use case for this work.
- The full engineering writeup as a research paper
(
docs/esp32_raw_tx_report.pdf).
Earlier community projects (wsl_bypasser, esp32-wifi-penetration-tool,
Atomic-SAQuery, …) relied on a strong-C-symbol override of the blob
function ieee80211_raw_frame_sanity_check. That technique silently
stopped working around ESP-IDF v5: the blob symbol's binding changed
from WEAK to STRONG, so the override now fails at link time with
a multiple-definition error.
The obvious fallback (-Wl,--wrap=ieee80211_raw_frame_sanity_check)
also silently fails: GNU ld --wrap only rewrites undefined,
inter-object references, but the call that matters —
esp_wifi_80211_tx → sanity_check — is intra-object inside
ieee80211_output.o, invisible to --wrap.
This repo documents the breaking change and ships a working alternative:
flip the blob symbol back to WEAK with objcopy --weaken-symbol,
then provide the override in app code. Global strong-beats-weak
resolution rebinds every reference, including the intra-object one.
See docs/esp32_raw_tx_report.pdf for the complete engineering trace
including disassembly of the frame-type whitelist, three failed
attempts, and end-to-end verification evidence.
# Assumes IDF is at $IDF_PATH. Override with LIBNET80211=... if needed.
bash patch/patch_libnet80211.sh
# Verify (should print "W" after; "T" means not patched)
xtensa-esp32-elf-nm $IDF_PATH/components/esp_wifi/lib/esp32/libnet80211.a \
| grep ieee80211_raw_frame_sanity_check
# 0000005c W ieee80211_raw_frame_sanity_check ← correctThe patch is idempotent; running it again is a no-op. To revert:
bash patch/patch_libnet80211.sh --revertA backup of the original archive is saved as libnet80211.a.bak on
first run.
cd example
idf.py set-target esp32
idf.py build flash monitorSerial output should cycle through five variants every 4 s, each
reporting esp_wifi_80211_tx() -> ESP_OK:
I (xxxxx) INJ-DEMO: >>> Sending V0 Deauth (control) esp_wifi_80211_tx() -> ESP_OK
I (xxxxx) INJ-DEMO: >>> Sending V1 Open-Auth (baseline) esp_wifi_80211_tx() -> ESP_OK
I (xxxxx) INJ-DEMO: >>> Sending V2 SAE-Commit bare esp_wifi_80211_tx() -> ESP_OK
I (xxxxx) INJ-DEMO: >>> Sending V3 SAE-Commit full (malformed) esp_wifi_80211_tx() -> ESP_OK
I (xxxxx) INJ-DEMO: >>> Sending V4 SAE-Commit valid (scalar=2,E=G)
esp_wifi_80211_tx() -> ESP_OK
If instead you see E (xxxxx) wifi:unsupport frame type: 0b0 on every
cycle, the patch did not take; re-run patch_libnet80211.sh and
idf.py fullclean build flash.
Point another Wi-Fi adapter in monitor mode on the same channel and
run tcpdump / Wireshark. See evidence/ for an example capture.
Table from the research paper (Table 1):
| Frame Type | Subtypes Permitted stock | Subtypes Rejected stock, Enabled by this patch |
|---|---|---|
| MGMT (0) | 4 (ProbeReq), 5 (ProbeResp), 6 (TimingAd), 7, 8 (Beacon), 13 (Action) | 0 Assoc, 1 AssocResp, 2 Reassoc, 3 ReassocResp, 9 ATIM, 10 Disassoc, 11 Auth, 12 Deauth |
| CTRL (1) | (none) | all (RTS, CTS, ACK, BlockAck, …) |
| DATA (2) | 0–7 (non-QoS) | 8–15 (QoS variants) |
- Downstream constraints still apply. The patch only removes the
sanity_checkgate. The MAC hardware, MLME state machine, and TX scheduler still apply their own restrictions. In practice this means mgmt frames inject reliably; control frames (RTS/CTS/ACK) get sent but may be too user-space-late for proper IEEE 802.11 timing (SIFS deadline). For content fuzzing, timing doesn't matter; for protocol-conforming interactions, it does. - This modifies the ESP-IDF install globally. Every project you
build against that IDF will link against the patched archive.
patch_libnet80211.sh --revertrestores the stock file from backup. - TX bypass only. This does nothing to RX — monitor-mode promiscuous capture works out of the box in ESP-IDF.
- Tested on ESP-IDF v6.1-dev against ESP32 (classic). Should work
on v5.x and other targets (ESP32-S2/S3/C-series) if the symbol
binding is
T— check withnmfirst, see the "Verify" step above.
The techniques here enable raw 802.11 frame transmission, which has both research/defensive uses (fuzzing, PMF testing, side-channel measurement — the motivating use case) and adversarial uses (deauth storms against networks you don't own). Only operate against Wi-Fi networks and devices you own or have explicit written authorization to test. Unauthorized operation against third-party infrastructure is illegal in most jurisdictions.
The author uses this patch inside an isolated laboratory environment at NHSM, Algiers, for a Master's thesis on WPA3-SAE side-channel analysis.
.
├── README.md — this file
├── LICENSE — MIT
├── patch/
│ └── patch_libnet80211.sh — the patch script
├── example/ — minimal demo IDF project
│ ├── CMakeLists.txt
│ └── main/
│ ├── CMakeLists.txt
│ └── main.c
├── docs/
│ └── esp32_raw_tx_report.pdf — full engineering writeup
└── evidence/
├── README.md — what each file proves
├── sae_injection_first_capture.pcap — monitor-mode OTA capture
├── tshark_injected_frames.txt — decoded frame list
├── hostapd_v4_roundtrip.log — Hostapd parse + response
└── serial_log_post_bypass.txt — ESP32 serial, no reject log
risinek/wsl_bypasser— the original same-name-override approach. Works on IDF ≤ v4.x; silently breaks on v5+ as documented here.risinek/esp32-wifi-penetration-tool— depends onwsl_bypasser; same limitation.Matheus-Garbelini/esp32_esp8266_attacks— academic CVE PoCs, limited to beacon-only injection.- Vanhoef & Ronen, Dragonblood: Analyzing the Dragonfly Handshake of WPA3 and EAP-pwd, IEEE S&P 2020 — the SAE PWE side-channel that motivates this project.
If you use this patch or the writeup in academic work, please cite:
Mehdi Mansour. "Enabling Raw 802.11 Management Frame Injection on
ESP-IDF v6: A Linker-Level Analysis of ieee80211_raw_frame_sanity_check
and a Reproducible Bypass." Technical report, École Nationale
Supérieure de Mathématiques (NHSM), Algiers, October 2026.
Mehdi Mansour — Dept. of Cryptography, Coding and Security, NHSM Algiers. Contact: mahdi.mansour@nhsm.edu.dz · LinkedIn
MIT. See LICENSE.