С/C++ - Самопальный снифер под Linux

kas1e

Xakep, номер #050, стр. 050-082-3


{

unsigned int ip_length:4; // длина идет раньше из-за того, что на x86

unsigned int ip_version:4; // порядок следования байт - little endian

unsigned char ip_tos;

unsigned short ip_total_length;

unsigned short ip_id;

unsigned short ip_flags;

unsigned char ip_ttl;

unsigned char ip_protocol;

unsigned short ip_chsum;

unsigned int ip_source; // вот это добавили уже сами

unsigned int ip_dest; // чтобы проще было

};

Типы int, char, short мы уже выбираем сами в зависимости от длины поля. Далее, имея вот такую структуру, мы сможем легко адресоваться по буферу, используя данные поля. Соответственно и ARP-пакет описывается точно так же:

struct my_arp /* смещение описание */

{

unsigned short arp_hardware_type; /* 2b 0001 = Ethernet */

unsigned short arp_protocol; /* 2b 0800 = IPv4 */

unsigned char arp_mac_len; /* 1b 06 = 6 байт */

unsigned char arp_ip_len; /* 1b 04 = 4 байта */

unsigned short arp_opcode; /* 2b 0001/2 = запрос/ответ */

unsigned char arp_mac_source[6]; /* 6b mac источника */

unsigned char arp_ip_source[6]; /* 6b ip источника */

unsigned char arp_mac_dest[6]; /* 6b mac назначения */

unsigned char arp_ip_dest[6]; /* 6b ip назначения */

};

Для более полного представления смотри соответствующие RFC (в блок-врезке) и заголовочные файлы linux'a.

Вот таким образом ты можешь наполнять какой-нибудь файл различными структурами, а потом просто подключать его в главную программу. Получается довольно удобно. Так же можно поступать и с функциями, но так как наши программки довольно маленькие, нам это не понадобится.

Анализатор пакетов

Эта программка делает простые вещи. При запуске она начинает читать всю информацию, проходящую через сетевую карту, и выводить на экран информацию об ethernet/ip/arp-пакетах. В общем-то, для своего размера (2-3 килобайта) это очень приятный сниферок. Если у тебя сегмент с пассивным хабом, то можно перевести ifconfig'ом карточку в promisc режим и ужаснуться огромнейшему количеству пакетов :).

Сначала мы опишем все переменные, которые нам пригодятся в анализаторе:

int sock; // Дескриптор на открытый сокет

unsigned char buffer[65555]; // Буфер сделаем побольше

struct my_ip *ip; // Вот наши

struct my_arp *arp; // структурки

struct in_addr need; // А это необходимо для inet_ntoa макроса

После этого поднимаем наш супер-сокет:

sock = socket(PF_PACKET,SOCK_PACKET,htons(ETH_P_ALL));

И далее в цикле начинаем читать данные с сокета и парсить в понятном формате на экран:

while(1)

{

recvfrom(sock,buffer,sizeof buffer,0,0,0); // прочитали в буфер

/* Теперь мы парсим, как нам будет угодно. Например, для вывода типа в ARP-па-

кете мы показываем, где у нас в буфере ARP-пакет, и какое поле в структуре

Назад на стр. 050-082-2  Содержание  Вперед на стр. 050-082-4