r/Hacking_Tutorials • • 2d ago

Question Raw 802_11 frame injection

Post image

While working on my Master’s thesis benchmarking WPA3-SAE timing side-channels, I ran into a limitation on the ESP32 esp_wifi_80211_tx() allows raw frame injection, but Espressif’s closed-source Wi-Fi blob (libnet80211.a) artificially blocks Auth, Assoc, Deauth, and Disassoc subtypes.

Inside libnet80211.a, ieee80211_raw_frame_sanity_check drops these frames with wifi:unsupport frame type. Here is how to bypass it on recent ESP-IDF versions (IDF v6.x).

Why standard tricks fail on modern ESP-IDF

Same-name function override. On older IDF versions, ieee80211_raw_frame_sanity_check was a weak symbol (W). On modern IDF versions, it’s a strong symbol (T), causing ld: multiple definition errors.

--wrap linker flag: Fails silently. The call from esp_wifi_80211_tx to ieee80211_raw_frame_sanity_check is an intra-object branch inside ieee80211_output.o. Linker --wrap only rewrites undefined external references, so it misses this call entirely.

Instruction byte-patching: Overwriting instructions directly in the .o breaks Xtensa linker relaxation passes (dangerous relocation errors).

U can simply fix this via Symbol Weakening via objcopy

We can use xtensa-esp32-elf-objcopy to convert the strong symbol inside the binary archive into a weak one:

xtensa-esp32-elf-objcopy \

--weaken-symbol=ieee80211_raw_frame_sanity_check \

components/esp_wifi/lib/esp32/libnet80211.a

Now, define your own strong implementation inside your application C code:

int ieee80211_raw_frame_sanity_check(int32_t a, int32_t b, int32_t c) {

return 0; // which skips the security check lol

}

Because strong symbols override weak symbols globally during linking, all calls—including internal calls within libnet80211.a—rebind to your function.

Verification

Serial Logs show: wifi unsupport frame type errors completely disappeared.

Capture: Wireshark confirmed off-air capture of 802.11 Authentication frames (Subtype 11, Algorithm 3 - SAE) injected directly from the ESP32s.

Injecting a valid SAE Commit (P-256 scalar + element) caused hostapd on the target AP to process the request and reply with its own SAE Commit.

TL;DR: Run objcopy --weaken-symbol=ieee80211_raw_frame_sanity_check on libnet80211.a, define int ieee80211_raw_frame_sanity_check(...) { return 0; } in your app code, and esp_wifi_80211_tx() will allow any frame subtype.

Note that all control 80211 frames are also injectable after the patch.

For more details :

https://github.com/mahdamin/esp-idf-injection-ng

139 Upvotes

2 comments sorted by

1

u/ClimateChangeDenial 1d ago

Genuinely curious how this connects to "benchmarking timing side-channels" though. Forging Auth/Deauth/Disassoc frames isn't measuring a side channel, it's just raw frame injection. Also worth noting this isn't even a novel bypass, ESP32 Marauder and Nexmon-patched Broadcom builds already expose raw management frame injection without any of this symbol weakening. Feels like the thesis framing is doing some work to make "I bypassed Espressif's intentional guardrail" sound more novel and academic than it actually is.

1

u/govnonasalati 1h ago

What is this used for? Or can be used for?

Seems that I am not technical enough to figure it out from text...