Skip to content

Instantly share code, notes, and snippets.

@Ynn
Created February 14, 2018 15:56
Show Gist options
  • Save Ynn/35e1e3145b23958a84880be51b094cec to your computer and use it in GitHub Desktop.
Save Ynn/35e1e3145b23958a84880be51b094cec to your computer and use it in GitHub Desktop.
esp8266 : sniff, send in udp, then sniff another channel
#include <Arduino.h>
#ifdef ESP8266
extern "C" {
#include "user_interface.h" //to gain access to promiscuous mode
}
#endif
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#define DATA_LENGTH 112
#define TYPE_MANAGEMENT 0x00
#define TYPE_CONTROL 0x01
#define TYPE_DATA 0x02
#define SUBTYPE_ASSOC_REQUEST 0x00
#define SUBTYPE_ASSOC_RESP 0x01
#define SUBTYPE_REASSOC 0x02
#define SUBTYPE_REASSOC_RESP 0x03
#define SUBTYPE_PROBE_REQUEST 0x04
#define SUBTYPE_PROBE_RESPONSE 0x05
#define SUBTYPE_BEACON 0x08
#define SUBTYPE_ATIM 0x09
#define SUBTYPE_DISAC 0x0A
#define SUBTYPE_AUTH 0x0B
#define SUBTYPE_DEAUTH 0x0C
#define DISABLE 0
#define ENABLE 1
#include <set>
#define WIFI_SSID "" //SSID must not be hidden by the AP!
#define WIFI_PASSWORD "" //actually not necessary for clock sync
IPAddress ip(172, 24, 1, 91);
int port = 8888;
std::set<std::string> macs;
struct RxControl {
signed rssi: 8;
unsigned rate: 4;
unsigned is_group: 1;
unsigned: 1;
unsigned sig_mode: 2;
unsigned legacy_length: 12;
unsigned damatch0: 1;
unsigned damatch1: 1;
unsigned bssidmatch0: 1;
unsigned bssidmatch1: 1;
unsigned MCS: 7;
unsigned CWB: 1;
unsigned HT_length: 16;
unsigned Smoothing: 1;
unsigned Not_Sounding: 1;
unsigned: 1;
unsigned Aggregation: 1;
unsigned STBC: 2;
unsigned FEC_CODING: 1;
unsigned SGI: 1;
unsigned rxend_state: 8;
unsigned ampdu_cnt: 8;
unsigned channel: 4;
unsigned: 12;
};
struct SnifferPacket {
struct RxControl rx_ctrl;
uint8_t data[112];
uint16_t cnt;
uint16_t len;
};
WiFiUDP Udp;
static void getMAC(char *addr, uint8_t* data, uint16_t offset) {
sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", data[offset+0], data[offset+1], data[offset+2], data[offset+3], data[offset+4], data[offset+5]);
}
static void showMetadata(SnifferPacket *snifferPacket) {
unsigned int frameControl = ((unsigned int)snifferPacket->data[1] << 8) + snifferPacket->data[0];
uint8_t version = (frameControl & 0b0000000000000011) >> 0;
uint8_t frameType = (frameControl & 0b0000000000001100) >> 2;
uint8_t frameSubType = (frameControl & 0b0000000011110000) >> 4;
uint8_t toDS = (frameControl & 0b0000000100000000) >> 8;
uint8_t fromDS = (frameControl & 0b0000001000000000) >> 9;
//Only look for non beacon packets
// if (frameType == TYPE_MANAGEMENT && frameSubType == SUBTYPE_BEACON)
// return;
switch (frameType) {
case TYPE_MANAGEMENT: Serial.print("[M]");
switch(frameSubType){
case SUBTYPE_PROBE_REQUEST : Serial.print("[PROBE]"); break;
case SUBTYPE_BEACON: Serial.print("[BEACON]"); break;
case SUBTYPE_ASSOC_REQUEST : Serial.print("[<ASSOC]"); break;
case SUBTYPE_ASSOC_RESP : Serial.print("[>ASSOC]"); break;
case SUBTYPE_AUTH : Serial.print("[>AUTH]"); break;
case SUBTYPE_DEAUTH : Serial.print("[<AUTH]"); break;
}
break;
case TYPE_CONTROL : Serial.print("[C]"); break;
case TYPE_DATA : Serial.print("[D]"); break;
}
Serial.printf("[%02x]",frameType,frameSubType);
Serial.print("RSSI: ");
Serial.print(snifferPacket->rx_ctrl.rssi, DEC);
Serial.print(" Ch: ");
Serial.print(wifi_get_channel());
char addr[] = "00:00:00:00:00:00";
getMAC(addr, snifferPacket->data, 10);
Serial.print(" Peer MAC: ");
Serial.print(addr);
macs.insert(addr);
// uint8_t SSID_length = snifferPacket->data[25];
// Serial.print(" SSID: ");
// printDataSpan(26, SSID_length, snifferPacket->data);
Serial.println();
}
void setup() {
Serial.begin(115200);
}
/**
* Callback for promiscuous mode
*/
static void ICACHE_FLASH_ATTR sniffer_callback(uint8_t *buffer, uint16_t length) {
struct SnifferPacket *snifferPacket = (struct SnifferPacket*) buffer;
showMetadata(snifferPacket);
}
void loop() {
int channel = 1;
Serial.print("start sniffing channel :");Serial.println(channel);
wifi_set_opmode(STATION_MODE);delay(10);
wifi_set_channel(channel);delay(10);
wifi_promiscuous_enable(0);delay(10);
wifi_set_promiscuous_rx_cb(sniffer_callback);delay(10);
wifi_promiscuous_enable(1);delay(10);
delay(5000);
Serial.println("stop sniffing");
wifi_promiscuous_enable(0);
wifi_set_promiscuous_rx_cb(0);
wifi_promiscuous_enable(1);
wifi_promiscuous_enable(0);
delay(500);
Serial.println("Set AP");
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(WIFI_SSID);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
for(auto mac : macs){
mac = mac+"\n";
Serial.println("Send packet");
Udp.beginPacket(ip, port);
Udp.write(mac.c_str());
Udp.endPacket();
}
delay(3000);
channel++;
if(channel == 14){
channel = 1;
}
macs.clear();
}
@Ynn
Copy link
Author

