Снифер своими руками: отслеживание входящего трафика
Введение
Попробуем для начала разобраться с самим понятием
снифер. Откуда оно взялось и что это такое? Разберемся с терминологией.
Слово sniffer (дословно с английского это можно перевести как
"нюхатель") в самом общем смысле суть некое прослушивающее устройство,
внедренное в сеть для перехвата передаваемых по ней данных. В некоторой
литературе и документации, а также в электронных словарях типа Lingvo,
термин sniffer (network sniffer) отождествляется с такими понятиями,
как "анализатор сетевого трафика", "анализатор пакетов", "анализатор
протоколов", "сетевой анализатор". А в более узком смысле - это ПО,
созданное для мониторинга сетевого потока и/или его анализа. Изначально
такие программы задумывались в помощь системным администраторам для
анализа проблем сети. Но
сниферы, как большинство программного обеспечения для сисадминов,
широко распространились и среди хакеров. Ведь такие вещи можно
использовать и для перехвата паролей и другой незашифрованной
информации, приходящей из сети, и исходящей в Сеть.
Что мы будем делать
Попробуем разобрать один из способов работы
снифера и напишем такую программу сами. Это будет несложная программа
без всяких драйверов, работающая в системе Windows 2000 и выше и
требующая прав администратора. Такие ограничения, конечно, не
вдохновляют, но все же если писать программу не для корыстных целей, то
такие условия достаточно приемлемы. В дальнейшем будет ясно, ЧТО и КАК
нас ограничивает. Для перехвата входящего трафика нашему
сниферу не потребуются внешний *.sys и *.dll файлы. Будут
использоваться исключительно возможности операционной системы.
Условимся сразу, что наш
снифер должен отлавливать приходящие пакеты с самым популярным набором
протоколов - таких, как IP, TCP, UDP, ICMP, IGMP, GGP, IPv6, ICMPv6.
Пишем простой снифер
Начнем с того, что нам нужно написать снифер, который можно будет
настраивать. Сделаем фильтр по протоколу, т.е. не будем пропускать в
лог пакеты, не относящиеся к интересующему нас протоколу. Также
реализуем возможности записи в лог IP получателя (наш), IP отправителя,
имени протокола и длины пакета. В нашей программе, помимо этого, можно
будет задавать имя файла лога. Он будет храниться в той же директории,
что и наш
снифер. После всего, что мы сделаем, окно нашей программы будет
выглядеть так:
Теперь перейдем к рассмотрению кода. Полный исходник нашей программы и
ее рабочий вариант можно скачать по ссылке в конце статьи. Напишем
программу на Visual C++ 6.0. Выбор этой среды разработки обоснован тем,
что она мне по душе.
Начинаем, естественно, с инициализации сокетов. Пусть это будет WinSock 2.2:
Теперь необходимо привязать локальный адрес к нашему сокету:
bind(s, (SOCKADDR*)&sa, sizeof SOCKADDR);
И, наконец, самое главное - включение режима promiscuous, о котором мы говорили ранее:
DWORD flag = TRUE;
ioctlsocket(s, SIO_RCVALL, &flag);
Здесь мы включаем режим приема всех приходящих из Сети пакетов,
указанием в качестве команды сокету SIO_RCVALL. Объявление этой
константы находится в заголовочном файле Mstcpip.h. Переменная flag
включает и выключает режим (TRUE/FALSE). В документации Microsoft про
эту команду сказано следующее:
Enables a socket to receive all IP packets on the network. The
socket handle passed to the WSAIoctl function must be of AF_INET
address family, SOCK_RAW socket type, and IPPROTO_IP protocol. The
socket also must be bound to an explicit local interface, which means
that you cannot bind to
INADDR_ANY.
Что в буквальном смысле означает: команда SIO_RCVALL позволяет
сокету принимать все IP пакеты из Сети. Дескриптор сокета (в нашем
случае это s), переданный в функцию WSAIoctl (мы используем просто
ioctlsocket), должен быть из семейства адресов AF_INET (internetwork),
тип этого сокета должен быть SOCK_RAW и протокол - IPPROTO_IP. Сокет
также должен быть связан с явным локальным интерфейсом, т.е. нельзя его
связать просто с INADDR_ANY. Соблюдая эти правила, мы и создаем сокет с
дескриптором s. Очень важно понимать, что Raw-сокеты могут принимать
множество неожиданных пакетов.
Заметим, что режим promiscuous включается только при активной системной
плате или при выходе в Internet. В общем, он возможен, только когда
есть какая-либо Сеть, будь то Internet или LAN. Если мы вызовем функцию
ioctlsocket с параметром SIO_RCVALL на машине без сети, то получим
ошибку.
Теперь попытаемся понять, почему наш снифер требует привилегий администратора. Microsoft пишет по этому поводу следующее:
Setting this ioctl requires Administrator privilege on the local
computer. SIO_RCVALL is available in Windows 2000 and later versions of
Windows.
Теперь должно быть ясно, что явно требуются привилегии
администратора. Также выясняется и то, что команда SIO_RCVALL доступна,
начиная с Windows 2000. Если
снифер запустит не администратор, функция bind не даст привязать сокет
к локальному адресу. Она возвратит ошибку WSAEACCES (10013 в десятичной
системе - не достаточно прав). Причем в MSDN сказано, что можно поднять
свои привилегии включением опции сокета SO_EXCLUSIVEADDRUSE:
Possible reason for the WSAEACCES error is that when the bind
function is called (on Windows NT 4 SP4 or later), another application,
service, or kernel mode driver is bound to the same address with
exclusive access. Such exclusive access is a new feature of Windows NT
4 SP4 and later, and is implemented by using the SO_EXCLUSIVEADDRUSE
option.
Т.е. мы могли бы просто вызвать setsockopt с параметром SO_EXCLUSIVEADDRUSE следующим образом:
Но, поэкспериментировав с этим, я не пришел к положительному
результату, т.е. по-прежнему нам требуются привилегии администратора.
Итак, режим promiscuous включен. Как же нам получить входящие IP
пакеты? Очевидно, нужно постоянно вызывать функцию recv (в нашем
случае) или WSARecv. Но создавать отдельный поток и делать бесконечный
цикл было бы не очень удобно. Гораздо лучше для нас использовать
асинхронные сокеты. Тем более, что у нас GUI-программа. Впишем
следующий вызов функции WSAAsyncSelect в обработчик кнопки "Start" (эта
кнопка не будет доступна, пока promiscuous mode не включен):
case IDC_BUTTON_START:
CHAR szFileName[_MAX_FNAME];
//Связываем событие FD_READ с окном
WSAAsyncSelect(s, hwndDlg, WM_RECV, FD_READ);
//...
}
break;
Здесь мы указываем функции, что окну с хендлом hwndDlg нужно отправить
сообщение WM_RECV при наступлении события FD_READ для сокета s. Событие
FD_READ приходит, когда сокет готов к чтению данных, т.е. когда
приходят данные. Сообщение WM_RECV объявим следующим образом:
#define WM_RECV (WM_USER + 1)
В MSDN про вызов функции recv написано следующее:
Once the socket is bound and the ioctl set, calls to the WSARecv or
recv functions return IP datagrams passing through the given interface.
Note that you must supply a sufficiently large buffer.
Т.е. мы должны предоставить функции recv буффер достаточного размера. В нашем
снифере он будет равен 64 Кб. Теперь напишем обработчик сообщения
WM_RECV:
case WM_RECV:
if (WSAGETSELECTEVENT(lParam) == FD_READ) {
//Буфер размера 64 Кб
CHAR btBuffer[65536];
//Получаем входящие данные
if (recv(s, btBuffer, sizeof(btBuffer), 0) >= sizeof(IPHeader)) {
IPHeader* hdr = (IPHeader*)btBuffer;
//Вычисляем размер. Т.к. в сети принят прямой порядок байт,
//а не обратный, то придется поменять байты местами.
WORD size = (hdr->iph_length << 8) + (hdr->iph_length >> 8);
Здесь, помимо приема пакета, у нас реализован фильтр по протоколу. Нам
не составило бы труда реализовать и фильтр по размеру пакета, по IP
адресам, но реализацию этих фильтров я оставляю читателю. Заголовок
пакета описывается структурой IPHeader. Она выглядит следующим образом:
//Структура заголовка 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;
Тестирование снифера
Теперь посмотрим на получившуюся программу в работе. Для
тестирования ее работы я решил использовать подключение к интернету, а
также виртуальную локальную сеть. Virtual LAN удобно использовать
когда нет реальной LAN, а работу своей программы необходимо
протестировать. Виртуальную LAN довольно удобно настраивать с помощью
VMware Workstation (у меня версия 5.5.0). Смоделируем локальную сеть
путем установки на виртуальную машину системы Windows 2000 Pro. На
хост-машине пусть будет Windows XP SP2. После настройки LAN менеджером
виртуальных сетей в VMware, получаем локальную сеть из 2-х компьютеров.
Перед тестированием нужно обязательно не забыть выключить Firewall,
т.к. он блокирует входящие пакеты. Убедиться в этом можно, пропинговав
машины в обе стороны.
Меня всегда интересовало, как выглядит сообщение при его отправке по
локальной сети командой net send. Но нельзя забывать о том, что эта
команда работает лишь при включенной службе Messenger. Попробуем
послать с виртуальной машины (Windows 2000) сообщение на хост машину
(Windows XP SP2) "This is my message!"...
Из данного лога видно все HTML-содержимое главной страницы
www.google.ru + содержимое *.gif файлов. Также мы видим ответы smtp- и
pop3-сервера.
Итог
Мы рассмотрели один из самых простых способов создания программ
перехвата входящего трафика. Полученные в результате прочтения данной
статьи знания можно использовать в различных целях, будь то
тестирование своих сетевых программ, наблюдение за кем-либо или просто
ради интереса. Теперь мы точно знаем, что Microsoft предоставляет
возможности для создания программ данного типа, хотя и с урезанными
привилегиями. Но в большинстве случаев этого бывает достаточно для
достижения поставленных целей.
Обнаружил url -адресов: http://srub-dizain.ru/proizvodstvo - изготовление во Владимире и мне захотелось построить садовый домик в селе! Мне как раз нужен был профилированный брус сухой. В общем после этого я и прыгнул на электричку! Там совсем всё качественно сделано и сухой брусок не трудно выбрать. Всему этому событию сопутствовала продуманная навигация ресурса, которую быстро обнаружил.Хорошо конечно то, что это производитель профилированного бруса – но сайт тяжёлый на восприятие.
Называется дожились! Вот в yahoo нарыл объявление http://rentrealtycrimea.com - сдам 1 квартиру в Симферополе и стал злым. Кстати забыл поздороваться! В общем сдам 2 комнатные квартиры в Симферополе ,я зачитал и до меня дошло, что настоящая жизнь только начинается – раз есть такие мастерские. Поэтому каждому рекомендую линк http://rentrealtycrimea.com с стильными квартирами на окраине Симферополя.