Исходники.Ру - Программирование
Исходники
Статьи
Книги и учебники
Скрипты
Новости RSS
Магазин программиста

Главная » Статьи по программированию » Visual C++ - Интернет и сеть »

Обсудить на форуме Обсудить на форуме

Пример простейшего сниффера для 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. надо изменить строки: printf("%s",itoa(hibyte,"",10)); printf(" TTL:%s",itoa(hdr->iph_ttl,"",10));


Может пригодится:


Автор: RSDN
Прочитано: 12300
Рейтинг:
Оценить: 1 2 3 4 5

Комментарии: (7)

Прислал: Адамантэус
Очень удачный пример, единственно что можно было-бы добавить и номер пакета : printf("# %5u ", ntohs(hdr->iph_id)); а также испльзовать формат %u, а не itoa.

Прислал: вано
Работает и написано понятно.

Прислал: Zero
error C2664: 'CharToOemW' : cannot convert parameter 1 from 'char [10]' to 'LPCWSTR' 1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

Прислал: Gr0
На чем вы это компелировали ? где Winuser.h, include Windows.h

Прислал: werso
Аналогичная ошибка, даже после подключения Winuser.h,Windows.h что делать? на VS 2005 компилил..

Прислал: RuslanCoder
чтобы откомпилить надо добавить два массива: char temp_buffer[6]; char temp_buffer2[6]; и заменить соответствующие строки на: printf("%s",itoa(hibyte,temp_buffer,10)); и далее: printf(" TTL:%s",itoa(hdr->iph_ttl,temp_buf

Прислал: Владимир
Заменить CharToOem на CharToOemA, и все компилится!

Добавить комментарий
Ваше имя*:
Ваш email:
URL Вашего сайта:
Ваш комментарий*:
Код безопастности*:

Рассылка новостей
Рейтинги
© 2007, Программирование Исходники.Ру