Ynn commented Feb 14, 2018

Same with MQTT support. You have to adjust scanning times in the loop.

#include <Arduino.h>

#ifdef ESP8266
extern "C" {
#include "user_interface.h" //to gain access to promiscuous mode
}
#endif

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include <PubSubClient.h>

#define DATA_LENGTH           112

#define TYPE_MANAGEMENT       0x00
#define TYPE_CONTROL          0x01
#define TYPE_DATA             0x02


#define SUBTYPE_ASSOC_REQUEST 0x00
#define SUBTYPE_ASSOC_RESP 0x01
#define SUBTYPE_REASSOC 0x02
#define SUBTYPE_REASSOC_RESP 0x03
#define SUBTYPE_PROBE_REQUEST 0x04
#define SUBTYPE_PROBE_RESPONSE 0x05
#define SUBTYPE_BEACON 0x08
#define SUBTYPE_ATIM 0x09
#define SUBTYPE_DISAC 0x0A
#define SUBTYPE_AUTH 0x0B
#define SUBTYPE_DEAUTH 0x0C


#define DISABLE 0
#define ENABLE  1

#include <set>



#define WIFI_SSID        "a" //SSID must not be hidden by the AP!
#define WIFI_PASSWORD    "c" //actually not necessary for clock sync

#define mqtt_server "m23.cloudmqtt.com"
#define mqtt_user "fdfdfgfd"
#define mqtt_password "gfgfgggf"
#define mqtt_port 12356



//UDP
IPAddress ip(172, 24, 1, 91);
int port = 8888;

//MQTT
WiFiClient espClient;
PubSubClient client(espClient);



std::set<std::string> macs;



