Снифер на C#
В этом переводе будет показано как создать простой снифер, с парсингом IP, TCP, UDP и DNS пакетов на c#. Без использования сторонних библиотек типа SharpCap.
Для захвата пакетов, мы используем raw(сырой) сокет и привязываем его к IP-адресу. После установки некоторых параметров для сокета, вызываем метод IOControl. Обратите внимание, что IOControl аналогичен методу Winsock2WSAIoctl. IOControlCode.ReceiveAll означает, что захватываться будут абсолютно все пакеты как входящие так и исходящие.
Второй параметр, передаваемый в IOControl с IOControlCode.ReceiveAll должен содержать именно такое значение массива byTrue (спасибо Леониду Молочному за это). Далее мы начинаем получать все пакеты асинхронно.
Анализ пакетов
IP датаграммы инкапсулируются TCP и UDP пакетами. Они также содержатся в данных, передаваемыъ по протоколам прикладного уровня, таких как DNS, HTTP, FTP, SMTP, SIP и т.д. Таким образом, пакет TCP содержит в себе дейтаграммы IP, например:
Итак, первое, что мы должны сделать, это проанализировать IP-заголовок. Для этого создан урезанный класс classIPHeader. Комментарии описывают что и как происходит.
Класс содержит элементы данных, соответствующих полям заголовка IP. Ознакомтесь с RFC 791 для подробного изучения IP заголовка и его полей. Конструктор класса берет полученные байты и создает MemoryStream для полученной информации. Затем создает BinaryReader, чтобы считать данные байт за байтом из MemoryStream. Также отметим, что данные, полученные от сети, находятся в форме с обратным порядком байтов, в связи с этим мы используем IPAddress. NetworkToHostOrder, чтобы исправить порядок байтов. Это должно быть сделано для всех элементов данных.
Пишем простой сниффер под 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. Естественно, пожинать его лавры цель не стоит — нас интересует задача перехвата трафика методом обычного «прослушивания» сетевого интерфейса. Важно понимать, что мы не собираемся заниматься взломом и перехватывать чужой трафик. Нужно всего лишь просматривать и анализировать трафик, который проходит через наш хост.
Как так? Очень просто.
Ключевым шагом в превращении простого сетевого приложения в сетевой анализатор является переключение сетевого интерфейса в режим прослушивания (promiscuous mode), что и позволит ему получать пакеты, адресованные другим интерфейсам в сети. Этот режим заставляют сетевую плату принимать все кадры, вне зависимости от того, кому они адресованы в сети. [2]
Начиная с Windows 2000 (NT 5.0) создать программу для прослушивания сегмента сети стало очень просто, т.к. ее сетевой драйвер позволяет перевести сокет в режим приёма всех пакетов.
Включение неразборчивого режима
Наша программа оперирует IP-пакетами, и использует библиотеку Windows Sockets версии 2.2 и «сырые» сокеты (raw sockets). Для того чтобы получить прямой доступ к IP-пакету, сокет нужно создавать следующим образом:
Создание сырого сокета
Здесь вместо константы SOCK_STREAM (протокол TCP) или SOCK_DGRAM (протокол UDP), мы используем значение SOCK_RAW. Вообще говоря, работа с raw sockets интересна не только с точки зрения захвата трафика. Фактически, мы получаем полный контроль за формированием пакета. Вернее, формируем его вручную, что позволяет, например, послать специфический ICMP-пакет…
Идем дальше. Известно, что IP-пакет состоит из заголовка, служебной информации и, собственно, данных. Советую заглянуть сюда, чтобы освежит знания. Опишем в виде структуры IP-заголовок (спасибо отличной статье на RSDN [3]):
Описание структуры IP-пакета
Главная функция алгоритма прослушивания будет выглядеть следующим образом:
Функция захвата одного пакета
Здесь все просто: получаем порцию данных с помощью стандартной функции socket-функции recv, а затем копируем их в структуру типа IPHeader.
И, наконец, запускаем бесконечный цикл захвата пакетов:
Захватым все пакеты, которые попадут на наш сетевой интерфейс
Немного оффтопика
Здесь и далее у некоторых важных функций и переменных автор сделал префкис RS_ (от Raw Sockets). Проект делал 3-4 года назад, и была шальная мысль написать полноценную библиотеку для работы с сырыми сокетами. Как это часто бывает, после получения сколь-нибудь значимых(для автора) результатов, энтузиазм угас, и дальше учебного примера дело не полшло.
В принципе, можно пойти дальше, и описать заголовки всех последующих протоколов, находящихся выше. Для этого необходимо анализировать поле protocol в структуре IPHeader. Посмотрите на пример кода (да, там должен быть switch, чёрт возьми!), где происходит раскрашивание заголовка в зависимости от того, какой протокол имеет пакет, инкапсулированный в IP:
Однако это существенно выходит за рамки этой статьи. Для нашего учебного примера вполне достаточно будет посмотреть ip-адреса хостов, с которых и на которые идет трафик, и посчитать его количество в единицу времени(готовая программа в архиве в конце статьи).
Для того, чтобы отобразить данные IP-заголовка, необходимо реализовать функцию преобразования заголовка (но не данных) дейтаграммы в строку. В качестве примера реализации, можно предложить такой вариант:
Преобразование IP-заголовка в строку
На основании приведенных выше базовых сведений, получается вот такая небольшая программа (жуткое название ss, сокр. от англ. simple sniffer), реализующая локальное прослушивание IP-трафика. Интерфейс ее приведен ниже на рисунке.
Исходный и бинарный код предоставляю как есть, таким как он был несколько лет назад. Сейчас мне на него страшно смотреть, и все же, он вполне читабельный (конечно же, нельзя быть таким самоуверенным). Для компиляции будет достаточно даже Visual Studio Express 2005.
upd: По совету Weageoo, выложил на гитхаб.
HTTP сниффер на C#
Есть немного погуглить, то становится ясно, что простого пути для создания собственного анализатора HTTP (не путать с TCP, который на уровень ниже того что надо было мне) нет. Простой и понятный код в свободном доступе отсутствует. Я постоянно напарывался на программы, которые мега разработчики хотят толкать за бабло. Ну есть нет бесплатно, то придется реверсить…
Почему TCP снифер не то что снифер для HTTP?
TCP это уровень ниже, чтобы получить полный пакет HTTP, еще предстоит огромное количество работы: определить заголовки, отфильтровать пакеты и выстроить их в цепочку. Это рутинный геморрой, на который бесплатно и сразу согласится разве что школьник.
Реверсим готовое
Так как я уже (к сожалению) не школьник, будем искать готовое. Жадины программисты, часто забывают скрыть код от посторонних глаз, пренебрегая даже банальной обфускацией. Большое вам на этом спасибо. И так, с такими инструментами как Reflector и плагином File Disassembler, программа превращается (конечно не превращается, а экспортируется) в код.
Что говорит код программы?
Есть много функционала с ключевым словом Persistent, а пространство имен — Perst… Вбиваем в поисковик, (да я настолько ленив, что даже код разбираю вместе с гуглом ? ) и получаем интересный результат. Это свободная, одно-файловая база данных с индексами и ключами.
Приятно узнавать новое, раньше я считал, что SQLite это единственный свободный выход для хранения массива данных в Windows формах на C#.
Пробиваем дальше… Вбиваем код в поисковик дальше:
public SocketPair(Socket socket, byte[] buffer)
Вот это да, ссылка на CodePRoject HSSniffer, именно того функционала, который я на мог найти с самого начала. Совпадение? Наверно, в виду того, что программа под реверсингом была опубликована до HSSniffer.
Еще один факт подтвердился, даже самая хорошая статья не будет давать заходов с поисковиков, если название не совсем соответствует тому, что хотели увидеть посетители.
В качестве заключения
Название первой программы я не расскажу, на это есть причины. Зато, могу рассказать, зачем я все это искал.
Уже давно делал программу YouTube View, может кто-то слышал. Сейчас эта программа уже не поддерживается и валяется на сайте в открытом коде. Так вот, естественно я просмотрел несколько программ, которые делают тоже самое. Прощупал рынок, так сказать и напоролся на одну интересную фишку. Одна из программ показывала значек в трее, для закачки ролика, не зависимо от того, какой браузер использовался. Смею предположить, что это сделано с помощью сканирования пакетов таким-же образом как это делает сниффер. Теперь, в своих программах я (и конечно вы) могу использовать ту-же фишку.
Снифер своими руками: отслеживание входящего трафика
Что мы будем делать
Пишем простой снифер
Начнем с того, что нам нужно написать снифер, который можно будет настраивать. Сделаем фильтр по протоколу, т.е. не будем пропускать в лог пакеты, не относящиеся к интересующему нас протоколу. Также реализуем возможности записи в лог IP получателя (наш), IP отправителя, имени протокола и длины пакета. В нашей программе, помимо этого, можно будет задавать имя файла лога. Он будет храниться в той же директории, что и наш
снифер. После всего, что мы сделаем, окно нашей программы будет выглядеть так:
Теперь перейдем к рассмотрению кода. Полный исходник нашей программы и ее рабочий вариант можно скачать по ссылке в конце статьи. Напишем программу на Visual C++ 6.0. Выбор этой среды разработки обоснован тем, что она мне по душе.
Начинаем, естественно, с инициализации сокетов. Пусть это будет WinSock 2.2:
WSADATA wsadata;
WSAStartup(MAKEWORD(2, 2), &wsadata);
Затем создаем сам сокет:
SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
Получаем имя нашего локального хоста и информацию о нем:
CHAR szHostName[16];
gethostname(szHostName, sizeof szHostName);
HOSTENT *phe = gethostbyname(szHostName);
SOCKADDR_IN sa;
ZeroMemory(&sa, sizeof sa);
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = ((struct in_addr*)phe->h_addr_list[0])->s_addr;
Теперь необходимо привязать локальный адрес к нашему сокету:
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.
Заметим, что режим 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.
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 следующим образом:
BOOL bOptVal = TRUE;
setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&bOptVal, sizeof(BOOL));
Но, поэкспериментировав с этим, я не пришел к положительному результату, т.е. по-прежнему нам требуются привилегии администратора.
Итак, режим promiscuous включен. Как же нам получить входящие IP пакеты? Очевидно, нужно постоянно вызывать функцию recv (в нашем случае) или WSARecv. Но создавать отдельный поток и делать бесконечный цикл было бы не очень удобно. Гораздо лучше для нас использовать асинхронные сокеты. Тем более, что у нас GUI-программа. Впишем следующий вызов функции WSAAsyncSelect в обработчик кнопки «Start» (эта кнопка не будет доступна, пока promiscuous mode не включен):
case IDC_BUTTON_START:
CHAR szFileName[_MAX_FNAME];
GetDlgItemText(hwndDlg, IDC_EDIT_LOG_FILENAME, szFileName, _MAX_FNAME);
hLogFile = CreateFile(szFileName, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, 0);
if (hLogFile == INVALID_HANDLE_VALUE) <
//.
> else <
//.
SetFilePointer(hLogFile, 0, NULL, FILE_END);
//Связываем событие FD_READ с окном
WSAAsyncSelect(s, hwndDlg, WM_RECV, FD_READ);
Здесь мы указываем функции, что окну с хендлом 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 iph_length >> 8);
// Записываем данные
WriteFile(hLogFile, «—Packet begin—\r\n», 18, &dwWritten, 0);
if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_OPTION_LOG_TARGET_IP) == TRUE) <
IN_ADDR ia;
ia.s_addr = hdr->iph_dest;
CHAR *pszTargetIP = inet_ntoa(ia);
WriteFile(hLogFile, «To: «, 4, &dwWritten, 0);
WriteFile(hLogFile, pszTargetIP, lstrlen(pszTargetIP), &dwWritten, 0);
WriteFile(hLogFile, «\r\n», 2, &dwWritten, 0);
>
if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_OPTION_LOG_SENDER_IP) == TRUE) <
IN_ADDR ia;
ia.s_addr = hdr->iph_src;
CHAR *pszSourceIP = inet_ntoa(ia);
WriteFile(hLogFile, «From: «, 6, &dwWritten, 0);
WriteFile(hLogFile, pszSourceIP, lstrlen(pszSourceIP), &dwWritten, 0);
WriteFile(hLogFile, «\r\n», 2, &dwWritten, 0);
>
if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_OPTION_WRITE_PROTO_NAME) == TRUE) <
WriteFile(hLogFile, «Protocol: «, 10, &dwWritten, 0);
switch (hdr->iph_protocol) <
case IPPROTO_IP:
WriteFile(hLogFile, «IP\r\n», 4, &dwWritten, 0);
break;
case IPPROTO_ICMP:
WriteFile(hLogFile, «ICMP\r\n», 6, &dwWritten, 0);
break;
case IPPROTO_IGMP:
WriteFile(hLogFile, «IGMP\r\n», 6, &dwWritten, 0);
break;
case IPPROTO_GGP:
WriteFile(hLogFile, «GGP\r\n», 5, &dwWritten, 0);
break;
case IPPROTO_TCP:
WriteFile(hLogFile, «TCP\r\n», 5, &dwWritten, 0);
break;
case IPPROTO_PUP:
WriteFile(hLogFile, «PUP\r\n», 5, &dwWritten, 0);
break;
case IPPROTO_UDP:
WriteFile(hLogFile, «UDP\r\n», 5, &dwWritten, 0);
break;
case IPPROTO_IDP:
WriteFile(hLogFile, «IDP\r\n», 5, &dwWritten, 0);
break;
case IPPROTO_IPV6:
WriteFile(hLogFile, «IPv6\r\n», 6, &dwWritten, 0);
break;
case IPPROTO_ND:
WriteFile(hLogFile, «ND\r\n», 4, &dwWritten, 0);
break;
case IPPROTO_ICLFXBM:
WriteFile(hLogFile, «ICLFXBM\r\n», 9, &dwWritten, 0);
break;
case IPPROTO_ICMPV6:
WriteFile(hLogFile, «ICMPv6\r\n», 8, &dwWritten, 0);
break;
>
>
if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_OPTION_WRITE_PACKET_LEN) == TRUE) <
CHAR szTemp[17];
WriteFile(hLogFile, «Packet length: «, 15, &dwWritten, 0);
wsprintf(szTemp, «%d\r\n», size);
WriteFile(hLogFile, szTemp, lstrlen(szTemp), &dwWritten, 0);
>
SetDlgItemInt(hwndDlg, IDC_EDIT_LOG_SIZE, GetFileSize(hLogFile, NULL), FALSE);
>
>
return TRUE;
Здесь, помимо приема пакета, у нас реализован фильтр по протоколу. Нам не составило бы труда реализовать и фильтр по размеру пакета, по 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!».
. и посмотрим в созданные нашим снифером логи:
Среди прочего мусора, мы видим, что сообщение прибыло в 3-ем пакете. А в 4-ом оно, видимо, завершилось.
Теперь попробуем вариант с Internet’ом. Зайдем на сайт www.google.ru и проверим почтовый ящик, находящийся на pop.mail.ru:
Из данного лога видно все HTML-содержимое главной страницы www.google.ru + содержимое *.gif файлов. Также мы видим ответы smtp- и pop3-сервера.
Мы рассмотрели один из самых простых способов создания программ перехвата входящего трафика. Полученные в результате прочтения данной статьи знания можно использовать в различных целях, будь то тестирование своих сетевых программ, наблюдение за кем-либо или просто ради интереса. Теперь мы точно знаем, что Microsoft предоставляет возможности для создания программ данного типа, хотя и с урезанными привилегиями. Но в большинстве случаев этого бывает достаточно для достижения поставленных целей.
Создаем Свой Sniffer/FireWall/Parental control/ SpyWare/Клиент для компьютерного Клуба. Технология LSP
Создаем Свой Sniffer/FireWall/Parental control/ SpyWare/Клиент для компьютерного Клуба. Технология LSP
Provider).
Недавно один знакомый выявил желание что ему для Электронного зала (библиотеки) нужна программа которая будет контролировать доступ к компьютерам и считать автоматически кто чего и почем.
Так как денег в бюджете за 2012 год не оказалось, знакомый дал отбой. Но идеей контроля доступа уже зажегся. Начал думать, как это можно сделать.
Больше всего меня беспокоил один вопрос. Как блокировать HTTP трафик если пользователь платит только за аренду компьютера, а не за аренду компьютера с интернетом?
На просторах интернета нашел интереснейшую статью о LSP и вот представляю ее перевод с некоторыми изменениями.
Кому интересно прошу под кат.
HTTP сниффер на базе LSP (Layered Service Provider)
Эта статья описывает, как создать простейший снифер для мониторинга HTTP трафика на ОС Windows. Эта программа основана на открытой технологии предоставленной Microsoft, имя ей — LSP (Layered Service Provider).
Эта технология используется различным ПО. В основном это Антивирусы, Фаерволлы и программы фильтрации трафика.
Для того чтобы создать этот пакет программ я использовал пример из Microsoft Platform SDK (Program Files\Microsoft Platform SDK\Samples\NetDS\WinSock\LSP\) и добавил дополнительную возможность для фильтрации HTTP трафика и сбора результатов в отдельное хранилище.
Концепция
Базовая Схема
Мы начинаем
Выводы и советы
Полезные Ссылки.
Концепция.
Главная идея LSP это создание провайдера который будет включен в цепочку существующих провайдеров. Чем то напоминает принцип Хуков в Windows.
LSP в действии.
Базовая Схема
Так выглядит базовая схема программного пакета.
После установки программного пакета, многие программы будут использовать наш провайдер (вообще наш провайдер это простой DLL файл, который загружается в каждое приложение которое использует библиотеку Winsock). Но нам нужно только определять HTTP трафик. Ниже представлена строка кода (нашего провайдера) с жестко привязанным портом, который и будет мониториться (HTTP протокол по умолчанию использует 80 порт ).
Вы можете улучшить этот инструмент, и сделать более элегантную логику программы для сохранения своих настроек, а не жестко определенных констант как в примере.
Кроме того мы должны определить HTTP запросы. Запросы HTTP GET определяются простым сравнением со строкой “GET”. Определение запросов POST можно осуществить тем же путем.
Также у нас имеется Служба, которая собирает всю информацию которая фильтруется – служба была создана для того чтобы предотвратить повреждения данных, она может произойти если мы будем следить за несколькими приложениями, а не за одним. Все перехваченная информация из браузера будет передаваться этой службе. Эта служба представляет из себя Socket сервер (слушает на 4004 порту) так что никаких проблем с синхронизацией сбора данных не должно быть. В данном случае Хранилище данных это просто текстовый файл, но можно с легкостью заменить на более удобный и стабильный вариант (например использовать СУБД ).
Мы начинаем
Тестовый Пакет содержит следующие проекты.
1.Проект LSP (папка LSP)
Этот проект содержит перегрузку основных методов Winsock. Именно в этом месте, мы должны добавить свои изменения. В моем случае, этот проект содержит пример из Platform SDK, где я и добавил логику для определения соединения к 80-му порту и пометил его как перехватываемым в методе Connect:
Таким образом, при будущих вызовах метода Send, мы обнаружим, что этот socket используется HTTP протоколом. Также мы установили соединение с Службой сбора трафика в методе Connect. В методе SEND, мы реализовали логику обнаружения запросов HTTP и перенаправления их на нашу службу(Service):
Я создал специализированный класс который держит одно постоянное соединение для каждого загруженного DLL файла.
Его роль сохранять Socket подключенным. Таким образом, только одно соединение установлено с службой хранилища.
2.Проект Common (папка Common)- этот проект содержит все утилиты предоставленные в примерах Platform SDK. И также были сделаны некоторые манипуляции с GUID от нашего LSP провайдера.
Проект Installer (папка Installer ) – это установщик LSP. Мы поменяли его главный метод – убрали парсинг командной строки и добавили поиск TCP провайдера. Теперь во время установки мы ищем ID TCP провайдера и перестраиваем цепочку провайдеров. Мы поместили наш провайдер поверх TCP.
3.Проект Service (папка Service )– это сборщик трафика. Он представляет из себя простейшую службу Windows и методы установки и удаления службы. В функции MAIN нашей службы также реализован Socket сервер. Вся логика манипуляции со службой любезно позаимствована из MSDN. Сервер принимает все входящие подключения и запускает на каждое приложение отдельный поток. Запущенный поток принимает данные разделенные последовательною «\r\n\r\n» (по сути 2 пустые строки) и сохраняет их в хранилище.
Для того чтобы начать работать с этим проектом вам понадобиться собрать весь проект Visual studio. После этого положите NSI скрипт в папку результата сборки и скомпилируете Nsi скрипт. У нас получиться установочный setup.exe файл
Во время установки setup.exe, все необходимые файлы будут распакованы в свои рабочие папки. LSP.DLL будет помещен в %SYSTEMROOT%\\system32\\LSP.dll. Служба и установщик провайдера будет помещен в папку Program Files. Также ярлык деинсталляции будет размещен на рабочий стол. Файл истории будет находиться в корне C://.
Выводы и советы.
В этой статье описывается, как создать свой собственный провайдер и мониторить весь сетевой трафик. Но это не единственный пример для использования данной технологии. Вы также можете легко реализовать логику для:
Блокирования HTTP запросов и ответов;
Изменять и удалять трафик;
Блокировать соединения (как это делает Firewall);
Перехватывать SLL зашифрованные данные (даже возможно сделать MITM перехват) (Man in the midle)
В разработке LSP было много граблей, чтобы не сожалеть, что интернет соединение было потеряно и были сбой, лучше для тестов использовать Виртуальную машину. Гораздо удобнее откатить образ ВМ на предыдущее состояние чем использовать каждый раз систему восстановления Windows.
Большая часть антивирусного ПО тоже использует данную технологию, так что вы можете найти их в цепочке установленных LSP провайдеров в вашей ОС. Также антивирусы могут стать для вас проблемой при тестирование своего LSP провайдера, потому что антивирусы тоже фильтруют трафик.
Вы можете добавить логику для игнорирования выбранных вами приложений. Чтобы Наш LSP-провайдер ничего не делал кроме передачи данных если приложение в списке игнорируемых.
Этот инструмент был разработан только для 32-битных приложений. Но оно может быть легко портировано на 64-разрядных приложений. Вы просто должны пересобрать проект в 64-битный и выставить флаг LspCatalog64Only во время установки провайдера.
Чтобы увидеть изменения в примере Platform SDK, которые были сделаны для создания этого инструмента, вы можете сравнить текст с оригинальным примером.
Также я отметил все блоки кода, которые были добавлены комментарием //ADDED
Также обратите внимание, что вы должны сгенерировать новый GUID для вашего LSP-провайдера, чтобы избежать коллизий с другими LSP-провайдерами.
Полезные ссылки
К сожалению ссылок не так много, но они все же есть.
1.MSDN и документация Platform SDK.
Сам проект выложен ТУТ
Также проект выложен на ГИТХАБ