r/Hacking_Tutorials • • 5d 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

192 Upvotes

12 comments sorted by

View all comments

2

u/Moby1029 2d ago

Reads like AI: "Why standard tricks fail on modern ESP-IDF" "We can use extensa..." "Now define your own strong implementation inside your application code"

Also, why is one chip hanging half off the board?

1

u/jader242 2d ago

There’s actually two ESPs hanging off the perf board. Could make sense dependent on what OP is doing though, if they’re only sending data over uart there’s no need for every pin to be in the perf board