struct RxControl {
  signed rssi: 8;
  unsigned rate: 4;
  unsigned is_group: 1;
  unsigned: 1;
  unsigned sig_mode: 2;
  unsigned legacy_length: 12;
  unsigned damatch0: 1;
  unsigned damatch1: 1;
  unsigned bssidmatch0: 1;
  unsigned bssidmatch1: 1;
  unsigned MCS: 7;
  unsigned CWB: 1;
  unsigned HT_length: 16;
  unsigned Smoothing: 1;
  unsigned Not_Sounding: 1;
  unsigned: 1;
  unsigned Aggregation: 1;
  unsigned STBC: 2;
  unsigned FEC_CODING: 1;
  unsigned SGI: 1;
  unsigned rxend_state: 8;
  unsigned ampdu_cnt: 8;
  unsigned channel: 4;
  unsigned: 12;
};

struct SnifferPacket {
  struct RxControl rx_ctrl;
  uint8_t data[112];
  uint16_t cnt;
  uint16_t len;
};



WiFiUDP Udp;

static void getMAC(char *addr, uint8_t* data, uint16_t offset) {
  sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", data[offset+0], data[offset+1], data[offset+2], data[offset+3], data[offset+4], data[offset+5]);
}

static void showMetadata(SnifferPacket *snifferPacket) {

  unsigned int frameControl = ((unsigned int)snifferPacket->data[1] << 8) + snifferPacket->data[0];

  uint8_t version      = (frameControl & 0b0000000000000011) >> 0;
  uint8_t frameType    = (frameControl & 0b0000000000001100) >> 2;
  uint8_t frameSubType = (frameControl & 0b0000000011110000) >> 4;
  uint8_t toDS         = (frameControl & 0b0000000100000000) >> 8;
  uint8_t fromDS       = (frameControl & 0b0000001000000000) >> 9;

  //Only look for non beacon packets
  if (frameType == TYPE_MANAGEMENT && frameSubType == SUBTYPE_BEACON)
        return;

  switch (frameType) {
    case TYPE_MANAGEMENT: Serial.print("[M]");
      switch(frameSubType){
        case  SUBTYPE_PROBE_REQUEST : Serial.print("[PROBE]"); break;
        case  SUBTYPE_BEACON: Serial.print("[BEACON]"); break;
        case  SUBTYPE_ASSOC_REQUEST : Serial.print("[<ASSOC]"); break;
        case  SUBTYPE_ASSOC_RESP : Serial.print("[>ASSOC]"); break;
        case  SUBTYPE_AUTH : Serial.print("[>AUTH]"); break;
        case  SUBTYPE_DEAUTH : Serial.print("[<AUTH]"); break;
      }
    break;
    case TYPE_CONTROL : Serial.print("[C]"); break;
    case TYPE_DATA : Serial.print("[D]"); break;
  }



  Serial.printf("[%02x]",frameType,frameSubType);
  Serial.print("RSSI: ");
  Serial.print(snifferPacket->rx_ctrl.rssi, DEC);

  Serial.print(" Ch: ");
  Serial.print(wifi_get_channel());

  char addr[] = "00:00:00:00:00:00";
  getMAC(addr, snifferPacket->data, 10);
  Serial.print(" Peer MAC: ");
  Serial.print(addr);

  macs.insert(addr);

  // uint8_t SSID_length = snifferPacket->data[25];
  // Serial.print(" SSID: ");
  // printDataSpan(26, SSID_length, snifferPacket->data);

  Serial.println();
}


void setup() {
  Serial.begin(115200);
  client.setServer(mqtt_server, mqtt_port);
}

/**
 * Callback for promiscuous mode
 */
static void ICACHE_FLASH_ATTR sniffer_callback(uint8_t *buffer, uint16_t length) {
  struct SnifferPacket *snifferPacket = (struct SnifferPacket*) buffer;
  showMetadata(snifferPacket);
}


void sendMQTT() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str(), mqtt_user, mqtt_password)) {
      Serial.println("connected");
      //SEND UDP
      for(auto mac : macs){
        mac = mac+"\n";
        Serial.println("Send mqtt");
        client.publish("mac", mac.c_str());
      }
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 1 seconds");
      // Wait 5 seconds before retrying
      delay(1000);
    }
  }
}


