Время на прочтение
7 мин
Количество просмотров 151K
В этой статье мы рассмотрим создание простого сниффера под ОС Windows.
Кому интересно, добро пожаловать под кат.
Введение
Цель:
написать программу, которая будет захватывать сетевой трафик (Ethernet, WiFi), передающийся по протоколу IP.
Средства:
Visual Studio 2005 или выше.
Подход, который здесь описан, не принадлежит лично автору и успешно применяется во многих коммерческих, а также категорически бесплатных программах (привет, GPL).
Сей труд предназначен прежде всего для новичков в сетевом программровании, которые, однако, имеют хотя бы базовые знания в области сокетов вообще, и windows-сокетов в частности. Здесь я часто буду писать общеизвестные вещи, потому что предметная область специфическая, если что-то пропустить — в голове будет каша.
Надеюсь, Вам будет интересно.
Теория (читать не обязательно, но желательно)
В данный момент подавляющее большинство современных информационных сетей базируются на фундаменте стека протоколов TCP/IP. Стек протоколов TCP/IP (англ. Transmission Control Protocol/Internet Protocol) — собирательное название для сетевых протоколов разных уровней, используемых в сетях. В настоящей статье нас будет интересовать в основном протокол IP — маршрутизируемый сетевой протокол, используемый для негарантированной доставки данных, разделяемых на так называемые пакеты (более верный термин – дейтаграмма) от одного узла сети к другому.
Особый интерес для нас представляют IP-пакеты, предназначенные для передачи информации. Это достаточно высокий уровень сетевой OSI-модели данных, когда можно обстрагироваться от устройства и среды передачи данных, оперируя лишь логическим представлением.
Совершенно логичным является то обстоятельство, что рано или поздно должны были появится инструменты для перехвата, контроля, учета и анализа сетевого трафика. Такие средства обычно называется анализаторами трафика, пакетными анализаторыми или снифферами (от англ. to sniff — нюхать). Это — сетевой анализатор трафика, программа или программно-аппаратное устройство, предназначенное для перехвата и последующего анализа, либо только анализа сетевого трафика, предназначенного для других узлов. [1]
Практика (разговор по существу)
На данный момент создано достаточно много программного обеспечения для прослушивания трафика. Наиболее известный из них: Wireshark. Естественно, пожинать его лавры цель не стоит — нас интересует задача перехвата трафика методом обычного «прослушивания» сетевого интерфейса. Важно понимать, что мы не собираемся заниматься взломом и перехватывать
чужой
трафик. Нужно всего лишь просматривать и анализировать трафик, который проходит через наш хост.
Для чего это может понадобиться:
- Смотреть текущий поток трафика через сетевое соеднинение (входящий/исходящий/всего).
- Перенаправлять трафик для последующего анализа на другой хост.
- Теоретически, можно попытаться применить его для взлома WiFi-сети (мы ведь не собираемся этим заниматься?).
В отличие от Wireshark, который базируется на библиотеке libpcap/WinPcap, наш анализатор не будет использовать этот драйвер. Чего уж там, у нас вообще не будет драйвера, и свой NDIS(о ужас!) мы писать не собираемся. Про это можно прочитать в этом топике. Он будет просто пассивным наблюдателем, использующим
только
библиотеку WinSock. Использование драйвера в данном случае избыточно.
Как так? Очень просто.
Ключевым шагом в превращении простого сетевого приложения в сетевой анализатор является переключение сетевого интерфейса в режим прослушивания (promiscuous mode), что и позволит ему получать пакеты, адресованные другим интерфейсам в сети. Этот режим заставляют сетевую плату принимать все кадры, вне зависимости от того, кому они адресованы в сети. [2]
Начиная с Windows 2000 (NT 5.0) создать программу для прослушивания сегмента сети стало очень просто, т.к. ее сетевой драйвер позволяет перевести сокет в режим приёма всех пакетов.
Включение неразборчивого режима
long flag = 1;
SOCKET socket;
#define SIO_RCVALL 0x98000001
ioctlsocket(socket, SIO_RCVALL, &RS_Flag);
Наша программа оперирует IP-пакетами, и использует библиотеку Windows Sockets версии 2.2 и «сырые» сокеты (raw sockets). Для того чтобы получить прямой доступ к IP-пакету, сокет нужно создавать следующим образом:
Создание сырого сокета
s = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
Здесь вместо константы SOCK_STREAM (протокол TCP) или SOCK_DGRAM (протокол UDP), мы используем значение SOCK_RAW. Вообще говоря, работа с raw sockets интересна не только с точки зрения захвата трафика. Фактически, мы получаем полный контроль за формированием пакета. Вернее, формируем его вручную, что позволяет, например, послать специфический ICMP-пакет…
Идем дальше. Известно, что IP-пакет состоит из заголовка, служебной информации и, собственно, данных. Советую заглянуть сюда, чтобы освежит знания. Опишем в виде структуры IP-заголовок (спасибо отличной статье на RSDN [3]):
Описание структуры IP-пакета
typedef struct _IPHeader
{
unsigned char ver_len; // версия и длина заголовка
unsigned char tos; // тип сервиса
unsigned short length; // длина всего пакета
unsigned short id; // Id
unsigned short flgs_offset; // флаги и смещение
unsigned char ttl; // время жизни
unsigned char protocol; // протокол
unsigned short xsum; // контрольная сумма
unsigned long src; // IP-адрес отправителя
unsigned long dest; // IP-адрес назначения
unsigned short *params; // параметры (до 320 бит)
unsigned char *data; // данные (до 65535 октетов)
}IPHeader;
Главная функция алгоритма прослушивания будет выглядеть следующим образом:
Функция захвата одного пакета
IPHeader* RS_Sniff()
{
IPHeader *hdr;
int count = 0;
count = recv(RS_SSocket, (char*)&RS_Buffer[0], sizeof(RS_Buffer), 0);
if (count >= sizeof(IPHeader))
{
hdr = (LPIPHeader)malloc(MAX_PACKET_SIZE);
memcpy(hdr, RS_Buffer, MAX_PACKET_SIZE);
RS_UpdateNetStat(count, hdr);
return hdr;
}
else
return 0;
}
Здесь все просто: получаем порцию данных с помощью стандартной функции socket-функции recv, а затем копируем их в структуру типа IPHeader.
И, наконец, запускаем бесконечный цикл захвата пакетов:
Захватым все пакеты, которые попадут на наш сетевой интерфейс
while (true)
{
IPHeader* hdr = RS_Sniff();
// обработка IP-пакета
if (hdr)
{
// печатаем заголовок в консоли
}
}
Немного оффтопика
Здесь и далее у некоторых важных функций и переменных автор сделал префкис RS_ (от Raw Sockets). Проект делал 3-4 года назад, и была шальная мысль написать полноценную библиотеку для работы с сырыми сокетами. Как это часто бывает, после получения сколь-нибудь значимых(для автора) результатов, энтузиазм угас, и дальше учебного примера дело не полшло.
В принципе, можно пойти дальше, и описать заголовки всех последующих протоколов, находящихся выше. Для этого необходимо анализировать поле protocol в структуре IPHeader. Посмотрите на пример кода (да, там должен быть switch, чёрт возьми!), где происходит раскрашивание заголовка в зависимости от того, какой протокол имеет пакет, инкапсулированный в IP:
/*
* Выделение пакета цветом
*/
void ColorPacket(const IPHeader *h, const u_long haddr, const u_long whost = 0)
{
if (h->xsum)
SetConsoleTextColor(0x17); // если пакет не пустой
else
SetConsoleTextColor(0x07); // пустой пакет
if (haddr == h->src)
{
SetConsoleTextColor(BACKGROUND_BLUE | /*BACKGROUND_INTENSITY |*/
FOREGROUND_RED | FOREGROUND_INTENSITY); // "родной" пакет на отдачу
}
else if (haddr == h->dest)
{
SetConsoleTextColor(BACKGROUND_BLUE | /*BACKGROUND_INTENSITY |*/
FOREGROUND_GREEN | FOREGROUND_INTENSITY); // "родной" пакет на прием
}
if (h->protocol == PROT_ICMP || h->protocol == PROT_IGMP)
{
SetConsoleTextColor(0x70); // ICMP-пакет
}
else if(h->protocol == PROT_IP || h->protocol == 115)
{
SetConsoleTextColor(0x4F); // IP-in-IP-пакет, L2TP
}
else if(h->protocol == 53 || h->protocol == 56)
{
SetConsoleTextColor(0x4C); // TLS, IP with Encryption
}
if(whost == h->dest || whost == h->src)
{
SetConsoleTextColor(0x0A);
}
}
Однако это существенно выходит за рамки этой статьи. Для нашего учебного примера вполне достаточно будет посмотреть ip-адреса хостов, с которых и на которые идет трафик, и посчитать его количество в единицу времени(готовая программа в архиве в конце статьи).
Для того, чтобы отобразить данные IP-заголовка, необходимо реализовать функцию преобразования заголовка (но не данных) дейтаграммы в строку. В качестве примера реализации, можно предложить такой вариант:
Преобразование IP-заголовка в строку
inline char* iph2str(IPHeader *iph)
{
const int BUF_SIZE = 1024;
char *r = (char*)malloc(BUF_SIZE);
memset((void*)r, 0, BUF_SIZE);
sprintf(r, "ver=%d hlen=%d tos=%d len=%d id=%d flags=0x%X offset=%d ttl=%dms prot=%d crc=0x%X src=%s dest=%s",
BYTE_H(iph->ver_len),
BYTE_L(iph->ver_len)*4,
iph->tos,
ntohs(iph->length),
ntohs(iph->id),
IP_FLAGS(ntohs(iph->flgs_offset)),
IP_OFFSET(ntohs(iph->flgs_offset)),
iph->ttl, iph->protocol,
ntohs(iph->xsum), nethost2str(iph->src),
nethost2str(iph->dest)
);
return r;
}
На основании приведенных выше базовых сведений, получается вот такая небольшая программа (жуткое название ss, сокр. от англ. simple sniffer), реализующая локальное прослушивание IP-трафика. Интерфейс ее приведен ниже на рисунке.
Исходный и бинарный код предоставляю как есть, таким как он был несколько лет назад. Сейчас мне на него страшно смотреть, и все же, он вполне читабельный (конечно же, нельзя быть таким самоуверенным). Для компиляции будет достаточно даже Visual Studio Express 2005.
Что у нас получилось в итоге:
- Сниффер работает в режиме пользователя, однако требует привилегии администратора.
- Пакеты не фильтруются, отображаясь как есть (можно добавить настраиваемые фильтры — предлагаю подробно рассмотреть эту тему в следующей статье, если интересно).
- WiFi-трафик тоже захватывается(все зависит от конкретной модели чипа, у Вас может и не работать, как у меня несколько лет назад), хотя есть AirPcap, которая чудесно это умеет делать, но стоит денег.
- Весь поток дейтаграмм логируется в файл (см. архив, приложенный в конце статьи).
- Программа работает в качестве сервера на порту 2000. Можно подключиться с помощью утилиты telnet к хосту и произвести мониторинг потоков трафика. Количество подключений ограничено двадцатью (код не мой, нашел на просторах сети и применял для экспериментов; удалять не стал — жалко)
Спасибо за внимание, проздравляю хабровчан и хабровчанок и всех-всех-всех с наступающим Рождеством!
Скачать проект Пароль на открытие: habr
upd: По совету Weageoo, выложил на гитхаб.
В этой статье мы рассмотрим создание простого сниффера под ОС Windows.
Кому интересно, добро пожаловать под кат.
Введение
Цель: написать программу, которая будет захватывать сетевой трафик (Ethernet, WiFi), передающийся по протоколу IP.
Средства: Visual Studio 2005 или выше.
Подход, который здесь описан, не принадлежит лично автору и успешно применяется во многих коммерческих, а также категорически бесплатных программах (привет, GPL).
Сей труд предназначен прежде всего для новичков в сетевом программровании, которые, однако, имеют хотя бы базовые знания в области сокетов вообще, и windows-сокетов в частности. Здесь я часто буду писать общеизвестные вещи, потому что предметная область специфическая, если что-то пропустить — в голове будет каша.
Надеюсь, Вам будет интересно.
Теория (читать не обязательно, но желательно)
В данный момент подавляющее большинство современных информационных сетей базируются на фундаменте стека протоколов TCP/IP. Стек протоколов TCP/IP (англ. Transmission Control Protocol/Internet Protocol) — собирательное название для сетевых протоколов разных уровней, используемых в сетях. В настоящей статье нас будет интересовать в основном протокол IP — маршрутизируемый сетевой протокол, используемый для негарантированной доставки данных, разделяемых на так называемые пакеты (более верный термин – дейтаграмма) от одного узла сети к другому.
Особый интерес для нас представляют IP-пакеты, предназначенные для передачи информации. Это достаточно высокий уровень сетевой OSI-модели данных, когда можно обстрагироваться от устройства и среды передачи данных, оперируя лишь логическим представлением.
Совершенно логичным является то обстоятельство, что рано или поздно должны были появится инструменты для перехвата, контроля, учета и анализа сетевого трафика. Такие средства обычно называется анализаторами трафика, пакетными анализаторыми или снифферами (от англ. to sniff — нюхать). Это — сетевой анализатор трафика, программа или программно-аппаратное устройство, предназначенное для перехвата и последующего анализа, либо только анализа сетевого трафика, предназначенного для других узлов. [1]
Практика (разговор по существу)
На данный момент создано достаточно много программного обеспечения для прослушивания трафика. Наиболее известный из них: Wireshark. Естественно, пожинать его лавры цель не стоит — нас интересует задача перехвата трафика методом обычного «прослушивания» сетевого интерфейса. Важно понимать, что мы не собираемся заниматься взломом и перехватывать чужой трафик. Нужно всего лишь просматривать и анализировать трафик, который проходит через наш хост.
Для чего это может понадобиться:
- Смотреть текущий поток трафика через сетевое соеднинение (входящий/исходящий/всего).
- Перенаправлять трафик для последующего анализа на другой хост.
- Теоретически, можно попытаться применить его для взлома WiFi-сети (мы ведь не собираемся этим заниматься?).
В отличие от Wireshark, который базируется на библиотеке libpcap/WinPcap, наш анализатор не будет использовать этот драйвер. Чего уж там, у нас вообще не будет драйвера, и свой NDIS(о ужас!) мы писать не собираемся. Про это можно прочитать в этом топике. Он будет просто пассивным наблюдателем, использующим только библиотеку WinSock. Использование драйвера в данном случае избыточно.
Как так? Очень просто.
Ключевым шагом в превращении простого сетевого приложения в сетевой анализатор является переключение сетевого интерфейса в режим прослушивания (promiscuous mode), что и позволит ему получать пакеты, адресованные другим интерфейсам в сети. Этот режим заставляют сетевую плату принимать все кадры, вне зависимости от того, кому они адресованы в сети. [2]
Начиная с Windows 2000 (NT 5.0) создать программу для прослушивания сегмента сети стало очень просто, т.к. ее сетевой драйвер позволяет перевести сокет в режим приёма всех пакетов.
Включение неразборчивого режима
long flag = 1;
SOCKET socket;
#define SIO_RCVALL 0x98000001
ioctlsocket(socket, SIO_RCVALL, &RS_Flag);
Наша программа оперирует IP-пакетами, и использует библиотеку Windows Sockets версии 2.2 и «сырые» сокеты (raw sockets). Для того чтобы получить прямой доступ к IP-пакету, сокет нужно создавать следующим образом:
Создание сырого сокета
s = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
Здесь вместо константы SOCK_STREAM (протокол TCP) или SOCK_DGRAM (протокол UDP), мы используем значение SOCK_RAW. Вообще говоря, работа с raw sockets интересна не только с точки зрения захвата трафика. Фактически, мы получаем полный контроль за формированием пакета. Вернее, формируем его вручную, что позволяет, например, послать специфический ICMP-пакет…
Идем дальше. Известно, что IP-пакет состоит из заголовка, служебной информации и, собственно, данных. Советую заглянуть сюда, чтобы освежит знания. Опишем в виде структуры IP-заголовок (спасибо отличной статье на RSDN [3]):
Описание структуры IP-пакета
typedef struct _IPHeader
{
unsigned char ver_len; // версия и длина заголовка
unsigned char tos; // тип сервиса
unsigned short length; // длина всего пакета
unsigned short id; // Id
unsigned short flgs_offset; // флаги и смещение
unsigned char ttl; // время жизни
unsigned char protocol; // протокол
unsigned short xsum; // контрольная сумма
unsigned long src; // IP-адрес отправителя
unsigned long dest; // IP-адрес назначения
unsigned short *params; // параметры (до 320 бит)
unsigned char *data; // данные (до 65535 октетов)
}IPHeader;
Главная функция алгоритма прослушивания будет выглядеть следующим образом:
Функция захвата одного пакета
IPHeader* RS_Sniff()
{
IPHeader *hdr;
int count = 0;
count = recv(RS_SSocket, (char*)&RS_Buffer[0], sizeof(RS_Buffer), 0);
if (count >= sizeof(IPHeader))
{
hdr = (LPIPHeader)malloc(MAX_PACKET_SIZE);
memcpy(hdr, RS_Buffer, MAX_PACKET_SIZE);
RS_UpdateNetStat(count, hdr);
return hdr;
}
else
return 0;
}
Здесь все просто: получаем порцию данных с помощью стандартной функции socket-функции recv, а затем копируем их в структуру типа IPHeader.
И, наконец, запускаем бесконечный цикл захвата пакетов:
Захватым все пакеты, которые попадут на наш сетевой интерфейс
while (true)
{
IPHeader* hdr = RS_Sniff();
// обработка IP-пакета
if (hdr)
{
// печатаем заголовок в консоли
}
}
Немного оффтопика
Здесь и далее у некоторых важных функций и переменных автор сделал префкис RS_ (от Raw Sockets). Проект делал 3-4 года назад, и была шальная мысль написать полноценную библиотеку для работы с сырыми сокетами. Как это часто бывает, после получения сколь-нибудь значимых(для автора) результатов, энтузиазм угас, и дальше учебного примера дело не полшло.
В принципе, можно пойти дальше, и описать заголовки всех последующих протоколов, находящихся выше. Для этого необходимо анализировать поле protocol в структуре IPHeader. Посмотрите на пример кода (да, там должен быть switch, чёрт возьми!), где происходит раскрашивание заголовка в зависимости от того, какой протокол имеет пакет, инкапсулированный в IP:
/*
* Выделение пакета цветом
*/
void ColorPacket(const IPHeader *h, const u_long haddr, const u_long whost = 0)
{
if (h->xsum)
SetConsoleTextColor(0x17); // если пакет не пустой
else
SetConsoleTextColor(0x07); // пустой пакет
if (haddr == h->src)
{
SetConsoleTextColor(BACKGROUND_BLUE | /*BACKGROUND_INTENSITY |*/
FOREGROUND_RED | FOREGROUND_INTENSITY); // "родной" пакет на отдачу
}
else if (haddr == h->dest)
{
SetConsoleTextColor(BACKGROUND_BLUE | /*BACKGROUND_INTENSITY |*/
FOREGROUND_GREEN | FOREGROUND_INTENSITY); // "родной" пакет на прием
}
if (h->protocol == PROT_ICMP || h->protocol == PROT_IGMP)
{
SetConsoleTextColor(0x70); // ICMP-пакет
}
else if(h->protocol == PROT_IP || h->protocol == 115)
{
SetConsoleTextColor(0x4F); // IP-in-IP-пакет, L2TP
}
else if(h->protocol == 53 || h->protocol == 56)
{
SetConsoleTextColor(0x4C); // TLS, IP with Encryption
}
if(whost == h->dest || whost == h->src)
{
SetConsoleTextColor(0x0A);
}
}
Однако это существенно выходит за рамки этой статьи. Для нашего учебного примера вполне достаточно будет посмотреть ip-адреса хостов, с которых и на которые идет трафик, и посчитать его количество в единицу времени(готовая программа в архиве в конце статьи).
Для того, чтобы отобразить данные IP-заголовка, необходимо реализовать функцию преобразования заголовка (но не данных) дейтаграммы в строку. В качестве примера реализации, можно предложить такой вариант:
Преобразование IP-заголовка в строку
inline char* iph2str(IPHeader *iph)
{
const int BUF_SIZE = 1024;
char *r = (char*)malloc(BUF_SIZE);
memset((void*)r, 0, BUF_SIZE);
sprintf(r, "ver=%d hlen=%d tos=%d len=%d id=%d flags=0x%X offset=%d ttl=%dms prot=%d crc=0x%X src=%s dest=%s",
BYTE_H(iph->ver_len),
BYTE_L(iph->ver_len)*4,
iph->tos,
ntohs(iph->length),
ntohs(iph->id),
IP_FLAGS(ntohs(iph->flgs_offset)),
IP_OFFSET(ntohs(iph->flgs_offset)),
iph->ttl, iph->protocol,
ntohs(iph->xsum), nethost2str(iph->src),
nethost2str(iph->dest)
);
return r;
}
На основании приведенных выше базовых сведений, получается вот такая небольшая программа (жуткое название ss, сокр. от англ. simple sniffer), реализующая локальное прослушивание IP-трафика. Интерфейс ее приведен ниже на рисунке.
Исходный и бинарный код предоставляю как есть, таким как он был несколько лет назад. Сейчас мне на него страшно смотреть, и все же, он вполне читабельный (конечно же, нельзя быть таким самоуверенным). Для компиляции будет достаточно даже Visual Studio Express 2005.
Что у нас получилось в итоге:
- Сниффер работает в режиме пользователя, однако требует привилегии администратора.
- Пакеты не фильтруются, отображаясь как есть (можно добавить настраиваемые фильтры — предлагаю подробно рассмотреть эту тему в следующей статье, если интересно).
- WiFi-трафик тоже захватывается(все зависит от конкретной модели чипа, у Вас может и не работать, как у меня несколько лет назад), хотя есть AirPcap, которая чудесно это умеет делать, но стоит денег.
- Весь поток дейтаграмм логируется в файл (см. архив, приложенный в конце статьи).
- Программа работает в качестве сервера на порту 2000. Можно подключиться с помощью утилиты telnet к хосту и произвести мониторинг потоков трафика. Количество подключений ограничено двадцатью (код не мой, нашел на просторах сети и применял для экспериментов; удалять не стал — жалко)
Спасибо за внимание, проздравляю иок и всех-всех-всех с наступающим Рождеством!
Скачать проект
Автор: antonpv
Источник
Перевод статьи: http://www.codeproject.com/Articles/17031/A-Network-Sniffer-in-C
Скачать: Исходный код с сайта codeproject
В этом переводе будет показано как создать простой снифер, с парсингом IP, TCP, UDP и DNS пакетов на c#. Без использования сторонних библиотек типа SharpCap.
//Для захвата пакетов сокетом //он должен иметь тип raw //с протоколом IP mainSocket = newSocket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP); // Привязываем сокет к выбранному IP mainSocket.Bind(newIPEndPoint(IPAddress.Parse(cmbInterfaces.Text),0)); //Устанавливаем опции у сокета mainSocket.SetSocketOption(SocketOptionLevel.IP, //Принимать только IP пакеты SocketOptionName.HeaderIncluded, //Включать заголовок true); byte[] byTrue = newbyte[4]{1, 0, 0, 0}; byte[] byOut = newbyte[4]; //Socket.IOControl это аналог метода WSAIoctl в Winsock 2 mainSocket.IOControl(IOControlCode.ReceiveAll, //SIO_RCVALL of Winsock byTrue, byOut); //Начинаем приём асинхронный приём пакетов mainSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, newAsyncCallback(OnReceive), null);
Для захвата пакетов, мы используем raw(сырой) сокет и привязываем его к IP-адресу. После установки некоторых параметров для сокета, вызываем метод IOControl. Обратите внимание, что IOControl аналогичен методу Winsock2WSAIoctl. IOControlCode.ReceiveAll означает, что захватываться будут абсолютно все пакеты как входящие так и исходящие.
Второй параметр, передаваемый в IOControl с IOControlCode.ReceiveAll должен содержать именно такое значение массива byTrue (спасибо Леониду Молочному за это). Далее мы начинаем получать все пакеты асинхронно.
Анализ пакетов
IP датаграммы инкапсулируются TCP и UDP пакетами. Они также содержатся в данных, передаваемыъ по протоколам прикладного уровня, таких как DNS, HTTP, FTP, SMTP, SIP и т.д. Таким образом, пакет TCP содержит в себе дейтаграммы IP, например:
+--------------+---------------+----------------------+ | IP заголовок | TCP заголовок | Данные | +--------------+---------------+----------------------+
Итак, первое, что мы должны сделать, это проанализировать IP-заголовок. Для этого создан урезанный класс classIPHeader. Комментарии описывают что и как происходит.
public classIPHeader { //Поля IP заголовка private byte byVersionAndHeaderLength; // Восемь бит для версии // и длины private byte byDifferentiatedServices; // Восемь бит для дифференцированного // сервиса private ushort usTotalLength; // 16 бит для общей длины private ushort usIdentification; // 16 бит для идентификатора private ushort usFlagsAndOffset; // 16 бит для флагов, фрагментов // смещения private byte byTTL; // 8 бит для TTL (Time To Live) private byte byProtocol; // 8 бит для базового протокола private short sChecksum; // 16 бит для контрольной суммы // заголовка private uint uiSourceIPAddress; // 32 бита для адреса источника IP private uint uiDestinationIPAddress; // 32 бита для IP назначения //Конец полей IP заголовка private byte byHeaderLength; //Длина заголовка private byte[] byIPData = new byte[4096]; //Данные в дейтаграмме public IPHeader(byte[] byBuffer, int nReceived) { try { //Создаём MemoryStream для принимаемых данных MemoryStream memoryStream = newMemoryStream(byBuffer, 0, nReceived); //Далее создаем BinaryReader для чтения MemoryStream BinaryReader binaryReader = newBinaryReader(memoryStream); //Первые 8 бит содержат верисю и длину заголовка //считываем 8 бит = 1 байт byVersionAndHeaderLength = binaryReader.ReadByte(); //Следующие 8 бит содержат дифф. сервис byDifferentiatedServices = binaryReader.ReadByte(); //Следующие 8 бит содержат общую длину дейтаграммы usTotalLength = (ushort) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); //16 байт для идентификатора usIdentification = (ushort)IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); //8 бит для флагов, фрагментов, смещений usFlagsAndOffset = (ushort)IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); //8 бит для TTL byTTL = binaryReader.ReadByte(); //8 бит для базового протокола byProtocol = binaryReader.ReadByte(); //16 бит для контрольной суммы sChecksum = IPAddress.NetworkToHostOrder(binaryReader.ReadInt16()); //32 бита для IP источника uiSourceIPAddress = (uint)(binaryReader.ReadInt32()); //32 бита IP назначения uiDestinationIPAddress = (uint)(binaryReader.ReadInt32()); //Высчитываем длину заголовка byHeaderLength = byVersionAndHeaderLength; //Последние 4 бита в версии и длине заголовка содержат длину заголовка //выполняем простые арифметические операции для их извлечения byHeaderLength <<= 4; byHeaderLength >>= 4; //Умножаем на 4 чтобы получить точную длину заголовка byHeaderLength *= 4; //Копируем данные (которые содержат информацию в соответствии с типом //основного протокола) в другой массив Array.Copy(byBuffer, byHeaderLength, //копируем с конца заголовка byIPData, 0, usTotalLength - byHeaderLength); } catch (Exception ex) { MessageBox.Show(ex.Message, "MJsniff", MessageBoxButtons.OK, MessageBoxIcon.Error); } } }
Класс содержит элементы данных, соответствующих полям заголовка IP. Ознакомтесь с RFC 791 для подробного изучения IP заголовка и его полей. Конструктор класса берет полученные байты и создает MemoryStream для полученной информации. Затем создает BinaryReader, чтобы считать данные байт за байтом из MemoryStream. Также отметим, что данные, полученные от сети, находятся в форме с обратным порядком байтов, в связи с этим мы используем IPAddress. NetworkToHostOrder, чтобы исправить порядок байтов. Это должно быть сделано для всех элементов данных.
P.S. На основе этого примера буду писать программку для мониторинга сети. До этого писал с использованием SharpPcap, но необходимость установки WinPcap заставила попробовать изобрести велосипед
Сниффер — это программный инструмент для перехвата сетевого трафика, который используется системными администраторами и хакерами. В этой статье мы напишем простой сниффер для перехвата трафика на Python.
Еще по теме: Как установить пакеты Python без интернета
Хакеры и специалисты по информационной безопасности могут использовать снифферы для выявления недостатков безопасности подключенных к сети устройств. С помощью сниффера можно перехватить пароли и другую личную информацию.
Снифферы делятся на две основные категории:
- Активные снифферы — анализаторы трафика, которые взаимодействуют с устройствами.
- Пассивные снифферы — собирают дополнительные данные.
Кроме хакинга, снифферы могут быть полезны в разных других сценариях. Они могут помочь в определении проблемных мест в локальной сети, собрать статистические данные об использовании сети и т.д.
Как работают анализаторы пакетов
Прежде чем мы пойдем дальше, важно понимать работу сетей. Для этого можно представить сеть, как ряд взаимосвязанных узлов. Каждый узел представляет собой одно устройство (смартфон, ноутбук, настольный ПК и т.д.) подключенное к Интернету.
Эти узлы отправляют данные по сети с помощью пакетов данных. Снифферы могут собирать данные в пассивном режиме, отслеживая данные в пути или посредством активного сниффинга, когда они отправляют на подключенных устройства специально созданные запросы.
Каждый пакет будет содержать данные об источнике, получателе, флагах и данных, а также другие параметры. В этой статье мы не будем углубляться в эту тему, но я рекомендую изучить устройство сетей самостоятельно.
Создание сниффера для анализа трафика на Python
В этом руководстве рассмотрим создание пассивного сниффера.
Итак, откройте VS Code и создайте файл
main.py. Начнем с трех операций импорта, которые помогут открыть сокет для захвата сетевых данных и распаковки отформатированных данных. Этот импорт выглядит следующим образом:
import socketi mport struct import binascii |
Далее откроем сокет и возьмем переменные длиной до 2048 бит. В функцию сокета нужно будет передать три переменные:
- Первая указывает интерфейс пакета Windows (AF_INET).
- Вторая указывает, что мы открываем необработанный сокет.
- Третья указывает интересующий протокол, который в данном случае является протоколом IP.
Для получения пакетов размером 2048 в бесконечном цикле будем использовать функцию recvfrom. Код выглядит следующим образом:
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket. htons(0x0800)) #Creating socket while True: packet = s.recvfrom(2048) |
Теперь, нужно вывести отформатированные данные пакета. Для этого будем использовать импорт struct и binascii. Учитывая, что в этом примере нас интересует IP-адрес источника и получателя, нам нужна только первая строка в пакете. Возьмем первые 16 байт этого заголовка и распечатаем их следующим образом:
ethernet_header = packet[0][0:14] # Get Ethernet Header eth_header = struct.unpack(«!6s6s2s», ethernet_header) print («Destination MAC:» + binascii.hexlify(eth_header[0]) + » Source MAC:» + binascii.hexlify(eth_header[1]) + » Type:» + binascii.hexlify(eth_header[2])) |
Запуск этого кода от имени администратора (или использование
sudo, если вы работаете в Linux) должен отобразить все пакеты в терминале.
Это пример простого пассивного сниффера на Python.
РЕКОМЕНДУЕМ:
- Создание пейлоада на Python для взлома камеры
- Написание спуфера на Python для подмены почты
- Как использовать pynput для создания кейлоггера на Python