Каков признак того, что компьютер инфицирован червем? Надо проверить, какие компьютеры чаще других отправляют ARP-пакеты.

Черви/вирусы/шпионские программы нередко пытаются соединиться со случайно выбранным компьютером локальной сети. Когда компьютер впервые пытается связаться с локальным IP-адресом, он отправляет ARP-пакет для выяснения Ethernet (МАС) — адреса. Нормальные (не-инфицированные) компьютеры обычно общаются лишь с несколькими компьютерами: с серверами, которые им нужны, и с их локальным маршрутизатором. Если обнаружится, что какой-то компьютер отправляет значительно больше ARP-пакетов, чем остальные, скорее всего, это можно считать признаком его заражения.

Построим простой канал в оболочке, который будет собирать следующие 100 ARP-пакетов в сети и определять, какой хост сгенерировал больше пакетов, чем другие хосты того же уровня. Что-то вроде конкурса «Кто пошлет больше пакетов». В прошлую такую проверку я обнаружил, что червями заражены два из пятидесяти компьютеров сети.

Команды, приведенные ниже, должны работать в любой системе UNIX/Linux или другой UNIX-подобной системе. Вам понадобится команда tcpdump и доступ с правами root. Команда which tcpdump сообщит вам, установлена ли команда tcpdump в вашей системе. Проверка пакетов в сети имеет этические аспекты. Выполняйте ее, только если у вас есть разрешение.

Вот команда, получившаяся у меня в итоге (прошу прощения за испорченный сюрприз):

$ sudo tcpdump — l -n агр | grep 'агр who-has' | \

head -100 | awk '{ print $NF }' |sort | uniq — с | sort — n

Она такая длинная, что не помещается в одной строке этой книги, поэтому я разбил ее на две строки, а символом переноса служит обратный слэш. Вам не нужно набирать обратный слэш при вводе команды.[7] Не следует и нажимать клавишу Enter в этом месте.

Вывод команды выглядит так:

tcpdump: verbose output suppressed, use — v or — vv for full protocol decode listening on en0, link-type EN10MB (Ethernet), capture size 96 bytes

 1 192.168.1.104

 2 192.168.1.231

 5 192.168.1.251

 7 192.168.1.11

 7 192.168.1.148

 7 192.168.1.230

 8 192.168.1.254

11 192.168.1.56

21 192.168.1.91

30 192.168.1.111

101 packets captured

3079 packets received by filter

0 packets dropped by kernel

Не обращайте внимание на две первые и три последние строки. В остальных строках указано количество пакетов и IP-адрес. Этот эксперимент показал, что хост 192.168.1.111 отправил 30 ARP-пакетов, а хост 192.168.104 — только один пакет. Большинство машин редко отправляли пакеты за исследуемый период, но два хоста отправили в 4–6 раз больше пакетов, чем остальные. Это свидетельствовало о проблеме. Быстрое сканирование антивирусной программой — и оба хоста стали как новенькие.

А теперь расскажу, как я строил эту командную строку. Я начал с команды:

$ sudo tcpdump — l -n arp

Здесь sudo означает, что следующая команда должна быть выполнена с правами пользователя root. Весьма вероятно, что она запросит пароль. Если в вашей среде нет sudo, вы можете воспользоваться аналогичной командой или выполнить эту последовательность от имени пользователя root.[8] Будьте внимательны. Человеку свойственно ошибаться, но настоящий храбрец не боится работать от имени root.

Команда tcpdump прослушивает Ethernet. Флаг -1 нужен, если мы собираемся направить вывод другой программе. Дело в том, что, в отличие от других команд, tcpdump выполняет буферизацию выходных данных для ускорения работы. Однако при направлении вывода в канал нам это не нужно. Флаг — n отключает поиск в DNS для каждого найденного IP-адреса. Параметр arр означает, что команда tcpdump должна отслеживать только ARP-пакеты.

(Если вас беспокоит этическая сторона вопроса, то должен сообщить вам хорошую новость. Если вы отфильтруете все, кроме ARP-пакетов, то на выходе будет очень мало частной информации.)