void loop() {
  int channel = 1;
  Serial.print("start sniffing channel :");Serial.println(channel);
  wifi_set_opmode(STATION_MODE);delay(10);
  wifi_set_channel(channel);delay(10);
  wifi_promiscuous_enable(0);delay(10);
  wifi_set_promiscuous_rx_cb(sniffer_callback);delay(10);
  wifi_promiscuous_enable(1);delay(10);
  delay(10000);

  Serial.println("stop sniffing");
  wifi_promiscuous_enable(0);
  wifi_set_promiscuous_rx_cb(0);
  wifi_promiscuous_enable(1);
  wifi_promiscuous_enable(0);

  delay(500);
  Serial.println("Set AP");
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }



  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(WIFI_SSID);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());



  sendMQTT();


  //SEND UDP
  for(auto mac : macs){
    mac = mac+"\n";
    Serial.println("Send packet");
    Udp.beginPacket(ip, port);
    Udp.write(mac.c_str());
    Udp.endPacket();
  }

  channel++;
  if(channel == 14){
    channel = 1;
  }

  macs.clear();
}

@Ynn
Copy link
Author

Ynn commented Feb 14, 2018

Improve channel scanning :

#include <Arduino.h>

#ifdef ESP8266
extern "C" {
#include "user_interface.h" //to gain access to promiscuous mode
}
#endif

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include <PubSubClient.h>

#define DATA_LENGTH           112

#define TYPE_MANAGEMENT       0x00
#define TYPE_CONTROL          0x01
#define TYPE_DATA             0x02


#define SUBTYPE_ASSOC_REQUEST 0x00
#define SUBTYPE_ASSOC_RESP 0x01
#define SUBTYPE_REASSOC 0x02
#define SUBTYPE_REASSOC_RESP 0x03
#define SUBTYPE_PROBE_REQUEST 0x04
#define SUBTYPE_PROBE_RESPONSE 0x05
#define SUBTYPE_BEACON 0x08
#define SUBTYPE_ATIM 0x09
#define SUBTYPE_DISAC 0x0A
#define SUBTYPE_AUTH 0x0B
#define SUBTYPE_DEAUTH 0x0C


#define DISABLE 0
#define ENABLE  1

#include <set>



#define WIFI_SSID        "a3G" //SSID must not be hidden by the AP!
#define WIFI_PASSWORD    "cee" //actually not necessary for clock sync

#define mqtt_server "m23.cloudmqtt.com"
#define mqtt_user "nxkhl"
#define mqtt_password "Pda2uKd"
#define mqtt_port 1235



//UDP
IPAddress ip(172, 24, 1, 91);
int port = 8888;

//MQTT
WiFiClient espClient;
PubSubClient client(espClient);



std::set<std::string> macs;



struct RxControl {
  signed rssi: 8;
  unsigned rate: 4;
  unsigned is_group: 1;
  unsigned: 1;
  unsigned sig_mode: 2;
  unsigned legacy_length: 12;
  unsigned damatch0: 1;
  unsigned damatch1: 1;
  unsigned bssidmatch0: 1;
  unsigned bssidmatch1: 1;
  unsigned MCS: 7;
  unsigned CWB: 1;
  unsigned HT_length: 16;
  unsigned Smoothing: 1;
  unsigned Not_Sounding: 1;
  unsigned: 1;
  unsigned Aggregation: 1;
  unsigned STBC: 2;
  unsigned FEC_CODING: 1;
  unsigned SGI: 1;
  unsigned rxend_state: 8;
  unsigned ampdu_cnt: 8;
  unsigned channel: 4;
  unsigned: 12;
};

struct SnifferPacket {
  struct RxControl rx_ctrl;
  uint8_t data[112];
  uint16_t cnt;
  uint16_t len;
};



WiFiUDP Udp;

static void getMAC(char *addr, uint8_t* data, uint16_t offset) {
  sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", data[offset+0], data[offset+1], data[offset+2], data[offset+3], data[offset+4], data[offset+5]);
}

