Главная - Данные
Анализаторы сетевых пакетов. Wireshark (перехватчик сетевых пакетов) Как с помощью wireshark проверить порт

Общая схема

Последовательность шагов, которая должна выполнить программа, использующая библиотеку pcap (от PacketCAPture) для выполнения своей задачи, такова:

  • Определить сетевой интерфейс, который будет прослушиваться. (В Linux это может быть eth0, в BSD xl1).
  • Инициализировать pcap . При этом библиотеке сообщается, на каком интерфейсе мы будем слушать данные. Возможно прослушивание нескольких интерфейсов одновременно (в разных сессиях).
  • В случае необходимости создать фильтр (например, нас интересуют только TCP пакеты, приходящие на порт 23), "скомпилировать" этот фильтр и применить к той или иной сессии.
  • Перейти в цикл приема пакетов. После этого всякий раз, когда приходит очередной пакет и он проходит через указанный фильтр, вызывается функция, которую нужно заранее определить. Эта функция может выполнять любые действия, которые мы захотим. Она может разбирать пакет и выдавать его пользователю, может сохранять его на диск или вообще ничего не делать.
  • По окончании работы нужно закрыть все открытые сессии.

Рассмотрим перечисленные шаги подробно.

Определение интерфейса

Для определения интерфейса, на котором необходимо производить прослушивание, можно воспользоваться двумя способами.

Первый состоит в том, что имя интерфейса задает пользователь. Рассмотрим следующую программу:

#include #include Int main(int argc, char *argv) { char *dev = argv; printf("Device: %s\n", dev); return(0); }

Пользователь указывает интерфейс, передавая его имя через первый аргумент нашей программы. Естественно, указываемый пользователем интерфейс должен существовать.

Второй способ - узнать имя интерфейса у самой библиотеки:

#include #include Int main() { char *dev, errbuf; dev = pcap_lookupdev(errbuf); printf("Device: %s\n", dev); return(0); }

В этом случае pcap передает нам имя интерфейса, которым он владеет. В строку errbuf будет передано описание ошибки, если таковая возникнет при исполнении вызова pcap_lookupdev() .

Открытие интерфейса для перехвата пакетов

Для создания сессии перехвата трафика необходимо вызвать функцию pcap_open_live() . Прототип этой функции (из страницы руководства по pcap) выглядит следующим образом:

Pcap_t *pcap_open_live (char *device, int snaplen, int promisc, int to_ms, char *ebuf)

Первый аргумент - имя устройства, которое мы определили на предыдущем шаге. snaplen - целое число, определяющее максимальное количество байт сетевого кадра, которое будет захватываться библиотекой. Если promisc установлен в true, интерфейс переходит в так называемый promiscuous mode (перехватываются пакеты, адресованные другим станциям сети). to_ms - тайм-аут в миллисекундах (в случае, если значение установлено в ноль, чтение будет происходить до первой ошибки, в минус единицу - бесконечно). Наконец, errbuf - строка, в которую мы получим сообщение об ошибке. Функция возвращает хэндл (дескриптор) сессии.

Для демонстрации рассмотрим фрагмент кода:

#include Pcap_t *handle; handle = pcap_open_live(somedev, BUFSIZ, 1, 0, errbuf);

Здесь открывается интерфейс, имя которого указано в строке somedev , указывается сколько байт пакета захватывать (значение BUFSIZ определено в pcap.h). Сетевой интерфейс переключается в promiscuous режим. Данные будут читаться до тех пор, пока не произойдет ошибка. В случае ошибки можно вывести ее текстовое описание на экран, используя указатель errbuf.

Замечание по поводу перехвата трафика в promiscuous и non-promiscuous режимах: эти два метода очень отличаются. В случае перехвата трафика в non-promiscuous режиме узел получает только тот трафик, который направлен или относится к нему. Только трафик до, от и маршрутизируемый через хост будет перехвачен нашей программой. В promiscuous режиме сетевой интерфейс принимает все пакеты, идущие через кабель. В некоммутируемом окружении это может быть весь сетевой трафик. Его явное преимущество в том, что он предоставляет большее количество пакетов для перехвата, что может быть (или может не быть) полезным, в зависимости от того, для чего вы перехватываете сетевой поток.

