Ниже приведён полный код программы. Данный код не претендует на звание крутого снифера, однако при желании его можно доработать, чтобы можно было просматривать содержимое пакетов. Так же на его основе можно легко сделать простой анализатор трафика. А главное - не надо делать всяких драйверов; всё просто и понятно. Суть этого сниффера заключается в том, что используются сокеты второй версии и созданный сокет переводится в режим promiscuous (прослушивания). #include <conio.h> #include <stdio.h> #include <winsock2.h>
#define MAX_PACKET_SIZE 0x10000 #define SIO_RCVALL 0x98000001 // Буфер для приёма данных char Buffer[MAX_PACKET_SIZE]; // 64 Kb
//Структура заголовка IP-пакета
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;
char src[10]; char dest[10]; char ds[15]; unsigned short lowbyte; unsigned short hibyte;
void main() { WSADATA wsadata; // Инициализация WinSock. SOCKET s; // Cлущающий сокет. char name[128]; // Имя хоста (компьютера). HOSTENT* phe; // Информация о хосте. SOCKADDR_IN sa; // Адрес хоста IN_ADDR sa1; // unsigned long flag = 1; // Флаг PROMISC Вкл/выкл.
// инициализация WSAStartup(MAKEWORD(2,2), &wsadata); s = socket( AF_INET, SOCK_RAW, IPPROTO_IP ); gethostname(name, sizeof(name)); phe = gethostbyname( name ); ZeroMemory( &sa, sizeof(sa) ); sa.sin_family = AF_INET; sa.sin_addr.s_addr = ((struct in_addr *)phe->h_addr_list[0])->s_addr; bind(s, (SOCKADDR *)&sa, sizeof(SOCKADDR)); // Включение promiscuous mode. ioctlsocket(s, SIO_RCVALL, &flag);
// Бесконечный цикл приёма IP-пакетов. while( !_kbhit() ) { int count; count = recv( s, Buffer, sizeof(Buffer), 0 ); // обработка IP-пакета if( count >= sizeof(IPHeader) ) { IPHeader* hdr = (IPHeader *)Buffer; //Начинаем разбор пакета...
strcpy(src,"Пакет: "); CharToOem(src,dest); printf(dest); // Преобразуем в понятный вид адрес отправителя. printf("From "); sa1.s_addr = hdr->iph_src; printf(inet_ntoa(sa1));
// Преобразуем в понятный вид адрес получателя. printf(" To "); sa1.s_addr = hdr->iph_dest; printf(inet_ntoa(sa1));
// Вычисляем протокол. Полный список этих констант // содержится в файле winsock2.h printf(" Prot: "); if(hdr->iph_protocol == IPPROTO_TCP) printf("TCP "); if(hdr->iph_protocol == IPPROTO_UDP) printf("UDP ");
// Вычисляем размер. Так как в сети принят прямой порядок // байтов, а не обратный, то прийдётся поменять байты местами. printf("Size: "); lowbyte = hdr->iph_length>>8; hibyte = hdr->iph_length<<8; hibyte = hibyte + lowbyte; printf("%s",itoa(hibyte,"",10));
// Вычисляем время жизни пакета. printf(" TTL:%s",itoa(hdr->iph_ttl,"",10)); printf("\n");
} }
closesocket( s ); WSACleanup(); }
Для успешной компиляции, необходимо подключить к проекту файл ws2_32.lib. |