Всем привет! Я пишу сниффер трафика на с++, возникли трудности с получением передаваемых данных в IP-пакетах. У меня получается читать информацию из IP-сегмента, tcp-сегмента. Дальше, по идеи, хранятся передаваемые данные. Я их вытаскиваю, но они непонятно в каком виде хранятся, при простом отображении я получаю смайлики и кракозябры. Не подскажите как получить эти данные в нормальном виде? Если что, вот исходники. Code: #include "ws2tcpip.h" #include <conio.h> typedef struct IPHeader { UCHAR iph_verlen; // версия и длина заголовка UCHAR iph_tos; // тип сервиса USHORT iph_length; // длина всего пакета USHORT iph_id; // Идентификация USHORT iph_offset; // флаги и смещения UCHAR iph_ttl; // время жизни пакета UCHAR iph_protocol; // протокол USHORT iph_xsum; // контрольная сумма ULONG iph_src; // IP-адрес отправителя ULONG iph_dest; // IP-адрес назначения } IPHeader; typedef struct { unsigned short int th_sport; unsigned short int th_dport; unsigned int th_seq; unsigned int th_ack; unsigned char th_x2:4, th_off:4; unsigned char th_flags; unsigned short int th_win; unsigned short int th_sum; unsigned short int th_urp; } TCPHDR; // 20 bytes #define SIO_RCVALL 0x98000001 Code: #include <WinSock2.h> #include <Windows.h> #include <iostream> #include <cstdlib> #include "ws2tcpip.h" #include "TCP_IP.h" #include <conio.h> using namespace std; #pragma comment(lib, "ws2_32.lib") const char* SOURCE_IP = "192.168.51.54"; struct udpheader { unsigned short int uh_sport; unsigned short int uh_dport; unsigned short int uh_len; unsigned short int uh_check; }; int main() { WSADATA wsaData; struct sockaddr_in sin; SOCKET s; char host[20]; hostent *phe; ULONG flag = 1; if (WSAStartup(MAKEWORD(2, 2), &wsaData)) { cout << "Error on startup WSA" << endl; return 1; } if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_IP)) == SOCKET_ERROR) { cout << "Error on create socket" << endl; return 1; } ZeroMemory(&sin, sizeof(sin)); gethostname(host, sizeof(host)); phe = gethostbyname(host); sin.sin_family = AF_INET; sin.sin_addr.s_addr = ((struct in_addr*)phe->h_addr_list[0])->s_addr; if (bind(s, (struct sockaddr *)&sin, sizeof(sin))) { cout << "Error on binding socket" << endl; return 1; } if (ioctlsocket(s, SIO_RCVALL, &flag)) { cout << "Error on set SIO_RCVALL" << endl; return 1; } char buffer[65536]; int count; while (true) { if ((count = recv(s, buffer, sizeof(buffer), 0))) { IPHeader* iph = (IPHeader* )buffer; char str[INET_ADDRSTRLEN]; in_addr sa; sa.s_addr = iph->iph_src; WORD size = (iph->iph_length << 8) + (iph->iph_length >> 8); //вывод информации от кого, кому, и какой протокол cout << "From: " << inet_ntoa(sa); sa.s_addr = iph->iph_dest; cout << " To: " << inet_ntoa(sa); switch(iph->iph_protocol) { case IPPROTO_TCP : cout << " TCP" << endl; break; case IPPROTO_UDP : cout << " UDP" << endl; break; } //начинаем разбирать пакеты struct TCPHDR *tcp_hdr = NULL; //тсп - сегмент struct udpheader *udp_hdr; //удп - сегмент size_t headers_len, data_len; //длмна сегмента и длина данных после сегментов u_char *data; //тут будем хранить данные о пакете if(iph->iph_protocol == IPPROTO_TCP) { tcp_hdr = (struct TCPHDR *)(buffer+sizeof(*iph)); //получаем тсп сегмент учитывая длину айпи - сегмента data = (u_char *)(buffer + (headers_len = sizeof(*iph) + sizeof(tcp_hdr))); // вычисляем длину данных в пакете data_len = count - headers_len; //cout << "TCP Receive: " << count << " Data_len" << data_len << " Header len: " << sizeof(tcp_hdr) << endl; // в принципе дальше можно делать что укогдо с данными } if(iph->iph_protocol == IPPROTO_UDP) { //тут все тоже самое только с удп пакетом udp_hdr = (struct udpheader *)(buffer+sizeof(*iph)); data = (u_char *)(buffer+(headers_len = sizeof(*iph)+sizeof(*udp_hdr))); data_len = count - headers_len; //cout << "UDP Receive: " << count << " Data_len" << data_len << endl; //cout << data << endl; // в принципе дальше можно делать что укогдо с данными } } Sleep(100); } return 0; }
То что ты взял откуда-то код это понятно, потому что обработки получения данных нет вовсе. По хорошему сначала нужно получить заголовок IP разобрать его - получить длину пакета из структуры. уже потом получить его полностью... далее уже разбирать TCP заголовок и уже проверять там размер окна... while(true) { recvall ipheaer siteof(ipheader) recvall tcpbuf ipheader->iph_length // работа с TCP пакетом } Если тебе важна целостность перехватываемых данных нужно учитывать что TCP разбивает пакеты на сегменты. По поводу вывода - в курсе что такое 16 ричная кодировка и HEX редактор? Знаешь о существовании функции sprintf %02h ?
Делал по примерам, не спорю, коменты сам ставил если что. Теперь по делу: IPHeader* iph = (IPHeader* )buffer; здесь я заполняю структуру, и выводя данные структуры, вижу от кого куда он посылается. Получается я уже получил ip заголовок, верно? Далее вот этой строчкой получаю tcp заголовок: tcp_hdr = (struct TCPHDR *)(buffer+sizeof(*iph)); и так же могу спокойно смотреть что внутри, верно? С HEX редактором знаком, знаю как в нем выглядят данные, т.е. я могу сохранить в файл принятые данные, а потом разобрать их редактором?, точнее там я их и увижу? sprintf %02h как то не сталкивался с такой функцией, работал с printf, fprintf На сколько я помню эти сегменты могут придти в любом порядке, в этом заключается загвоздка?