ESP32 WiFi отсылка каких попало пакетов

Здравствуйте, товарищи. Мы сегодня будем разблокировать интересные возможности
ESP32S3, ESP32S2 и ESP32. Написанное скорее всего будет работать так же на другой модели, но тестировалось
все только на ESP32-S3.

ВВЕДЕНИЕ В ПРОБЛЕМУ

Кратко: Espressif, начиная с определенной версии своего SDK вытащила на свет божий ранее
скрытую функцию

  esp_err_t esp_wifi_80211_tx(wifi_interface_t ifx, const void *buffer, int len, bool en_sys_seq)

Да, это то, что вы подумали - функция отправки сырого WiFi кадра. Но, т.к. такой инструмент
может быть потенциально опасным в умелых руках, инженеры их Espressif ограничили типы WiFi пакетов,
которые можно отослать с помощью этой функции до совсем неинтересного набора:

“Attention Currently only support for sending beacon/probe request/probe
response/action and non-QoS data frame”

Будем избавляться от этого ограничения, в среде Arduino. Инструкции, “что делать“, начинаются с “ИСПРАВЛЕНИЯ“. А пока немного теории.

WiFi, которым славятся чипы Espressif, содержит как открытую, так и precompiled часть, причем, как всегда,
самое интересно находится в закрытой части: интересующие нас функции находятся
приемущественно в библиотеке libieee80211.a (устанавливается она вместе ESP32 board support в Arduino IDE).

Вот туда-то мы и полезем (поиск в каталогах вам в помощь).

2025-09-23  06:24 PM             4,848 libcore.a                   
2025-09-23  06:24 PM            62,174 libespnow.a                 
2025-09-23  06:24 PM           995,432 libmesh.a                   
2025-09-23  06:24 PM         1,387,762 libnet80211.a       <----------- Это
2025-09-23  06:24 PM           706,754 libpp.a                     
2025-09-23  06:24 PM           196,186 libsmartconfig.a            
2025-09-23  06:24 PM            52,466 libwapi.a                                  

Для начала распакуем библиотеку командой “ar x libieee80211.a” (если у вас linux или windows+cygwin),
должна появится куча файликов, из которых нам нужно выбрать тот, в котором находится наша

  esp_wifi_80211_tx()

Это будет файл ieee80211_output.o

Если теперь этот файл загрузить в Ghidra (дизассемблер\декомпайлер), отыскать там esp_wifi_80211_tx
то увидим примерно такое:

(код отредактирован человеком :))