Однако, перехват трафика в promiscuous режиме можно обнаружить; другой узел может с высокой точностью определить, используем ли мы promiscuous режим. Кроме того, он работает только в некоммутируемом окружении (таком как концентраторы или коммутаторы, которые затоплены arp пакетами). В третьих, в случае, если сеть сильно загружена, наша программа будет использовать большое количество системных ресурсов.

Фильтрация трафика

Часто перехватчик пакетов нужен для перехвата не всех, а только определенных пакетов. Например, бывают случаи, когда мы хотим перехватывать трафик на 23-тий порт (telnet) в поисках паролей. Или, возможно, мы хотим перехватить файл, которые пересылается по 21-му порту (FTP). Возможно, мы хотим перехватывать только DNS трафик (53-ий порт UDP). В любом случае, очень редко необходимо перехватывать все данные. Для фильтрации трафика предназначены функции pcap_compile() и pcap_setfilter() .

После того, как мы вызвали pcap_open_live() и получили функционирующую сессию перехвата трафика, мы можем применить наш фильтр. Естественно, можно реализовать фильтр вручную, разбирая ETH/IP/TCP заголовки после получения пакета, но использование внутреннего фильтра pcap более эффективно, и кроме того, это проще.

Перед тем тем, как применить фильтр, нужно его "скомпилировать". Выражение для фильтра хранится в обыкновенной строке (массиве символов). Синтаксис таких выражений подробно описан в странице руководства по tcpdump (man tcpdump).

Для компиляции фильтра используется функция pcap_compile() . Ее прототип выглядит следующим образом:

Int pcap_compile(pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32 netmask)

Первый аргумент - хэндл (дескриптор) нашей сессии (pcap_t *handle в предыдущем примере). Следующий аргумент - указатель на область в памяти, где мы будем хранить скомпилированную версию нашего фильтра. Далее идет само выражение фильтра в виде обычной строки. Следующий параметр определяет, нужно ли оптимизировать наше выражение или нет (как обычно, 0 означает "нет", 1 - "да"). Последний параметр - маска сети, к которой применяется наш фильтр. Функция возвращает -1 в случае ошибки, все другие значения говорят о успешном завершении.

После того, как выражение скомпилировано, его нужно применить, что осуществляется с помощью функции pcap_setfilter() . Ее прототип таков:

Int pcap_setfilter(pcap_t *p, struct bpf_program *fp)

Первый аргумент - хэндл(дескриптор) нашей сессии перехвата пакетов, второй - указатель на скомпилированную версию выражения для фильтра (как правило - второй аргумент функции pcap_compile()).

В нижеследующем примере демонстрируется использование фильтра:

#include Pcap_t *handle; // дескриптор сессии char dev = "eth0"; // интерфейс, на котором мы будем слушать char errbuf; // Строка с ошибкой struct bpf_program filter; // Скомпилированное выражение для фильтра сhar filter_app = "port 23"; // Выражение для фильтра bpf_u_int32 mask; // Сетевая маска нашего интерфейса bpf_u_int32 net; // IP адрес нашего интерфейса pcap_lookupnet(dev, &net, &mask, errbuf); handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf); pcap_compile(handle, &filter, filter_app, 0, net); pcap_setfilter(handle, &filter);

Эта программа подготавливает перехватчик для пакетов, идущих на или с 23-го порта, в promiscuous режиме, на интерфейсе eth0. Пример содержит функцию pcap_lookupnet() , которая возвращает сетевой адрес и маску сети для устройства, имя которого передано ей как параметр. Ее использование необходимо, так как для того, чтобы наложить фильтр, мы должны знать адрес и маску сети.

Перехват пакетов

Существуют две техники перехвата пакетов. Можно перехватывать и обрабатывать по одному пакету, а можно работать с группой пакетов, задав специальный цикл, который будет работать, пока pcap не перехватит заданное количество пакетов. Для работы в первом режиме используется функция pcap_next() . Прототип pcap_next() :

U_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)

