Allan Ayes
Allan Ayes

Reputation: 1

TCP dump ESP8266

greetings from Cuba. I am having problems dumping tcp packets using an ESP8266, all I am getting are the SSID of the wifi networks that are close to my actual location. I give the complete code if anyone could help me figure out where the problem is or if I need another library to accomplish the task.

#include <ESP8266WiFi.h>

#include <ESP8266WiFiGeneric.h>

#ifndef IPPROTO_TCP
#define IPPROTO_TCP 4
#endif
#pragma pack(1)

void promiscue(uint8_t* buf, uint16_t len);
void promisc_cb(uint8_t *buf, uint16_t len);
void promisc_raw(uint8_t *buf, uint16_t len);

// IP struct
struct IPPacket {
  uint8_t version : 4;
  uint8_t headerLength : 4;
  uint8_t typeOfService;
  uint16_t totalLength;
  uint16_t identification;
  uint16_t fragmentOffset;
  uint8_t ttl;
  uint8_t protocol;
  uint16_t checksum;
  uint32_t sourceIP;
  uint32_t destinationIP;
};

// TCP struct
struct TCPPacket {
  uint16_t sourcePort;
  uint16_t destinationPort;
  uint32_t sequenceNumber;
  uint32_t ackNumber;
  uint8_t dataOffset;
  uint8_t flags;
  uint16_t windowSize;
  uint16_t checksum;
  uint16_t urgentPointer;
};

WiFiClient wtcp;

void setup() {
  Serial.begin(115200);
  delay(10);

  Serial.println();
  Serial.println("Init ESP8266");

  // STA - station mode
  WiFi.mode(WIFI_STA);
  WiFi.begin("my_ssid", "my_password");

  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WiFi.SSID());

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("My IP: ");
  Serial.println(WiFi.localIP());
  wifi_promiscuous_enable(1);
  //wifi_set_promiscuous_rx_cb(promiscue);
  //wifi_set_promiscuous_rx_cb(promisc_cb);
  wifi_set_promiscuous_rx_cb(promisc_raw);
}

void loop() {
  // Do loop
}

void printIPPacket(const IPPacket& ipPacket) {
  // Print IP packets info
  
  Serial.print("Version: ");
  Serial.println(ipPacket.version);
  Serial.print("Head length: ");
  Serial.println(ipPacket.headerLength * 4);  
  Serial.print("Service type: ");
  Serial.println(ipPacket.typeOfService);
  Serial.print("Total length: ");
  Serial.println(ipPacket.totalLength);
  Serial.print("ID: ");
  Serial.println(ipPacket.identification);
  Serial.print("Fragment displacement ");
  Serial.println(ipPacket.fragmentOffset);
  Serial.print("TTL: ");
  Serial.println(ipPacket.ttl);
  Serial.print("Protocol: ");
  Serial.println(ipPacket.protocol);
  Serial.print("Checksum: ");
  Serial.println(ipPacket.checksum, HEX);
  Serial.print("IP src ");
  Serial.println(IPAddress(ipPacket.sourceIP));
  Serial.print("IP dst ");
  Serial.println(IPAddress(ipPacket.destinationIP));
  Serial.println();
}
void printTCPPacket(const TCPPacket& tcpPacket, const uint8_t* payload, size_t payloadLength) {
  // Print TCP packets info

  Serial.print("Port src ");
  Serial.println(tcpPacket.sourcePort);
  Serial.print("Port dst ");
  Serial.println(tcpPacket.destinationPort);
  Serial.print("Secuency number ");
  Serial.println(tcpPacket.sequenceNumber);
  Serial.print("Número de acuse de recibo: ");
  Serial.println(tcpPacket.ackNumber);
  Serial.print("Data displacement: ");
  Serial.println(tcpPacket.dataOffset);
  Serial.print("Flags: ");
  Serial.println(tcpPacket.flags, HEX);
  Serial.print("Windows size ");
  Serial.println(tcpPacket.windowSize);
  Serial.print("Checksum: ");
  Serial.println(tcpPacket.checksum, HEX);
  Serial.print("Emergent pointer ");
  Serial.println(tcpPacket.urgentPointer);
  Serial.println("Datos del paquete TCP:");
  for (size_t i = 0; i < payloadLength; i++) {
    Serial.print(payload[i], HEX);
    Serial.print(' ');
  }
  Serial.println();
}

void promisc_raw(uint8_t *buf, uint16_t len) {
  // Show ASCII data
  for (int i = 0; i < len; i++) {
   // Serial.printf("%02X ", buf[i]); // byte to hexadecimal
    Serial.printf("%c ", buf[i]); 
  }
  Serial.println(); // Nueva línea para mayor claridad
}