int esp_wifi_80211_tx(int Interface,const void *Buffer,int Length,bool En_Sys_Seq) {

  int ret;
  char *eb;
.....
.....
.....
  // Если ret == 0, то пакет хороший, а если нет - то пакет негодный.
  //
  if ((ret = ieee80211_raw_frame_sanity_check(Interface,Buffer,Length,En_Sys_Seq)) == 0) {
    _mutex_lock(_g_wifi_global_lock);
    // Судя по всему - аллокация памяти, копирование пакета
    // 1- похоже на "true"
    //
    eb = ic_ebuf_alloc(Buffer,1,Length); 
    if (eb == 0) {
      _mutex_unlock(_g_wifi_global_lock);    
      // Память кончилась :(
      ret = 0x101;
    } else {
.....
.....
.....
      ieee80211_post_hmac_tx(eb);
      _mutex_unlock(_g_wifi_global_lock);
    }

  return ret; // должен быть 0 (ESP_OK)
}

В самом начале кода можно увидеть саму проверку - вызов ieee80211_raw_frame_sanity_check().
Как-то нам теперь надо сделать так, чтобы этот sanity_check всегда возвращал 0, т.е. “проверка пройдена успешно”.

ИСПРАВЛЕНИЯ

Ну и сделаем мы это самым прямым и официальным путем - пропросим линкер выкинуть родной код функции проверки и
использовать наш. А наш новый код “проверки” будет выглядеть вот так вот незатейливо:

int ieee80211_raw_frame_sanity_check( … ) {
return 0;
}

Находим файлик “ld_flags” из установки ESP32 Arduino Core (там их несколько, для каждого CPU - свой).
Там, в одну строчку, видимо , для лучшей читаемости записана длинная макаронина опций линкера:

-mlongcalls -nostartfiles -Wl,--cref -Wl,--defsym=IDF_TARGET_ESP32S3=0 -Wl,--no-warn-rwx-segments -Wl,--orphan-handling=warn -fno-rtti -fno-lto -Wl,--gc-sections -Wl,--warn-common -u nvs_sec_provider_include_impl -Wl,--wrap=ieee80211_raw_frame_sanity_check -Wl,--wrap=log_printf -u _Z5setupv -u _Z4loopv -u esp_app_desc -u esp_efuse_startup_include_func -u ld_include_highint_hdl -u start_app -u start_app_other_cores -u __ubsan_include -u esp_system_include_startup_funcs -Wl,--wrap=longjmp -u __assert_func -u esp_security_init_include_impl -Wl,--undefined=FreeRTOS_openocd_params -u app_main -u esp_libc_include_heap_impl -u esp_libc_include_reent_syscalls_impl -u esp_libc_include_syscalls_impl -u esp_libc_include_pthread_impl -u esp_libc_include_assert_impl -u esp_libc_include_getentropy_impl -u esp_libc_include_init_funcs -u esp_libc_init_funcs -u pthread_include_pthread_impl -u pthread_include_pthread_cond_var_impl -u pthread_include_pthread_local_storage_impl -u pthread_include_pthread_rwlock_impl -u pthread_include_pthread_semaphore_impl -u __cxa_guard_dummy -u __cxx_init_dummy -u esp_timer_init_include_func -u uart_vfs_include_dev_init -u include_esp_phy_override -u usb_serial_jtag_vfs_include_dev_init -u usb_serial_jtag_connection_monitor_include -u esp_vfs_include_console_register -u vfs_include_syscalls_impl -u esp_vfs_include_nullfs_register -u esp_system_include_coredump_init 

Добавляем туда -Wl,–wrap=ieee80211_raw_frame_sanity_check

Можно - в начало, можно - куда-нибудь в середину, это не имеет значения.

Добавляем в свой Arduino проект один Си файл, назовем его, скажем, itsfine.c:

#include <stdbool.h>

int __wrap_ieee80211_raw_frame_sanity_check(int ifx,const void *buffer,int len,bool auto_seq) {

  ifx = ifx;
  buffer = buffer;
  len = len;
  auto_seq = auto_seq;

  return 0;
}

Практически все готово. Последний, но важный штрих - сделать оригинальную функцию unresolved external

Добавить

extern int ieee80211_raw_frame_sanity_check(int,const void *,int,bool);

ну или

extern "C" int ieee80211_raw_frame_sanity_check(int,const void *,int,bool);

в файл с кодом, в котором предполагается использовать функцию отсылки кадра esp_wifi_80211_tx(),
например в ваш .ino файл.

Теперь, мы можем свободно пользоваться esp_wifi_80211_tx(), не опасаясь, что пакет будет отвергнут, как не
прошедший проверки.

Как это работает: линкер, при сборке проекта, заменит все вызовы к ieee80211_raw_frame_sanity_check() на вызовы
__wrap_ieee80211_raw_frame_sanity_check. Замена глобальная - т.е. она произойдет и в бинарных закрытых библиотеках:
закрытый код, который раньше вызывал ieee80211_raw_frame_sanity_check, теперь будет вызывать наш враппер. А наш враппер,
как было ужа сказано - незатейлевый - возвращает “все ок” а оригинальный код не вызывает.

Но если сильно нужно , то оригинальная проверка все еще доступна через вызов

__real_ieee80211_raw_frame_sanity_check(int,const void *,int,bool);

Таким образом, проверка всегда будет возвращать 0 “проверка пройдена успешно” и пакет будет отправляться.

Удачных экспериментов с WiFi
Не нарушайте закон, играйтесь только со своими личными сетями.

ЗЫЖ: фрагмент кода, отсылающего мусор

extern int ieee80211_raw_frame_sanity_check(int,const void *,int,bool);

//IEEE802.11 header + data
uint8_t header_and_data[] = {

    0x48, 0x00, 0x00, 0x00,

    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0x10, 0x11, 0x11, 0x11, 0x11, 0x11,
    0x20, 0x22, 0x22, 0x22, 0x22, 0x22,

    0x00, 0x00,

    0xDE, 0xAD, 0xBE, 0xEF,
};


void example_wifi_frame_tx() {
  
  int err = esp_wifi_80211_tx(WIFI_IF_STA, header_and_data, sizeof(header_and_data), false);
  printf(":-%c\r\n", err == ESP_OK ? ')' : '(');
}

3 лайка

а потом будет заседание по ст. ст. 274, 274.1 УК РФ :saluting_face:

Обращаю внимание, что бинарники Espressif используются в неизмененном (непропатченом виде), так что никакого нарушения соглашения об использовании тут нет.

а в сети deauther проект видели ? )))
а пачаму ЫЫ говорит что там ошибка в libieee80211.a На самом деле правильное название библиотеки - libnet80211.a ?_)))

