
Injection de trames 802.11 brutes sur ESP-IDF v5+/v6+ via un patch en une seule commande objcopy --weaken-symbol. Active les trames d'authentification (SAE Commit), Deauth, Reassoc, Disassoc et de contrôle (RTS/CTS/ACK) via esp_wifi_80211_tx()
Injection de trames 802.11 brutes sur ESP-IDF v5.x / v6.x. Un correctif en une seule commande et réversible qui réactive l'ensemble complet des types de trames 802.11 (Authentication, Deauth, Assoc, Reassoc, Disassoc, RTS/CTS/ACK, …) pour la transmission via esp_wifi_80211_tx(), que le libnet80211.a fourni par Espressif restreint à une courte liste blanche (Beacon, Probe Req/Resp, Action, Data non-QoS).
Comprend :
patch/patch_libnet80211.sh) — objcopy --weaken-symbol sur un symbole, avec sauvegarde et --revert.example/) qui injecte cinq variantes de trames et rapporte les résultats via le port série.docs/esp32_raw_tx_report.pdf).Des projets communautaires antérieurs (wsl_bypasser, esp32-wifi-penetration-tool, Atomic-SAQuery, …) reposaient sur une redéfinition par symbole C fort de la fonction du blob ieee80211_raw_frame_sanity_check. Cette technique a cessé de fonctionner silencieusement vers ESP-IDF v5 : la liaison du symbole du blob est passée de WEAK à STRONG, de sorte que la redéfinition échoue désormais à l'édition de liens avec une erreur de définition multiple.
La solution de repli évidente (-Wl,--wrap=ieee80211_raw_frame_sanity_check) échoue également silencieusement : le ld --wrap de GNU ne réécrit que les références non définies entre objets, mais l'appel qui compte — esp_wifi_80211_tx → sanity_check — est intra-objet à l'intérieur de ieee80211_output.o, invisible pour --wrap.
Ce dépôt documente le changement cassant et fournit une alternative fonctionnelle : repasser le symbole du blob à WEAK avec objcopy --weaken-symbol, puis fournir la redéfinition dans le code de l'application. La résolution globale où le fort l'emporte sur le faible relie à nouveau chaque référence, y compris celle intra-objet.
Voir docs/esp32_raw_tx_report.pdf pour la trace d'ingénierie complète, incluant le désassemblage de la liste blanche des types de trames, trois tentatives infructueuses et les preuves de vérification de bout en bout.
# 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 ← correct
Le patch est idempotent ; l'exécuter à nouveau n'a aucun effet. Pour annuler :
bash patch/patch_libnet80211.sh --revert
Une sauvegarde de l'archive d'origine est enregistrée sous libnet80211.a.bak lors
de la première exécution.
cd example
idf.py set-target esp32
idf.py build flash monitor
La sortie série doit alterner entre cinq variantes toutes les 4 s, chacune
rapportant 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
Si vous voyez plutôt E (xxxxx) wifi:unsupport frame type: 0b0 à chaque
cycle, le patch n'a pas été appliqué ; relancez patch_libnet80211.sh et
idf.py fullclean build flash.
Pointez un autre adaptateur Wi-Fi en mode moniteur sur le même canal et
lancez tcpdump / Wireshark. Voir evidence/ pour un exemple de capture.
Tableau issu de l'article de recherche (Tableau 1) :
| Type de trame | Sous-types autorisés en stock | Sous-types rejetés en stock, activés par ce 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) | (aucun) | tous (RTS, CTS, ACK, BlockAck, …) |
| DATA (2) | 0–7 (non-QoS) | 8–15 (variantes QoS) |
sanity_check. Le matériel MAC, la machine à états
MLME et l'ordonnanceur TX appliquent toujours leurs propres restrictions.
En pratique, cela signifie que les trames mgmt s'injectent de manière
fiable ; les trames de contrôle (RTS/CTS/ACK) sont bien envoyées mais
peuvent arriver trop tard depuis l'espace utilisateur pour respecter la
synchronisation IEEE 802.11 appropriée (échéance SIFS). Pour le fuzzing
de contenu, la synchronisation n'a pas d'importance ; pour des
interactions conformes au protocole, si.patch_libnet80211.sh --revert restaure le fichier d'origine depuis la
sauvegarde.T — vérifiez d'abord avec nm, voir l'étape « Vérifier » ci-dessus.Les techniques présentées ici permettent la transmission brute de trames 802.11, ce qui a à la fois des usages de recherche/défense (fuzzing, tests PMF, mesure de canal auxiliaire — le cas d'usage motivant) et des usages malveillants (tempêtes de deauth contre des réseaux que vous ne possédez pas). N'opérez que contre des réseaux et appareils Wi-Fi que vous possédez ou pour lesquels vous disposez d'une autorisation écrite explicite de test. L'utilisation non autorisée contre une infrastructure tierce est illégale dans la plupart des juridictions.
L'auteur utilise ce patch dans un environnement de laboratoire isolé à NHSM, Alger, pour un mémoire de Master sur l'analyse de canal auxiliaire WPA3-SAE.
.
├── 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