void promisc_cb(uint8_t *buf, uint16_t len) {
  // Check packet legth of TCP head
  if (len < 20) {
    return; // Ignore if less than 20
  }
  
  // TCP headers
  uint16_t puertoOrigen = (buf[0] << 8) | buf[1];
  uint16_t puertoDestino = (buf[2] << 8) | buf[3];
  uint32_t numeroSecuencia = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
  uint32_t numeroAcuseRecibo = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11];
  uint8_t longitudEncabezado = (buf[12] >> 4) * 4;
  uint8_t reservados = ((buf[12] & 0x0F) >> 1);
  bool flagURG = (buf[13] & 0x20) != 0;
  bool flagACK = (buf[13] & 0x10) != 0;
  bool flagPSH = (buf[13] & 0x08) != 0;
  bool flagRST = (buf[13] & 0x04) != 0;
  bool flagSYN = (buf[13] & 0x02) != 0;
  bool flagFIN = (buf[13] & 0x01) != 0;
  uint16_t ventanaRecepcion = (buf[14] << 8) | buf[15];
  uint16_t checksum = (buf[16] << 8) | buf[17];
  uint16_t punteroUrgente = (buf[18] << 8) | buf[19];
  
  Serial.println("------ New TCP package ------");
  Serial.printf("Port src %d\n", puertoOrigen);
  Serial.printf("Port dst %d\n", puertoDestino);
  Serial.printf("Secuence number: %lu\n", numeroSecuencia);
  Serial.printf(" %lu\n", numeroAcuseRecibo);
  Serial.printf("Header length %d bytes\n", longitudEncabezado);
  Serial.printf("Reservados: %d\n", reservados);
  Serial.printf("URG: %s\n", flagURG ? "Sí" : "No");
  Serial.printf("ACK: %s\n", flagACK ? "Sí" : "No");
  Serial.printf("PSH: %s\n", flagPSH ? "Sí" : "No");
  Serial.printf("RST: %s\n", flagRST ? "Sí" : "No");
  Serial.printf("SYN: %s\n", flagSYN ? "Sí" : "No");
  Serial.printf("FIN: %s\n", flagFIN ? "Sí" : "No");
  Serial.printf("Windows reception: %d\n", ventanaRecepcion);
  Serial.printf("Checksum: 0x%04X\n", checksum);
  Serial.printf("Urgent pointer: %d\n", punteroUrgente);
  
  // Analizar los datos después del encabezado TCP para identificar el protocolo de la capa de aplicación
  if (len > longitudEncabezado) {
    uint8_t *datos = buf + longitudEncabezado;
    uint8_t protocoloIP = datos[0];
    // Intentar identificar otros protocolos de aplicación
    if (len > longitudEncabezado + 3) {
      // Extraer direcciones IP
    uint8_t ipOrigen[4] = {datos[0], datos[1], datos[2], datos[3]};
    uint8_t ipDestino[4] = {datos[4], datos[5], datos[6], datos[7]};

    // Convertir bytes a enteros e imprimir direcciones IP
    uint32_t ipOrigenInt = (ipOrigen[0] << 24) | (ipOrigen[1] << 16) | (ipOrigen[2] << 8) | ipOrigen[3];
    uint32_t ipDestinoInt = (ipDestino[0] << 24) | (ipDestino[1] << 16) | (ipDestino[2] << 8) | ipDestino[3];
    Serial.printf("IP Origen: %d.%d.%d.%d\n", ipOrigenInt >> 24, (ipOrigenInt >> 16) & 0xFF, (ipOrigenInt >> 8) & 0xFF, ipOrigenInt & 0xFF);
    Serial.printf("IP Destino: %d.%d.%d.%d\n", ipDestinoInt >> 24, (ipDestinoInt >> 16) & 0xFF, (ipDestinoInt >> 8) & 0xFF, ipDestinoInt & 0xFF);
    
    // Obtener protocolos de la capa
      if(protocoloIP == 1){
        Serial.println("Protocolo: ICMP");
      }else if(protocoloIP == 17){
        if(datos[1] == 53){
          Serial.println("Protocolo: DNS");
          return;
        }else if((datos[1] == 20 || datos[1] == 21) && datos[2] == 0){
          Serial.println("Protocolo: FTP");
          return;
        }
      }else if (protocoloIP == 6 && (datos[13] & 0x02) == 0x02) { // Bandera SYN establecida
        Serial.println("Protocolo: FTP");
        return;
      }else if (datos[0] == 0x16 && datos[1] == 0x03 && datos[2] <= 0x03) {
        Serial.println("Protocolo: TLS/SSL");
        return;
      } else if (datos[0] == 0x48 && datos[1] == 0x54 && datos[2] == 0x54 && datos[3] == 0x50) {
        Serial.println("Protocolo: HTTP");
        return;
      } else if (datos[0] == 0x47 && datos[1] == 0x45 && datos[2] == 0x54 && datos[3] == 0x20) {
        Serial.println("Protocolo: GET");
        return;
      } else if (datos[0] == 0x50 && datos[1] == 0x4F && datos[2] == 0x53 && datos[3] == 0x54) {
        Serial.println("Protocolo: POST");
        return;
      }
    }
    // Si no se reconoce el protocolo, imprimir los datos del paquete TCP en formato hexadecimal
    Serial.println("Protocolo: Desconocido");
    Serial.println("Datos del paquete TCP:");
    for (int i = longitudEncabezado; i < len; i++) {
      Serial.printf("%02X ", buf[i]); // Mostrar cada byte de datos en formato hexadecimal
    }
    Serial.println("\nASCII");
    for (int i = longitudEncabezado; i < len; i++) {
      Serial.printf("%c",buf[i]); // Mostrar cada byte de datos en formato hexadecimal
    }
    Serial.println("\n------ Fin del paquete TCP ------");
  }
}

