Создаем Свой 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.
Во время инсталяции провайдера, вы можете указать место в цепочке провайдеров. И цепочка будет перестроена согласно новым настройкам. В нашем случае провайдер устанавливается поверх [TCP/IP] провайдера. Будьте осторожны во время установки на реальную машину. Если при установки будет сбой, это добавит много проблем – потеря сети, интернета и сбоя некоторых сетевых приложений.
Для того чтобы обойти проблемы отладки и создания провайдера LSP тестируйте его на Виртуальной машине.
В LSP провайдере, вы должны заместить все методы библиотеки winsock. Вообще то в примере Platform SDK уже включена логика замещения, остается только добавить логику перехвата, блокировки УРЛа либо сохранения HTTP трафика.
LSP используют как легальные программы, так и SpyWare/AdWare.
Например:
Легальные программы:
- Sygate Firewall
- Mcafee Personal Firewall
- E-Safe
- Dr.Web Security Space 6 использует LSP в качестве модуля Родительского контроля.
AdWare:
- Webhancer
- New.net
- NewDotNet
LSP в действии.
Базовая Схема
Так выглядит базовая схема программного пакета.
После установки программного пакета, многие программы будут использовать наш провайдер (вообще наш провайдер это простой DLL файл, который загружается в каждое приложение которое использует библиотеку Winsock). Но нам нужно только определять HTTP трафик. Ниже представлена строка кода (нашего провайдера) с жестко привязанным портом, который и будет мониториться (HTTP протокол по умолчанию использует 80 порт ).
if((namelen >= sizeof(sockaddr_in)) && (((sockaddr_in*)name)->sin_port == htons(HTTPPort)))
{
SocketContext->intercept = TRUE;
}
Вы можете улучшить этот инструмент, и сделать более элегантную логику программы для сохранения своих настроек, а не жестко определенных констант как в примере.
Кроме того мы должны определить HTTP запросы. Запросы HTTP GET определяются простым сравнением со строкой “GET”. Определение запросов POST можно осуществить тем же путем.
Также у нас имеется Служба, которая собирает всю информацию которая фильтруется – служба была создана для того чтобы предотвратить повреждения данных, она может произойти если мы будем следить за несколькими приложениями, а не за одним. Все перехваченная информация из браузера будет передаваться этой службе. Эта служба представляет из себя Socket сервер (слушает на 4004 порту) так что никаких проблем с синхронизацией сбора данных не должно быть. В данном случае Хранилище данных это просто текстовый файл, но можно с легкостью заменить на более удобный и стабильный вариант (например использовать СУБД ).
Мы начинаем
Тестовый Пакет содержит следующие проекты.
1.Проект LSP (папка LSP)
Этот проект содержит перегрузку основных методов Winsock. Именно в этом месте, мы должны добавить свои изменения. В моем случае, этот проект содержит пример из Platform SDK, где я и добавил логику для определения соединения к 80-му порту и пометил его как перехватываемым в методе Connect:
if((namelen >= sizeof(sockaddr_in)) && (((sockaddr_in*)name)->sin_port == htons(HTTPPort)))
{
SocketContext->intercept = TRUE;
}
Таким образом, при будущих вызовах метода Send, мы обнаружим, что этот socket используется HTTP протоколом. Также мы установили соединение с Службой сбора трафика в методе Connect. В методе SEND, мы реализовали логику обнаружения запросов HTTP и перенаправления их на нашу службу(Service):
if (IsHTTPRequest(lpBuffers->buf) && SocketContext->intercept)
{
SetBlockingProvider(SocketContext->Provider);
ret = SocketContext->Provider->NextProcTable.lpWSPSend(
serviceConnection.GetSocket(),
lpBuffers,
dwBufferCount,
lpNumberOfBytesSent,
dwFlags,
lpOverlapped,
lpCompletionRoutine,
lpThreadId,
lpErrno
);
SetBlockingProvider(NULL);
}
Я создал специализированный класс который держит одно постоянное соединение для каждого загруженного DLL файла.
class ServiceConnectionKeeper;
Его роль сохранять Socket подключенным. Таким образом, только одно соединение установлено с службой хранилища.
2.Проект Common (папка Common)- этот проект содержит все утилиты предоставленные в примерах Platform SDK. И также были сделаны некоторые манипуляции с GUID от нашего LSP провайдера.
Проект Installer (папка Installer ) – это установщик LSP. Мы поменяли его главный метод – убрали парсинг командной строки и добавили поиск TCP провайдера. Теперь во время установки мы ищем ID TCP провайдера и перестраиваем цепочку провайдеров. Мы поместили наш провайдер поверх TCP.
if (IsHTTPRequest(lpBuffers->buf) && SocketContext->intercept)
{
SetBlockingProvider(SocketContext->Provider);
ret = SocketContext->Provider->NextProcTable.lpWSPSend(
serviceConnection.GetSocket(),
lpBuffers,
dwBufferCount,
lpNumberOfBytesSent,
dwFlags,
lpOverlapped,
lpCompletionRoutine,
lpThreadId,
lpErrno
);
SetBlockingProvider(NULL);
}
3.Проект Service (папка Service )– это сборщик трафика. Он представляет из себя простейшую службу Windows и методы установки и удаления службы. В функции MAIN нашей службы также реализован Socket сервер. Вся логика манипуляции со службой любезно позаимствована из MSDN. Сервер принимает все входящие подключения и запускает на каждое приложение отдельный поток. Запущенный поток принимает данные разделенные последовательною "\r\n\r\n" (по сути 2 пустые строки) и сохраняет их в хранилище.
do
{
result = recv(clientSocket, buffer, PACKSIZE, 0);
if (result > 0)
{
response += std::string(buffer, result);
do
{
position = response.find(messageTerminator);
if (std::string::npos != position)
{
if (!CollectorServer::Instance()->SaveData(std::string(response.begin(), response.begin() + position)))
{
return -1;
}
response = response.substr(position + messageTerminator.size());
}
} while (std::string::npos != position);
}
else
{
break;
}
} while (SOCKET_ERROR != result);
Для того чтобы начать работать с этим проектом вам понадобиться собрать весь проект 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-провайдерами.
Полезные ссылки
К сожалению ссылок не так много, но они все же есть.
0. Оригинал статьи на английском
1.MSDN и документация Platform SDK.
2. Также есть информация на вебсайте LSP разработчиков.
Сам проект выложен ТУТ
Также проект выложен на ГИТХАБ