Какие-то видел.

Но для такого мелкого вредительства, собственно, вообще ничего не нужно исправлять и какие-либо пакеты отсылать.

Делают вот что:

  1. Сканируют сеть, находят BSSID интересующей нас сети, (например, мы сидим в McDonalds, с free WiFi)
  2. Создают точку доступа (WiFi.softAP(), помоему, если не напутал) с таким же BSSID и таким же SSID как у нужной нам сети.
  3. Собственно, все.

Теперь, когда клиент будет посылать пакетики, наша AP будет автоматом слать DEAUTH , потому, что ни про каких клиентов наша AP не знает. В эфире будут находится две точки доступа - оригинальная и наша. Но они в эфире будут неотличимы.

PS:

да libnet80211.a

а BSSID тоже можно подменить? ну это же полная …

Конечно :). Решето дырявое, согласен :slight_smile:

В три команды:

esp32#>wifi ap                              <-- режим конфигурирования точки доступа (Access Point, AP)
esp32-ap>mac 0023:cc55:2334                 <-- задаем mac-address точки доступа (BSSID), какой угодно
esp32-ap>up McDonalds_FREE password Secret1 <-- задаем имя сети (SSID), стартуем точку доступа

а ваш способ как собирать ?))) для чайников и нубяр инструкция где ?)))

существует вроде всего 1 в сети… но может что то и еще появилось, и у того устройства есть готовый веб интерфейс, в поиске вроде первая ссылка
и вроде устройство спамит пакетами, а не просто ложит точку, или отключает… но и фейковые сети создать можно, 10ки! забив весь эфир своими)))

но а ваш способ будет работать с сетями которые используют стандарт 802.11w ?)))

а еще есть хакыры могут заражать любой usb кабель, и при втыкании будет переход на сайт, на это обзор еще сделаете ?)))
исключительно в целях защиты!)))

а чайникам и не нужно это :slight_smile:

вот тут как раз и понадобится то, о чем первый пост в этой теме.

конструируется и рассылается beacon кадр, с рандомными именами сетей. Их все принимают, у всех список сетей из ста позиций. Тоже мелкое вредительство. Меня больше интересует не напакостить, а траффик подсмотреть.

я как-то сканер запустил, более 90 точек из них большая часть OBD2, они так с ним и путешествуют, видимо на смартфон что-то льют

с пакетами что бы работать все равно нужен пк или ноут же….
особенно для перехвата и расшифровки пароля, что бы проникнуть в туже сеть…
просто же перехватив пакеты, и отправив не попасть же авторизованным в том же контакте ?
я пентестингом лет 10 не занимался, и освоил кучу всего нового, а при освоении одно влетает, а другое уже вылетает)))
могу что то путать…

как раз им и нужно это)))

еще интересно как быть с перехватом, если сеть скрытая))) умеет ли перебирать имена …

и еще кстати вроде сосед проводил атаку на свой старенький роутер, и он сгорел))) перестал работать, новые роутеры справятся с нагрузкой, а что если 15 таких устройств атакуют вас ?))) но может новые устройства как то справляются с бессмысленными пакетами…(протоколы есть другие может) с одним устройством они точно справятся, но вот с

15… а вообще я не очень сильно заморачивался, и wifi почти не пользуюсь…

это как ?))) что то не понял о чем вы… если например телефон запомнил 10ток wifi то только при включении wifi на телефоне, он сразу кучу мусора будет слать в эфир…

Ну вот одно из дельных применений deauth, это кикнуть юзера с его wifi точки и поставить свою поближе, чтобы уровень сигнала был повыше, поймать юзера на свою переносную точку доступа (сделанную, например, на esp32). А твоя точка доступа уже сливает весь траффик на , например, твой телефон или лаптоп.

Но я думаю, что обсуждение у нас куда-то не туда заходит :). Не надо хулиганить, вы же не кевин митник, а у нас не 60-е. Посодють!

Коннектится к таким сетям надо не по имени сети, а по BSSID (MAC адресу точки)

Когда WiFi.begin() делаешь, попробуй указать там пустой ssid , но нужный bssid.

Не нужно ничего перебирать.

это такая штука - втыкающаяся в диагностический порт “нетазиков”, Касперская продемонстрировала кстати как можно перехватить управление авто

А ссылку можно?

50 автомобилей в радиусе десятка метров? :roll_eyes:

парковка аднака, он реально метров на 30 бьёт еже что, так как некоторые появляются и исчезают, а это проезжающие, других вариантов нет

вот, минуту посканировал, но в другом месте, 2.4 полностью изгажен

И здесь более половины автомобили? :roll_eyes: