Reputation: 1
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