static void showMetadata(SnifferPacket *snifferPacket) {

  unsigned int frameControl = ((unsigned int)snifferPacket->data[1] << 8) + snifferPacket->data[0];

  uint8_t version      = (frameControl & 0b0000000000000011) >> 0;
  uint8_t frameType    = (frameControl & 0b0000000000001100) >> 2;
  uint8_t frameSubType = (frameControl & 0b0000000011110000) >> 4;
  uint8_t toDS         = (frameControl & 0b0000000100000000) >> 8;
  uint8_t fromDS       = (frameControl & 0b0000001000000000) >> 9;

  //Only look for non beacon packets
  if (frameType == TYPE_MANAGEMENT && frameSubType == SUBTYPE_BEACON)
        return;

  switch (frameType) {
    case TYPE_MANAGEMENT: Serial.print("[M]");
      switch(frameSubType){
        case  SUBTYPE_PROBE_REQUEST : Serial.print("[PROBE]"); break;
        case  SUBTYPE_BEACON: Serial.print("[BEACON]"); break;
        case  SUBTYPE_ASSOC_REQUEST : Serial.print("[<ASSOC]"); break;
        case  SUBTYPE_ASSOC_RESP : Serial.print("[>ASSOC]"); break;
        case  SUBTYPE_AUTH : Serial.print("[>AUTH]"); break;
        case  SUBTYPE_DEAUTH : Serial.print("[<AUTH]"); break;
      }
    break;
    case TYPE_CONTROL : Serial.print("[C]"); break;
    case TYPE_DATA : Serial.print("[D]"); break;
  }



  Serial.printf("[%02x]",frameType,frameSubType);
  Serial.print("RSSI: ");
  Serial.print(snifferPacket->rx_ctrl.rssi, DEC);

  Serial.print(" Ch: ");
  Serial.print(wifi_get_channel());

  char addr[] = "00:00:00:00:00:00";
  getMAC(addr, snifferPacket->data, 10);
  Serial.print(" Peer MAC: ");
  Serial.print(addr);

  macs.insert(addr);

  // uint8_t SSID_length = snifferPacket->data[25];
  // Serial.print(" SSID: ");
  // printDataSpan(26, SSID_length, snifferPacket->data);

  Serial.println();
}


void setup() {
  Serial.begin(115200);
  client.setServer(mqtt_server, mqtt_port);
}

/**
 * Callback for promiscuous mode
 */
static void ICACHE_FLASH_ATTR sniffer_callback(uint8_t *buffer, uint16_t length) {
  struct SnifferPacket *snifferPacket = (struct SnifferPacket*) buffer;
  showMetadata(snifferPacket);
}


void sendMQTT() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str(), mqtt_user, mqtt_password)) {
      Serial.println("connected");
      //SEND UDP
      for(auto mac : macs){
        mac = mac+"\n";
        Serial.print("Send mqtt >");Serial.print(mac.c_str());
        client.publish("mac", mac.c_str());
        delay(100);
      }
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 1 seconds");
      // Wait 5 seconds before retrying
      delay(1000);
    }
  }
}


void loop() {


  int channel = 1;

  Serial.print("start sniffing channel :");Serial.println(channel);
  wifi_set_opmode(STATION_MODE);delay(10);
  wifi_set_channel(channel);delay(10);
  wifi_promiscuous_enable(0);delay(10);
  wifi_set_promiscuous_rx_cb(sniffer_callback);delay(10);
  wifi_promiscuous_enable(1);delay(10);

  for (size_t i = 1; i < 14; i++) {
    wifi_set_channel(channel++);delay(10);
    Serial.print("start sniffing channel :");Serial.println(channel);
    delay(1000);
  }


  Serial.println("stop sniffing");
  wifi_promiscuous_enable(0);
  wifi_set_promiscuous_rx_cb(0);
  wifi_promiscuous_enable(1);
  wifi_promiscuous_enable(0);

  delay(500);
  Serial.println("Set AP");
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }



  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(WIFI_SSID);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());



  sendMQTT();


  //SEND UDP
  for(auto mac : macs){
    mac = mac+"\n";
    Serial.print("Send udp >");Serial.print(mac.c_str());
    Udp.beginPacket(ip, port);
    Udp.write(mac.c_str());
    Udp.endPacket();
    delay(100);
  }


  macs.clear();
}

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