Первый аргумент - хэндл нашей сессии, второй - указатель на структуру, в которой будет храниться такая информация о пакете, как время, когда он был перехвачен, длина пакета и длина его отдельной части (например, в случае, если пакет фрагментирован). pcap_next() возвращает указатель u_char на область памяти, где хранится пакет, описанный этой структурой.

Демонстрация использования pcap_next() для перехвата одного пакета:

#include #include int main() { pcap_t *handle; char *dev; char errbuf; // строка с описанием ошибки struct bpf_program filter; // скомпилированный фильтр char filter_app = "port 23"; // фильтр bpf_u_int32 mask; // сетевая маска bpf_u_int32 net; // наш ip адрес struct pcap_pkthdr header; // заголовок пакета, который заполнит pcap const u_char *packet; // сам пакет // определим интерфейс dev = pcap_lookupdev(errbuf); // получим сетевой адрес и маску интерфейса pcap_lookupnet(dev, &net, &mask, errbuf); // откроем сессию перехвата в promiscuous режиме handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf); // скомпилируем и применим пакетный фильтр pcap_compile(handle, &filter, filter_app, 0, net); pcap_setfilter(handle, &filter); // перехватим пакет packet = pcap_next(handle, &header); // выведем его длину в консоль printf("Jacked a packet with length of [%d]\n", header.len); // закроем сессию pcap_close(handle); return(0); }

Эта программа перехватывает пакеты на устройстве, которое возвращает pcap_lookupdev() , переводя его в pormiscuous режим. Она обнаруживает пакет, который идет через 23-ий порт (telnet) и выводит его размер в байтах. Вызов pcap_close() закрывает открытую сессию перехвата.

Альтернативный метод, хотя и более труден для понимания, но, скорее всего, более полезен. Существуют очень мало (если вообще существуют) перехватчиков пакетов, которые используют pcap_next() . В подавляющем большинстве случаев они используют pcap_loop() или pcap_dispatch() (который, в свою очередь, использует pcap_loop()). Для того, чтобы понять использование этих двух функций, нужно понимать идею callback-функций (функций обратного вызова).

Callback-функции - часто использующийся прием программирования. Принцип довольно прост. Предположим, у вас есть программа, которая ожидает какого-либо события. С целью, например, обработки нажатия клавиши. Каждый раз, когда нажимается клавиша, я хочу вызывать функцию, которая обработает это событие. Функция, которую я использую - callback-функция. Каждый раз, когда пользователь нажимает клавишу, моя программа вызовет callback-функцию. Callback-функции используются в pcap , но вместо того, чтобы вызывать их, когда пользователь нажмет на клавишу, pcap вызывает их, когда получает очередной пакет. pcap_loop() и pcap_dispatch() - функции, которые практически одинаково используют механизм callback-функций. Обе вызывают callback-функцию, каждый раз, когда pcap перехватывает пакет, который проходит через фильтр (если, конечно, фильтр скомпилирован и применен к сессии, в противном случае callback-функции передаются все перехваченные пакеты)

Прототип функции pcap_loop():

Int pcap_loop (pcap_t *p, int cnt, pcap_handler callback, u_char *user);

Первый аргумент - хэндл нашей сессии. Следующее целое число говорит pcap_loop() сколько всего пакетов нужно перехватить (отрицательное значение обозначает, что перехват пакетов должен происходить, пока не произойдет ошибка). Третий аргумент - имя callback-функции (только имя, без скобок). Последний аргумент используется в некоторых приложениях, но обычно он просто установлен в NULL. pcap_dispatch() практически идентична, единственная разница в том, как функции обрабатывают таймаут, величина которого задается при вызове pcap_open_live() . pcap_loop() просто игнорирует таймауты, в отличие от pcap_dispatch() . Детали - в man pcap .

Перед тем, как привести пример использования pcap_loop() , мы должны рассмотреть формат нашей callback-функции. Мы не можем произвольно определить прототип callback-функции, так как pcap_loop() не будет знать, что с ней делать. Прототип нашей callback-функции должен быть таким:

Void got_packet (u_char *args, const struct pcap_pkthdr *header, const u_char *packet);