void promiscue_b(uint8_t* buf, uint16_t len) {
  IPPacket ipPacket;
  TCPPacket tcpPacket;
  const uint8_t* payload = nullptr;
  size_t payloadLength = 0;

  if (len < sizeof(IPPacket)) {
    Serial.println("Paquete IP incompleto");
    Serial.print("Longitud del paquete: ");
    Serial.println(len);
    return;
  }

  // Leer los campos del paquete IP desde los datos brutos recibidos
  ipPacket.version = (buf[0] >> 4) & 0x0F;
  ipPacket.headerLength = buf[0] & 0x0F;
  ipPacket.typeOfService = buf[1];
  ipPacket.totalLength = (buf[2] << 8) | buf[3];
  ipPacket.identification = (buf[4] << 8) | buf[5];
  ipPacket.fragmentOffset = (buf[6] << 8) | buf[7];
  ipPacket.ttl = buf[8];
  ipPacket.protocol = buf[9];
  ipPacket.checksum = (buf[10] << 8) | buf[11];
  ipPacket.sourceIP = (buf[12] << 24) | (buf[13] << 16) | (buf[14] << 8) | buf[15];
  ipPacket.destinationIP = (buf[16] << 24) | (buf[17] << 16) | (buf[18] << 8) | buf[19];

  // Si el protocolo es TCP, leer los campos del paquete TCP
  if (ipPacket.protocol == IPPROTO_TCP) {
    // Verificar si el paquete tiene el tamaño mínimo esperado para un paquete TCP
    if (len < sizeof(TCPPacket) + (ipPacket.headerLength * 4)) {
      Serial.println("Paquete TCP incompleto");
      Serial.print("Longitud del paquete: ");
      Serial.println(len);
      return;
    }

    // Leer los campos del paquete TCP desde los datos brutos recibidos
    uint8_t* tcpData = buf + (ipPacket.headerLength * 4);  // Apuntar a los datos TCP después de la cabecera IP
    tcpPacket.sourcePort = (tcpData[0] << 8) | tcpData[1];
    tcpPacket.destinationPort = (tcpData[2] << 8) | tcpData[3];
    tcpPacket.sequenceNumber = (tcpData[4] << 24) | (tcpData[5] << 16) | (tcpData[6] << 8) | tcpData[7];
    tcpPacket.ackNumber = (tcpData[8] << 24) | (tcpData[9] << 16) | (tcpData[10] << 8) | tcpData[11];
    tcpPacket.dataOffset = (tcpData[12] >> 4) ;  // El desplazamiento de datos está en palabras de 32 bits
    tcpPacket.flags = tcpData[13] & 0x3F;
    tcpPacket.windowSize = (tcpData[14] << 8) | tcpData[15];
    tcpPacket.checksum = (tcpData[16] << 8) | tcpData[17];
    tcpPacket.urgentPointer = (tcpData[18] << 8) | tcpData[19];

    size_t tcpPayloadOffset = ipPacket.headerLength * 4 + tcpPacket.dataOffset;

    // Verificar si el paquete TCP tiene datos
    if (len > tcpPayloadOffset) {
      // Calcular la longitud de los datos TCP
      payloadLength = len - tcpPayloadOffset;
      // Apuntar al inicio de los datos TCP
      payload = buf + tcpPayloadOffset;

      // Imprimir o procesar los datos TCP según sea necesario
      Serial.println("Datos del paquete TCP:");
      for (size_t i = 0; i < payloadLength; i++) {
        // Imprimir los datos como caracteres o en formato hexadecimal
        Serial.print((char)payload[i]);
      }
      Serial.println(); // Nueva línea para mayor claridad
    } else {
      Serial.println("El paquete TCP no contiene datos.");
    }
    // Imprimir información
    printTCPPacket(tcpPacket, payload, payloadLength);
  }
  // Imprimir información
  printIPPacket(ipPacket);
}

Help me figure out where the problem is or if I need another library to accomplish the task

Upvotes: 0

Views: 29

Answers (0)

Related Questions