Categories:

Anmeldeversuche im WLAN mit ESP32 Mikrocontroller erkennen

Veröffentlicht von empy
Lesezeit: 3 Minuten

Vor einigen Tagen habe ich euch gezeigt, wie sich mit einem wirklich preiswerten Mikrocontroller (ESP8266) einfache Attacken im WLAN sichtbar machen lassen. Leider musste ich feststellen, dass der ESP8266 keine Data-Frames in voller Länge aufzeichnen. Ein Umstand, welcher sich mit einem ESP32 für unter 10 Euro einfach beheben lässt.

Das Skript vom letzten Artikel habe ich daher so angepasst, dass es nur Data-Frames signalisiert werden, welche das EAPOL-Protokoll transportieren. Das Skript ist auf dem ESP32 lauffähig und lässt die LED immer dann blinken, wenn ein solches Frame aufgezeichnet wird. Bei fehlerhafter Anmeldung im WLAN wird der EAPOL-Prozess (4-Way-Handshake) mehrmals wiederholt. Fehlerhafte WLAN-Anmeldungen werden so sichtbar, indem der ESP32 intervallweise blinkt. Eine reguläre WLAN-Anmeldung führt nur zu einem kurzen Blinken.

Wie bereits beim ESP8266 solltet ihr euch überlegen, ob ihr die abgehörten Kanäle weiter eingrenzt. Wenn ihr das Skript auf einen Kanal festlegt, dann erhöht dies die Erkennungsgenauigkeit. Das Skript ist standardmäßig auf die Kanäle 1,6 und 11 eingestellt.

Es steht euch frei, beide Skripte zu kombinieren. Die Erkennung der Management-Frames könnt ihr in das Skript des ESP32 einfach einbauen. Andersherum kann die Erkennung der Data-Frames aufgrund der Beschränkung leider nicht in das ESP8266 eingebaut werden.

Schritt 1: ESP32 Boardmanager installieren

Um das Skript auf den ESP32 zu bringen, folgt am besten meinem Tutorial zum ESP8266. Für den ESP32 müsst ihr allerdings ein anderes SDK in die Arduino IDE einbinden.

In der Arduino IDE öffnet ihr also die Einstellungen unter „File -> Preferences…“ und gebt bei „Additional boards manager URLs“ folgenden Link ein:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

Wenn ihr bereits das ESP8266 SDK installiert habt, könnt ihr beide URLs einfach mit Komma separieren.

Nun muss die ESP32-Plattform noch installiert werden. Dazu wieder unter „Tools -> Board -> Boards Manager…“ die Plattform „esp32 by Espressif Systems“ auswählen. Dann das SDK installieren.

Stellt nun das Board sowie den Port entsprechend ein. Ich verwende das NodeMCU-32S. Denkt daran, den USB-Treiber zu installieren und ein passendes USB-Datenkabel zu verwenden, wenn euer ESP32 nicht am PC erkannt wird.

Schritt 2: Programmcode auf ESP32 hochladen

Ihr könnt nun folgenden Code auf den ESP32 hochladen. Er lässt die LED blinken, sofern EAPOL-Inhalte in Data-Frames erkannt werden. Das Skript versetzt den ESP32 in den Sniffer-Modus und filtert die Data-Frames heraus. Im Anschluss durchsucht der Mikrocontroller dann die Data-Frames nach dem EAPOL-Protokoll. Dazu durchsucht der Programmcode die Daten des Frames nach der EtherType-Kennzeichnung (0x88, 0x8E).

// Based on Spacehuhn's DeauthDetector. For details visit github.com/spacehuhn/DeauthDetector
// Based on Łukasz Podkalicki's ESP32-WiFi-Sniffer. Visit github.com/ESP-EOS/ESP32-WiFi-Sniffer

// changed LED behaviour, added EAPOL detection.

// include necessary libraries
#include <esp_wifi.h>


