Тоталитарный контроль трафика. Ловим и контролируем весь TCP/UCP-трафик на компьютереМы проводим в интернете море времени, иногда сетуя на злого провайдера и медленный трафик. Зачастую это происходит из-за того, что «левые» или троянские приложения ломятся в сеть за обновлениями и отбирают драгоценный трафик. У каждого из нас может быть запущено множество процессов — аська (иногда и не одна), торрент, майл-агент и парочка браузеров. Всем им нужна сеть. А если ты сидишь с GPRSмодема? Ой-ой-ой. С помощью материала из этой статьи ты сможешь узнать, как отследить и наказать злобного нарушителя, съедающего твой трафик. ИнструментарийС целью организации хорошего улова нам понадобится любой С/ С++ компилятор, прямые руки и немного мозгов. Итак, для получения всех соединений мелкомягкие предоставляют набор функций библиотеки iphlplib.dll. Не ко всем компиляторам поставляются актуальные на сегодняшний день заголовочные файлы, поэтому функции будем вызывать по их адресу. Сегодня мы станем использовать пришедшие на смену старым функции GetTcpTable(), GetUdpTable(), GetExtendedTcpTable() и GetExtendedUdpTable(). Кстати, для последних двух необходим, как минимум, Windows XP SP2 (вряд ли это составит для тебя проблему). Функции AllocateAndGetTcpTableFromSt ack() и ей подобные, с таким трепетом рекомендуемые на множестве форумов, я использовать не буду по причине их древности — современными ОС они не поддерживаются. Все наши функции хранятся в библиотеке Iphlpapi.dll, располагающейся в системной директории. TCPФункция GetTcpTable() получает таблицу всех Tcp-соединений в системе:
Здесь мы объявили прототип этой функции (PROCGETTCPTABLE). Итак, рассмотрим параметры подробнее. Всего их три: pTcpTable — указатель на выделенный буфер, куда будет записана таблица MIB_TCPTABLE. pdwSize — размер выделенного буфера; если же буфера будет недостаточно, то в эту переменную запишется размер буфера, нужного для размещения таблицы. bOrder — если TRUE, то указывает, что полученную таблицу нужно отсортировать по следующим параметрам в порядке: 1. Локальный IP-адрес. Функция при успехе возвращает NO_ERROR; при ошибке возможно несколько значений, здесь мы рассмотрим только одно: UDPТеперь перейдем к UDP-соединениям. Прототип, согласно MSDN, выглядит так:
Про последние два параметра мы уже все знаем (правда, сортировка идет только по IP-адресу и порту), а указатель на структуру имеет тип PMIB_UDPTABLE, так как сама таблица немного отличается. Структура таблицРассмотрим таблицу, в которую занесутся TCP-соединения, MIB_ TCPTABLE. Она определена ниже и значения ее полей ясны из названия. Отмечу только, что адреса и порты представлены в сетевом формате (старший байт по старшему адресу):
Параметр dwNumEntries — количество записей, то есть соединений, а table — массив записей, имеющих вот такой вид:
Как видишь, тут присутствует состояние соединения (ожидает ли оно подключения, установлено или уже закрывается), локальные и удаленные IP-адрес с портом. Структуру UDP-таблиц ты можешь найти в MSDN или в приложении к журналу, а пока я приведу код, который покажет все TCP-соединения в системе: Функция, получающая все TCP-соединения в системе
Попробую объяснить вышеприведенный исходник. В начале мы выделяем память под указатель, затем вызываем функцию с нулевым dwSize. Удивительно, не правда ли? Это делается с целью узнать актуальный (необходимый) размер структуры, чтобы туда поместился весь список соединений (помнишь? при нехватке места функция возвращает необходимый). Далее мы резервируем память и вызываем функцию. И в цикле печатаем удаленный адрес, порт и состояние соединения, переводя порт и IP из сетевого формата в формат Intel. Вот и все, в прилагаемых файлах смотри полный исходник функции. Берем сеть под контрольВдумчивый читатель (то есть, ты), наверняка, задался вопросом: «как же мы будем контролировать сеть? Ведь мы еще ничего не знаем о самом соединении». Спокойно! Сейчас я познакомлю тебя и с Ex-функциями этого семейства, которые появились на свет, начиная с Windows XP. Эти функции перехватывают многие руткиты и используют все файрволы, поскольку дают нам всю информацию о сети. Вот они:
Помимо открытых портов, функции поддерживают IPv6, позволяют выводить не только имя процесса, породившего соединение, но и имя модуля. Для нас они подходят просто идеально — будем охотиться на зверька, который решил прогуляться по сети. Эти функции принимают первый параметр как нетипизированный указатель. Почему нетипизированный? Потому что тип структуры, куда занесется результат, заранее не известен и зависит от параметра TableClass. А параметр этот может принимать много значений, в частности, возможна выборка прослушивающих, установленных соединений, всех вместе, а также он может получать ID процесса или даже имя модуля, открывшего соединение. Это справедливо для UDP и TCP модулей. Еще надо учесть, что параметр ulAf принимает беззнаковое целое число, обозначающее получение IPv4 или IPv6 (AF_INET и AF_INET6) соответственно. Но так как IPv6 обладает большим рядом параметров, чем IPv4, то количество типов таблиц будет равно 5 (для IPv6 нельзя получить параметры соединения без PID). Нас будет интересовать структура типа MIB_TCPTABLE_OWNER_ PID, в нее занесутся параметры соединений и PID каждого процесса. Структура данных
Как мы видим, от структуры MIB_TCPROW эта отличается наличием поля dwOwnigPid. А теперь — приведем отслеживающий шпиона код:
Этот кусок кода выведет нам все процессы и места, куда они коннектятся, что позволит тут же выявить нарушителя границы. Функция GetProcessNameByID моя, она определяет имя процесса по его идентификатору, исходник ты сможешь найти во врезке. Кстати, не забудь объявить ее прототип:
После инициализации функция может быть вызвана как обычная. Не забывай делать всевозможные проверки в коде — они у меня опущены в виду того, что журнал не резиновый. С UDP-подключениями ситуация полностью аналогична, новое будет только в IPv6 — там структура содержит еще и ScopeID-подключения. ЗаключениеПолный исходник программы ты можешь найти на DVD, она определяет порты подключений и представляет собой своеобразный, расширенный аналог netstat’a. Как видишь, вся работа очень проста, и ты можешь дополнить программу многими удобными функциями. Например, резолвить DNS (т.е. определять имена хостов, например, через функцию Winsock gethostbyaddr), сделать автообновление, убивать неугодный процесс, задействовать очень полезную опцию «отображать только нелокальные подключения» — ведь многие программы открывают подключения на локалхост, а их нам мониторить не нужно. Графические программы с таким функционалом я встречал, а вот консольных аналогов не видел, надеюсь, она будет тебе полезна. До новых встреч! Links
|