Пример простейшего сниффера для W2K/XP
Ниже приведён полный код программы. Данный код не претендует на звание крутого снифера, однако при желании его можно доработать, чтобы можно было просматривать содержимое пакетов. Так же на его основе можно легко сделать простой анализатор трафика. А главное - не надо делать всяких драйверов; всё просто и понятно.
Суть этого сниффера заключается в том, что используются сокеты второй версии и созданный сокет переводится в режим 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.
Оригинал статьи: rsdn.ru
Оставить комментарий
Комментарии
1.
28 марта 2011, 22:18:41
попробывал написать ету прогу, запускаеться, но только черный екран, в чем дело, подскажите пожалуйста
2.
19 июля 2006, 00:16:47
#define SIO_RCVALL 0x98000001
Люди, помогите плз. Обьясните по каким принципам взято число 0x98000001? Как его получили?
Люди, помогите плз. Обьясните по каким принципам взято число 0x98000001? Как его получили?
3.
30 мая 2006, 23:29:05
printf("%s",itoa(hibyte,"",10));
printf(" TTL:%s",itoa(hdr->iph_ttl,"",10));
В функциях "intoa" вместо ковычек надо поставить ds, то есть:
printf("%s",itoa(hibyte,ds,10));
printf(" TTL:%s",itoa(hdr->iph_ttl,ds,10));
p.s. иначе ds нигде не используется... ;)
И все будет!
printf(" TTL:%s",itoa(hdr->iph_ttl,"",10));
В функциях "intoa" вместо ковычек надо поставить ds, то есть:
printf("%s",itoa(hibyte,ds,10));
printf(" TTL:%s",itoa(hdr->iph_ttl,ds,10));
p.s. иначе ds нигде не используется... ;)
И все будет!
4.
31 мая 2005, 12:10:52
А что за _kbhit()? У меня все компиляторы ругаются. (((
5.
11 мая 2005, 16:08:56
Джентльмены !!! А можно ли сделать похожую штучку чтобы работать с пакетом Ethernet и иметь к нему доступ - передавать и принимать произвольные данные ???
6.
6 апреля 2005, 13:41:52
2Иван
пользуй библиотеку WinPCAP (Windows Packet Capture Library). на ней, например, Ethereal написан.
пользуй библиотеку WinPCAP (Windows Packet Capture Library). на ней, например, Ethereal написан.
7.
23 февраля 2005, 16:15:21
А как насчет исходящих???
8.
22 февраля 2005, 01:25:25
Эта штучка слушает только входящие пакеты?
9.
17 ноября 2004, 14:18:47
Ну я просто ща лопну со смеха!
нафига писать printf("%s",itoa(hibyte,"",10));
если можно просто printf("%u", hibyte); ???????
к тому же это все рухнет, ведь destination string для itoa() - строка НУЛЕВОЙ длины!!! А теперь подумайте куда запишется результат...
нафига писать printf("%s",itoa(hibyte,"",10));
если можно просто printf("%u", hibyte); ???????
к тому же это все рухнет, ведь destination string для itoa() - строка НУЛЕВОЙ длины!!! А теперь подумайте куда запишется результат...
10.
13 октября 2004, 21:39:15
Правильно ли я понял, что Winsock API позволит таким образом увидеть только IP-датаграммы? Если да, то можно ли и как получить доступ к всему Ethernet-кадру?
11.
8 сентября 2004, 12:57:15
он не будет работать!!! :))) надо изменить строки:
printf("%s",itoa(hibyte,"",10));
printf(" TTL:%s",itoa(hdr->iph_ttl,"",10));
после этого работать будет
printf("%s",itoa(hibyte,"",10));
printf(" TTL:%s",itoa(hdr->iph_ttl,"",10));
после этого работать будет