Skip to content

Instantly share code, notes, and snippets.

@brainstorm
Last active June 16, 2024 14:47
Show Gist options
  • Save brainstorm/24e843ae0295ee1e41dff47c5b43a02c to your computer and use it in GitHub Desktop.
Save brainstorm/24e843ae0295ee1e41dff47c5b43a02c to your computer and use it in GitHub Desktop.
esp32 promiscuous mode and packet injection experiments
// Espressif ESP32 promiscuous mode and packet injection experiments
// by brainstorm at nopcode org
#include "freertos/FreeRTOS.h"
#include "esp_wifi.h"
#include "esp_wifi_internal.h"
#include "lwip/err.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
uint8_t HEX_COLSIZE = 7;
esp_err_t event_handler(void *ctx, system_event_t *event)
{
return ESP_OK;
}
void process_promisc(void* buf, uint16_t len)
{
char* buflen = (char*) buf + len;
uint8_t hexdump_cols = 0;
uint8_t offset = 0;
// RAW packet
for (char* ptr = buf; ptr < buflen; ptr++) printf("%c", *ptr);
printf("\n\n");
// Hexdump (wireshark-friendly)
for (char* ptr = buf; ptr < buflen; ptr+=HEX_COLSIZE) {
// print offset
printf(" %06X ", offset);
for (hexdump_cols=0; hexdump_cols < HEX_COLSIZE; hexdump_cols++)
printf(" %02X", *(ptr+hexdump_cols*sizeof(char)));
offset = offset + HEX_COLSIZE;
printf("\n");
}
printf("\n\n");
}
void send_packet(esp_interface_t iface, void* buf, uint8_t len)
{
printf("Sending actual packet via driver...\n");
switch(esp_wifi_internal_tx(iface, buf, len))
{
case ERR_OK:
printf("Packet in the air!\n");
break;
case ERR_IF:
printf("WiFi driver error\n");
break;
default:
printf("Some other error I don't want to control now\n");
break;
}
}
void app_main(void)
{
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_interface_t wifi_if;
void* wifi_eth = NULL;
nvs_flash_init();
tcpip_adapter_init();
ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
printf("Setting up wifi\n");
ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
//printf("Promiscuous mode callback\n");
//esp_wifi_set_promiscuous(true);
//esp_wifi_set_promiscuous_rx_cb(&process_promisc);
ESP_ERROR_CHECK( esp_wifi_start() );
// Borrowed from the original esp8266 injection example:
// https://github.com/kripthor/WiFiBeaconJam/blob/master/WiFiBeaconJam.ino
uint8_t packet[128] = { 0x80, 0x00, 0x00, 0x00,
/*4*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*10*/ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
/*16*/ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
/*22*/ 0xc0, 0x6c,
/*24*/ 0x83, 0x51, 0xf7, 0x8f, 0x0f, 0x00, 0x00, 0x00,
/*32*/ 0x64, 0x00,
/*34*/ 0x01, 0x04,
/* SSID */
/*36*/ 0x00, 0x06, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
0x01, 0x08, 0x82, 0x84,
0x8b, 0x96, 0x24, 0x30, 0x48, 0x6c, 0x03, 0x01,
/*56*/ 0x04};
wifi_if = tcpip_adapter_get_esp_if(wifi_eth);
printf("About to send packets every 200ms\n");
while(true)
{
send_packet(wifi_if, (void*)packet, sizeof(packet));
vTaskDelay(200 / portTICK_RATE_MS);
}
}
@brainstorm
Copy link
Author

The approach above will never inject 802.11 frames, reversing of libpp.a and lib80211.a seems to be needed:

http://esp32.com/viewtopic.php?p=3053#p3053

@nissimzur
Copy link

Hi brainstorm,
Can I hire you to small work on esp32 promiscuous?
Please email me to [email protected] or call my Skype nissim.text
Thank you
-Nissim

@dsiganos
Copy link

dsiganos commented Jun 17, 2017

It appears that Espressif will be imminently releasing a feature to inject 802.11 data frames (but not management frames):
https://esp32.com/viewtopic.php?f=13&t=2025#p9539

It is probably the function esp_wifi_80211_tx() introduced by this commit:
espressif/esp32-wifi-lib@ce0ce8b

@Staubgeborener
Copy link

Staubgeborener commented Jun 24, 2017

Another approach is to get the whole frame by casting the buffer and greb the playload with casted_buffer->payload. Also the length is in sig_len (see https://github.com/espressif/esp-idf/blob/master/components/esp32/include/esp_wifi_types.h). With this variant, i'll also get nearly all of the packets. Though i also have the same problem with malformed packets.

a possibility could be:

// get length of packet
 for (i = 0; i < casted_buffer->rx_ctrl.sig_len; i++) {
// print payload
printf(" %02X", casted_buffer->payload[i]);
}

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