Рассмотрим его подробнее. Первое - функция возвращает пустое значение (void). Это логично, так как pcap_loop() не может знать, что делать с возвращаемым значением. Первый аргумент совпадает с последним аргументом pcap_loop(). Какое бы значение не использовалось как последний аргумент pcap_loop() , оно пробрасывается в качестве первого аргумента callback-функции каждый раз когда она вызывается из pcap_loop() . Второй аргумент - заголовок pcap , который содержит информацию о том, когда был перехвачен пакет, его размер и т.д. Структура pcap_pkthdr определена в pcap.h следующим образом:

Struct pcap_pkthdr { struct timeval ts; // временная метка bpf_u_int32 caplen; // длина захваченной части пакета bpf_u_int32 len; // полная длина пакета };

Последний аргумент callback-функции наиболее интересен. Это указатель на буфер, который и содержит, собственно, весь пакет, перехваченный с помощью pcap_loop() .

Как использовать переменную packet ? Пакет содержит множество атрибутов, так что, как вы можете представить, он на самом деле не строка, а некоторый набор структур (например, пакет TCP/IP будет содержать ethernet-, ip-, tcp-заголовок и сами данные). Параметр packet , имеющий тип u_char , на самом деле сериализованная версия этих структур. Для того, чтобы получить полезные данные из этих структур, мы должны провести некоторые преобразования.

В первую очередь мы должны иметь определенные в программе структуры, которыми мы будем пользоваться. Мы будем использовать следующие структуры (на самом деле мы могли бы взять их напрямую из заголовочных файлов, но названия полей структур изменяются от платформы к платформе, поэтому, в демонстрационных целях используются эти):

Struct sniff_ethernet { u_char ether_dhost; u_char ether_shost; u_short ether_type; /* IP? ARP? RARP? etc */ }; // IP заголовок struct sniff_ip { #if BYTE_ORDER == LITTLE_ENDIAN u_int ip_hl:4, ip_v:4; #endif #if BYTE_ORDER == BIG_ENDIAN u_int ip_v:4, /* version */ ip_hl:4; /* header length */ #endif /* not _IP_VHL */ u_char ip_tos; u_short ip_len; u_short ip_id; u_short ip_off; #define IP_RF 0x8000 /* reserved fragment flag */ #define IP_DF 0x4000 /* dont fragment flag */ #define IP_MF 0x2000 /* more fragments flag */ #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ u_char ip_ttl; /* time to live */ u_char ip_p; /* protocol */ u_short ip_sum; /* checksum */ struct in_addr ip_src,ip_dst; /* source and dest address */ }; struct sniff_tcp { u_short th_sport; u_short th_dport; tcp_seq th_seq; /* sequence number */ tcp_seq th_ack; /* acknowledgement number */ #if BYTE_ORDER == LITTLE_ENDIAN u_int th_x2:4, /* (unused) */ th_off:4; /* data offset */ #endif #if BYTE_ORDER == BIG_ENDIAN u_int th_off:4, /* data offset */ th_x2:4; /* (unused) */ #endif u_char th_flags; #define TH_FIN 0x01 #define TH_SYN 0x02 #define TH_RST 0x04 #define TH_PUSH 0x08 #define TH_ACK 0x10 #define TH_URG 0x20 #define TH_ECE 0x40 #define TH_CWR 0x80 #define TH_FLAGS \ (TH_FIN|TH_SYN|TH_RST|\ TH_ACK|TH_URG|TH_ECE|TH_CWR) u_short th_win; /* window */ u_short th_sum; /* checksum */ u_short th_urp; /* urgent pointer */ };

Если используются описания структур из стандартных заголовочных файлов, то иногда для того, чтобы программа, использующая описание TCP-заголовка, откомпилировалась без ошибок, нужно определить символ _BSD_SOURCE , перед подключением заголовочных файлов. Альтернативный способ - определить структуры, описывающие TCP-заголовок, вручную.

pcap , естественно, использует точно такие же структуры, когда перехватывает пакеты. Затем он просто создает u_char строку (буфер) и копируют данные из структур в нее. Как разобрать строку обратно на структуры? Это легко делается с помощью указателей и преобразований типов.

Сначала объявим переменные, которые нам нужны для разбора u_char пакета на отдельные заголовки:

Const struct sniff_ethernet *ethernet; const struct sniff_ip *ip; const struct sniff_tcp *tcp; const char *payload; int size_ethernet = sizeof(struct sniff_ethernet); int size_ip = sizeof(struct sniff_ip); int size_tcp = sizeof(struct sniff_tcp);

Теперь делаем преобазование типов:

Ethernet = (struct sniff_ethernet*)(packet); ip = (struct sniff_ip*)(packet + size_ethernet); tcp = (struct sniff_tcp*)(packet + size_ethernet + size_ip); payload = (u_char *)(packet + size_ethernet + size_ip + size_tcp);

После этого мы можем обращаться к полям всех структур обычным образом, например:

If (tcp->th_flags & TH_URG) { ... }; ... printf("TTL = %d\n", ip->ip_ttl);

Завершение работы

По завершении работы нужно закрыть сессию. Это делается с помощью функции pcap_close() .

У каждого из команды ][ свои предпочтения по части софта и утилит для
пен-теста. Посовещавшись, мы выяснили, что выбор так разнится, что можно
составить настоящий джентльменский набор из проверенных программ. На том и
решили. Чтобы не делать сборную солянку, весь список мы разбили на темы – и в
этот раз коснемся утилит для снифинга и манипулирования пакетами. Пользуйся на
здоровье.

Wireshark

Netcat

Если говорить о перехвате данных, то Network Miner снимет с «эфира»
(или из заранее подготовленного дампа в PCAP-формате) файлы, сертификаты,
изображения и другие медиа, а также пароли и прочую инфу для авторизации.
Полезная возможность - поиск тех участков данных, что содержат ключевые слова
(например, логин пользователя).

Scapy

Сайт:
www.secdev.org/projects/scapy

Must-have для любого хакера, представляющий собой мощнейшую тулзу для
интерактивной манипуляции пакетами. Принять и декодировать пакеты самых
различных протоколов, ответить на запрос, инжектировать модифицированный и
собственноручно созданный пакет - все легко! С ее помощью можно выполнять целый
ряд классических задач, вроде сканирования, tracorute, атак и определения
инфраструктуры сети. В одном флаконе мы получаем замену таких популярных утилит,
как: hping, nmap, arpspoof, arp-sk, arping, tcpdump, tetheral, p0f и т.д. В то
же самое время Scapy позволяет выполнить любое, даже самое специфическое
задание, которое никогда не сможет сделать уже созданное другим разработчиком
средство. Вместо того чтобы писать целую гору строк на Си, чтобы, например,
сгенерировать неправильный пакет и сделать фаззинг какого-то демона, достаточно
накидать пару строчек кода с использованием Scapy ! У программы нет
графического интерфейса, а интерактивность достигается за счет интерпретатора
Python. Чуть освоишься, и тебе уже ничего не будет стоить создать некорректные
пакеты, инжектировать нужные фреймы 802.11, совмещать различные подходы в атаках
(скажем, ARP cache poisoning и VLAN hopping) и т.д. Разработчики сами настаивают
на том, чтобы возможности Scapy использовались в других проектах. Подключив ее
как модуль, легко создать утилиту для различного рода исследования локалки,
поиска уязвимостей, Wi-Fi инжекции, автоматического выполнения специфических
задач и т.д.

packeth

Сайт:
Платформа: *nix, есть порт под Windows

Интересная разработка, позволяющая, с одной стороны, генерировать любой
ethernet пакет, и, с другой, отправлять последовательности пакетов с целью
проверки пропускной способности. В отличие от других подобных тулз, packeth
имеет графический интерфейс, позволяя создавать пакеты в максимально простой
форме. Дальше - больше. Особенно проработано создание и отправка
последовательностей пакетов. Ты можешь устанавливать задержки между отправкой,
слать пакеты с максимальной скоростью, чтобы проверить пропускную способность
участка сети (ага, вот сюда-то и будут ддосить) и, что еще интереснее -
динамически изменять параметры в пакетах (например, IP или MAC-адрес).

Кроме подключения к каналу передачи данных, мопитор должен иметь эффективный способ идентифицировать, какие IP-иакеты перехватывать при их поступлении. Протоколы прикладного уровня Обычно связапы с определенным ТСР-пор- том, например, HTTP использует порг 80. Для отслеживания НТТР-трафика монитор пакетов может ограничиться учетом ТСР-трафика на порту 80. Такое решение может быть принято для каждого конкретного пакета путем анализа поля протокола в IP-заголовке и номеров портов источника и места назначения в TCP- заголовке. Однако выделить весь НТТР-трафик достаточно трудно. Некоторые Web-сайты не используют данный порт, а порты 8000 или 8080. Кроме того, некоторые приложения могут взаимодействовать через порт 80, используя другой протокол. Хотя порты выделяются определенным приложениям, разработчик приложения или системный администратор могут игнорировать эти указания и задействовать порт 80 для приложения, использующего другой протокол.

Кроме того, в Web имеется протокол HTTPS, использующий порт 443. Мопитор пакетов может захватить HTTPS-трафик путем отслеживания ТСР-трафика, содержащего в качестве номера порта источника и места назначения порт 443. Однако данные, передаваемые через HTTPS, зашифрованы с применением Secure Socket Layer (SSL). Монитор не может идентифицировать НТТР-сообщения, передаваемые через эти ТСР-соедииения. Однако может перехватывать ТСР-трафик на порту 443 с целью расчета основных статистических показателей, таких как число соединений и байтов, передаваемых с помощью HTTPS. Другие передачи, инициированные Web-браузером, могут использовать другие протоколы прикладного уровня. В некоторых случаях этот трафик может перехватываться путем мониторинга портов, выделенных этим протоколам. Однако ряд приложений использует протоколы, которые динамически назначают номера порто» при передаче данных. Например, клиент и сервер File Transfer Protocol (FTP) могут динамически выбирать номер порта для ТСР-соединеиия, используемого для передачи данных. Аналогично многие протоколы для передачи мультимедийных потоков Обычно не используют определенные номера портов для передачи данных аудио и видео, о чем подробнее будет говориться далее в разделе 14.4.4.

Перехват трафика с определенными IP- и TCP-заголовками требует применения фильтра к IP-пакетам по мере их поступления. Как Можно более ранняя фильтрация пакетов сокращает издержки, связанные с копированием и обработкой пакетов, которые будут затем отвергнуты. Мопитор пакетов может иметь специальное аннаратное обеспечение, которое осуществляет классификацию пакетов при их приеме сетевой картой. Если аннаратная поддержка отсутствует, пакеты могут отфильтровываться операционной системой или приложением. Большое число программ мониторинга пакетов основывается на ипструмепталыюм средстве tcpdump

LJLM, Tcpj на основе фильтра пакетов Berkeley Packet Filter (BPF) }

 


Читайте:



Вывод части изображения html спрайт

Вывод части изображения html спрайт

Существует множество методов по оптимизации веб-страниц. Какие-то из них работают, какие-то уже нет. Тем не менее есть некоторые методы,...

Настройка дополнительных реквизитов и дополнительных сведений номенклатуры 1с дополнительные реквизиты и сведения отличия

Настройка дополнительных реквизитов и дополнительных сведений номенклатуры 1с дополнительные реквизиты и сведения отличия

» подсистема дополнительных реквизитов была существенно усовершенствована, и работать с ней стало намного удобнее. Однако сначала нужно разобраться...

Что делать, когда нет регистрационных данных

Что делать, когда нет регистрационных данных

Причины для переноса 1С (или базы данных) с компьютера на компьютер могут быть самыми разными – обновление в компании парка оборудования, желание...

Запрос на выборку данных (формулы) в MS EXCEL Эксель выборка по условию макрос

Запрос на выборку данных (формулы) в MS EXCEL Эксель выборка по условию макрос

С помощью средств Excel можно осуществлять выборку определенных данных из диапазона в случайном порядке, по одному условию или нескольким. Для...

feed-image RSS