// ===== SETTINGS ===== //
const short channels[] = { 1,6,11 };  // Channels to scan


// ===== Runtime variables ===== //
int ch_index{ 0 };                     // Current index of channel array
int packet_rate_EAPOL{ 0 };            // EAPOL packet counter (resets with each update)
int attack_counter_EAPOL{ 0 };         // EAPOL attack counter
unsigned long update_time_EAPOL{ 0 };  // Last update time EAPOL detection
unsigned long ch_time{ 0 };            // Last channel hop time

// ===== Typdef function ===== //
typedef struct {
  unsigned frame_ctrl : 16;
  unsigned duration_id : 16;
  uint8_t addr1[6]; 
  uint8_t addr2[6]; 
  uint8_t addr3[6]; 
  unsigned sequence_ctrl : 16;
  uint8_t addr4[6]; 
} wifi_ieee80211_mac_hdr_t;

typedef struct {
  wifi_ieee80211_mac_hdr_t hdr;
  uint8_t payload[0]; 
} wifi_ieee80211_packet_t;


// ===== Sniffer function ===== //
IRAM_ATTR void sniffer(void *buf, wifi_promiscuous_pkt_type_t type) { // IRAM_ATTR improves speed
  if (type != WIFI_PKT_DATA) return;

  const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buf; // Separate MAC Header
  const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)ppkt->payload; // Trim MAC Header
  
  // If captured packet is EtherType (88 8E).
  if (ipkt->payload[0] == 0x88 && ipkt->payload[1] == 0x8E) { // EAPOL follows EtherType directly
    ++packet_rate_EAPOL;
  }
}


// ===== Setup ===== //
void setup() {
  Serial.begin(115200);  // Start serial communication

  pinMode(1, OUTPUT);                                   // Onboard LED
  digitalWrite(1, LOW);                                 // Enable LED pin

  wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();  // Initialize the configuration to default values
  esp_wifi_init(&cfg);                                  // Initialize WiFi Allocate resource for WiFi driver
  esp_wifi_set_storage(WIFI_STORAGE_RAM);               // Set the WiFi API configuration storage type to RAM
  esp_wifi_set_mode(WIFI_MODE_NULL);                    // Sniffer Mode
  esp_wifi_start();                                     // Start WiFi with above configuration
  esp_wifi_set_promiscuous(true);                       // Enable sniffer 
  esp_wifi_set_promiscuous_rx_cb(&sniffer);             // Set sniffer function.
}


// ===== Loop ===== //
void loop() {
  unsigned long current_time = millis();         // Get current time (in ms)

  if (current_time - update_time_EAPOL >= 50) {  // Run every 50ms
    update_time_EAPOL = current_time;            // Reset 60ms interval counter

    // When detected EAPOL packets exceed the minimum allowed number
    if (packet_rate_EAPOL >= 1) {                // If one or more EAPOL packets within 60ms
      ++attack_counter_EAPOL;                    // Then increment attack counter
    } else {
      if (attack_counter_EAPOL >= 1) {
        digitalWrite(1, LOW);                    // turn LED on
        Serial.println("EAPOL STOPPED");
        attack_counter_EAPOL = 0;                // Reset attack counter
      }
    }

    // When attack exceeds minimum allowed time
    if (attack_counter_EAPOL == 1) {             // If attack conditions hit
      digitalWrite(1, HIGH);                     // turn LED off
      Serial.println("EAPOL DETECTED");
    }

    packet_rate_EAPOL = 0;                       // Reset packet rate
  }


  // Channel hopping
  if (sizeof(channels) > 1 && current_time - ch_time >= 50) {
    ch_time = current_time;  // Run every 50ms

    // Get next channel
    ch_index = (ch_index + 1) % (sizeof(channels) / sizeof(channels[0]));
    short ch = channels[ch_index];

    esp_wifi_set_channel(ch, WIFI_SECOND_CHAN_NONE);
  }
}