Выполните эту команду на своем компьютере. Вообще, если вы будете проверять на практике все, о чем здесь прочитаете, вы многому научитесь. Эта команда не удаляет никакие данные. Но должен вас предупредить, что отслеживание пакетов может быть незаконным. Делайте это, только если у вас есть соответствующее разрешение.

Когда я запускаю эту команду, вывод выглядит так:

$ sudo tcpdump — n -l агр

tcpdump: verbose output suppressed, use — v or — vv for full protocol decode listening on en0, link-type EN10MB (Ethernet), capture size 96 bytes

19:10:48,212755 arp who-has 192.168.1.110 (85:70:48:a0:00:10) tell 192.168.1.10

19:10:48,743185 arp who-has 192.168.1.96 tell 192.168.1.92

19:10:48,743189 arp reply 192.168.1.2 is-at 00:0e:e7:7a:b2:24 19:10:48.

743198 arp who-has 192.168.1.96 tell 192.168.1.111

^C

Чтобы прекратить вывод, я нажимаю клавиши CtrL–C Иначе он будет продолжаться вечно.

Если вы получили сообщение об ошибке доступа, скорее всего, вы запустили команду не как суперпользователь. Команда tcpdump может быть выполнена только пользователем root. Вы ведь не хотите, чтобы вашу сеть прослушивал кто попало, правда?

После заголовка идут строки вида «arp who-has X tell Y». Здесь Y — это хост, который задал вопрос. Вопрос имел примерно такое содержание: «Уважаемый хост с IP-адресом Х, не сообщите ли вы свой Ethernet (МАС) — адрес?» Вопрос отправляется широковещательным пакетом, поэтому мы видим все ARP-запросы в нашей локальной сети. Однако мы видим не так уж много ответов, поскольку они отправляются в виде однонаправленных пакетов, а мы находимся на концентраторе. В данном случае виден только один ответ, потому что мы находимся на одном концентраторе с тем компьютером (а, может, это компьютер, выполняющий команду, — этого я вам не скажу). Тем не менее, все хорошо; ведь нам нужны только те, кто задает вопросы.

Итак, у вас есть источник информации. Преобразуем ее так, чтобы ею можно было воспользоваться.

Во-первых, изолируем те строки вывода, которые нас интересуют. В данном случае это строки, содержащие «arp who-has»:

$ sudo tcpdump — l -n arp | egrep 'arp who-has'

Мы можем запустить эту команду и убедиться, что она ведет себя, как ожидалось. Единственная проблема в том, что команда работает безостановочно, пока мы не нажмем CtrL–C. Мы хотим получить достаточное количество строк и затем обработать их. Ограничимся первой сотней строк:

$ sudo tcpdump — l -n arp | grep 'arp who-has' | head -100

Снова запустим команду и убедимся, что все хорошо. Во время тестирования этой команды у меня не хватило терпения, и я изменил 100 на 10.

Это дало мне уверенность, что команда работает правильно, и в окончательном варианте я поставил 100. Вы, конечно, заметите в выводе кучу заголовков. Они направляются в поток stderr (прямо на экран) и не передаются в команду gгер.

Итак, у нас есть сто строк с интересующими нас данными. Настало время статистических подсчетов. Какие хосты генерируют больше всего ARP-пакетов? Нам нужно выделить IP-адреса всех хостов, сгенерировавших ARP-пакет, и как-то подсчитать их количество. Начнем с выделения IP-адресов. Это шестое поле каждой строки, и мы можем воспользоваться следующей командой:

awk '{ print $6 }'

Этот маленький фрагмент кода awk является прекрасной идиомой для выделения конкретного поля из каждой строки текста.

Должен сознаться, что мне было лень подсчитывать, в каком поле находятся данные, которые я хотел выделить. Было похоже, что это пятое поле, и я сначала пробовал указать $5. Не сработало, тогда я указал $6. Конечно! Мне следовало помнить, что в awk поля нумеруются с единицы, а не с нуля. Преимущество тестирования командной строки на каждом шаге в том и заключается, что мы достаточно рано обнаруживаем такие мелкие ошибки. Представьте, что было бы, если бы я написал всю командную строку сразу, а затем стал бы искать эту ошибку!