pingscan
- исполняемый файл программы в zip архиве.
Ссылки к статье
MSDN - масса справочной
информации по используемым функциям. Поиск по сайту рекомендую осуществлять
через гугл строкой вида site:msdn.microsoft.com _ключевое_слово_
Многопоточный ICMP сканер (pingscan)
Поддерживаемая платформа: Windows.
Однажды мне потребовался простой ICMP сканер сегментов, имеющий адекватную
скорость сканирования, простой интерфейс и возможность работы в Windows от
имени непривелигерованного пользователя. Различные утилиты, найденные в сети,
обычно, обладали как минимум одним из перечисленных недостатков: низкая
скорости сканирования сегмента; необходимость запуска с правами администратора;
сложный интерфейс. В связи с этим (а так же с целью удовлетворения праздного
любопытства - "как это работает?"), была написана простенькая, но достаточно
эффективная программа pingscan, обладающая возможностью
сканирования сегментов задаваемых сетевой маской в CIDR нотации и возможностью
тестирования сети при помощи ICMP флуда для отдельно взятого хоста.
Описание режимов работы программы
pingscan работает в 2х режимах использующих два разных подхода для
создания потока ICMP сообщений:
Режим сканирования диапазона адресов. В этом случае производится динамическая
загрузка функций для работы с ICMP протоколом из icmp.dll (системная
DLL Windows) -
методика применяется при сканировании диапазона адресов заданых сетевой маской.
Высокая скорость сканирования достигается за счёт создания пула потоков (до 64х
одновременно) в каждом из которых производся опрос отдельного хоста.
Режим флуда. В этом случае используется низкоуровневая сборка пакетов ICMP
сообщений и отправка/получение их при помощи RAW сокетов. Отправка
и получение ICMP сообщений производятся в разных потоках. Работа в
этом режиме возможна только с правами администратора системы.
Параметры и ключи программы
Формат командной строки для запуска программы:
IP-address - любой IP адрес входящий в сканируемую подсеть. netmask - длина маски сканируемой подсети. Если не указано -
используется значение 24 бита. Список ключей принимаемых программой:
Примеры использования программы
Режим сканирования.
Сканирование с параметрами по умолчанию, в качестве цели использован один из
адресов хоста mail.ru:
***часть вывода программы пропущена***
При использовании значений параметров заданных по умолчанию, программа получает
адрес подсети из переданного ей IP адреса хоста используя значение маски равное
24м битам (в данном случае - 194.67.57.0/24), таким образом сканируется 256 IP
адресов включая получаемый адрес сети и широковещательный адрес - ведь
фактическая длина маски удалённой подсети не известна и по этим адресам так же
могут находиться хосты. Как видно из вывода программы - для начальныых хостов
подсети (по значению IP адреса) имеются записи в обратной зоне DNS. Для
последних хостов этих записей нет, потому информация о них выводится без
доменных имён. Замечу что на обратное разрешение имён тратится значительное
время, особенно в случае отсутствия записи для хоста в обратной зоне, потому
суммарное время сканирования данной подсети равно примерно 6ти секундам. При
использовании ключа '-n' обратное преобразование имён отключается
и время сканирования указаной подсети сокращается примерно до 2х секунд.
Возможно вам бросился в глаза не упорядоченный по IP адресу вывод информации о
полученных от хостов ответах. Например сперва выведена информация о хосте
194.67.57.3, потом о 194.67.57.21 а за ним - 194.67.57.6 и т.д. Это объясняется
тем что программа не производит внутреннего упорядочивания полученных данных и
выводит информацию об ответах хостов в режиме реального времени.
Теперь пример сканирования с указанием того же адреса и дополнительными
параметрами:
В данном примере указана длина сетевой маски равной 30ти битам (CIDR нотация),
отключено обратное преобразование доменных имён, задано отправлять до 3х
пакетов к каждому хосту в случае его не ответа, задан таймаут ответа в 2
секунды и установлен размер пакета равный 5000 байт. Как можно заметить -
результат выполнения программы изменился. Например увеличилось время получения
ответа, а хосты с адресами 194.67.57.226, 194.67.57.227 и вовсе не ответили на
запросы. Если задать размер пакета равным например 1000 байт, то эти хосты
ответят. Судя по всему фаерволл блокирует ответы на фрагментированные ICMP
запросы.
Примечание: программа не принимает в качестве параметра имя хоста, т.к.
доменное имя может разрешаться сразу в несколько IP адресов. Порядок выдачи
этих адресов DNS сервером является случайным. Таким образом при сканировании
сегмента заданного доменным именем получается сканирование случайного сегмента.
Что как мне кажется - лишено смысла.
Режим ICMP флуда. Внимание! Использование ICMP флуда требует разумного подхода! В
противном случае не исключена блокировка вас со стороны администратора сети,
провайдера и т.д. Крайне не рекомендуется запускать флуд в интернет.
Как уже указывалось выше - запустить флуд можно только с правами администратора
системы. Тестирование одного из хостов локальной сети:
Как мне кажется - вывод программы достаточно очевиден что бы его дополнительно
пояснять. Можно обратить внимание на передаваемые параметры: маска обязательно
должна быть указана равной 32м битам. В случае использования бесконечного флуда
(до прерывания по Ctrl+C) значение ключа '-c' нужно задать равным
нулю:
Символы "^C" в последней строке вывода обозначают что программа
завершена по клавиатурному прерыванию через Ctrl+C.
Используемые системные функции
Ниже приведён список системных функций используемых в программе.
Функции для работы с ICMP протоколом (производится динамическая загрузка DLL):
IcmpCreateFile - открывает хэндл для выполнения ICMP запросов.
IcmpSendEcho - выполняет отправку ICMP-echo и завершается либо при
получении ответа, либо по заданному таймауту.
IcmpCloseHandle - закрывает хэндл созданный при помощи IcmpCreateFile
Функции создания и завершения потоков:
_beginthreadex() - создаёт дочерний поток выполнения. Используется как
в режиме сканирования, так и в режиме флуда для создания дочернего
потока-приёмника ICMP сообщений.
_endthreadex()
- завершение дочернего потока. Вызывается внутри завершающегося потока.
TerminateThread() - принудительное завершение порождённого потока.
Обычно (и в данном случае) выполняется из породившего потока. Используется в
режиме флуда для завершения потока-приёмника
Функции для синхронизации потоков:
WaitForMultipleObjects() - производит блокировку вызвавшего потока до
перехода указанного числа объектов в сигнальное состояние. Используется в
режиме сканирования.
WaitForSingleObject()
- производит блокировку вызвавшего потока до перехода указанного (одного)
объекта в сигнальное состояние. Используется в режиме флуда для ожидания
завершения потока - передатчика ICMP сообщений.
func.c,
func.h - функции для работы с icmp.dll, исполняемая
функция дочерних потоков (one_ping()), а так же вспомогательные
фунции.
raw_ping.c,
raw_ping.h
- функции использующие RAW сокеты для отправки и получения ICMP
сообщений. Используются в режиме флуда.
Сборка производилась в "Eclipse Platform Version: 3.3.2" + компилятор
gcc, но т.к. в программе используется практически чистый WinAPI + стандартный
Си - сборка не должна составить проблем с использованием любой другой IDE и
компилятора.
Все возникшие пожелания и предложения можно (или даже нужно) сообщить в
гостевую или на и статья будет скорректированна, если это будет уместно.