Skip to content

Instantly share code, notes, and snippets.

@wojtess
Last active June 19, 2024 16:51
Show Gist options
  • Save wojtess/ec441a1efa374b8b02f5e52633bfa3f4 to your computer and use it in GitHub Desktop.
Save wojtess/ec441a1efa374b8b02f5e52633bfa3f4 to your computer and use it in GitHub Desktop.
esp32 send any raw ieee802.11 packet/injection mode

ESP-IDF have exported function esp_err_t esp_wifi_80211_tx(wifi_interface_t ifx, const void *buffer, int len, bool en_sys_seq); It allows user to send raw ieee802.11 packets, it allows only certain types of packet.

To bypass check and send all packets you want you need to remove one call and replace it with mov instruction.

To use bypass copy "bypass.S" next to your "main.c", change CMakeLists.txt to something like this: idf_component_register(SRCS "main.c" "bypass.S" "other_c_files.c" INCLUDE_DIRS ".") and use esp_wifi_80211_tx_mod to send any packet you want using example code from bypass.c

This is only for educational purposes and provided "AS IS"

#include "endianness.h"
#include "esp_wifi.h"
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
//IEEE 802.11 header with type "data" and subtype "null data"
//https://en.wikipedia.org/wiki/802.11_frame_types
uint8_t ieee80211header[] = {
//IEEE802.11 header
0x48, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,//addr1
0x13, 0x22, 0x33, 0x44, 0x55, 0x66,//addr2
0x13, 0x22, 0x33, 0x44, 0x55, 0x66,//addr3
0x00, 0x00,//duration or seq number, idk
//END IEEE802.11 header
};
uint8_t data_you_want_to_send[] = {
0x12, 0x32, 0x33, 0x53
};
//I am not sure what is necesary for witi to init succesfuly
void init_wifi() {
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_ap();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
const wifi_country_t wifi_country = {
.cc = "CN",
.schan = 1,
.nchan = 13,
.policy = WIFI_COUNTRY_POLICY_AUTO
};
ESP_ERROR_CHECK(esp_wifi_set_country(&wifi_country)); //set country for channel range [1, 13]
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_ERROR_CHECK(esp_wifi_set_channel(11, 0));
}
void send_packet() {
//declare esp_wifi_80211_tx_mod, it can be in header file
extern int esp_wifi_80211_tx_mod(wifi_interface_t ifx, const void *buffer, int len, bool en_sys_seq);
char buf[sizeof(ieee80211header) + sizeof(data_you_want_to_send)];
memcpy(buf, &ieee80211header, sizeof(ieee80211header));
memcpy(buf + sizeof(ieee80211header), &data_you_want_to_send, sizeof(data_you_want_to_send));
int err = esp_wifi_80211_tx_mod(WIFI_IF_STA, buf, sizeof(buf), false);
if(err != ESP_OK) {
printf("error while sending packet");
}
}
.text
.global esp_wifi_80211_tx_mod
.literal_position
.literal .LC0, esp_wifi_80211_tx+20
esp_wifi_80211_tx_mod:
entry a1, 0x30
extui a5, a5, 0x0, 0x8
mov a13, a5
mov a12, a4
mov.n a11, a3
mov.n a10, a2
movi a10, 0
l32r a13, .LC0
jx a13
@wojtess
Copy link
Author

wojtess commented Jun 18, 2024

@acautomacaoecontrole
You can use address 2 or address 3 based on To DS and From DS bit flags.
You can read more in this pdf table 7-7 and 7.1.3.3 Address fields.
You need to edit ieee80211header variable to change that.
You can use Beacon for your purpose.

@acautomacaoecontrole
Copy link

@wojtess, thanks for replying soon.

I've tried all frames types, thanks to your unlimited version of esp_wifi_80211_tx, but nothing has made a certain station to react. Indeed, I have not experimented other combinations with "from DS" and "to DS", so there is still a hope. All I have done was with both "to DS" and "from DS" equal to zero.
I'll keep you informed.

A beacon frame does not cause a station to transmit anything.

To make clear what I am trying to do: I intend to find a way to make a specific station (whose MAC address is known) to transmit a frame that I can sniff, no matter which type of frame this station outputs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment