Проблема с отслеживанием "вечно"-работающего процесса (службы либо приложения) имеет много общего с проблемой скрытия от пользователя работающего процесса. Уже несколько раз подобные темы поднимались, но универсального решения не найдено до сих пор. Как правило, задача становиться неразрешимой уже на теоретическом уровне, при обдумывании действий "продвинутого" пользователя по обходу защиты. Всегда оказывается, что усилия администратора сводятся "на нет" при использовании пользователем неких утилит от "третьих" фирм.
Но в данном конкретном случае, имхо, есть надежда. Представляю на обсуждение свой вариант решения проблемы (не "готовенькое", впрочем; придется поработать руками и головой). Сразу хочу предупредить, что решение предполагает XP (нет у меня ничего другого под рукой) на машине администратора и NT/2k/XP на "подследственной" машине.
Итак, что я предлагаю? Сначала о том, как это выглядит "на словах". При старте Windows на машине А, за которой ведётся наблюдение, запускается некая служба сА. По условию задачи, мы должны предотвратить остановку данной службы, используя все методы, вплоть до выключения нарушителя. Наблюдение за работой сА на "подследственной" машине А ведётся с другой машины - Б; как нетрудно догадаться, это машина администратора. Использование в качестве "базы" администраторской машины позволит избежать затяжной войны с хитроумным пользователем, который наверняка быстро научится останавливать службу сА вместе со службами слежения сБ на локальной машине А. Если же он нагло полезет на машину Б через RPC (или "вживую", что ещё наглее), то получит по ручонкам от админа. Теперь остаётся решить вопрос, как мы будем следить за сА.
Одним из простых решений является периодические запросы с машины Б с целью получения списка исполняемых на машине А процессов. При отсутствии в полученном списке работающей службы сА можно идти за "скалкой"
![](http://fool.exler.ru/sm/nunu.gif)
. Периодичность мы можем обеспечить вызовом т.н. "запланированной задачи". Для этого будем использовать стандартный виндовый планировщик задач schtasks. Он является более мощной версией at и позволяет нам "не заморачиваться" насчёт периодического запуска каждый несколько минут. Кто хочет, может использовать приблуды типа crond и т.д. Я же делаю упор на стандартные стредства виндов. Итак, вызов проверяющего скрипта я предполагал организовать так:
c:\> schtasks /create /sc MINUTE /mo 10 /tr c:\temp\1.bat /tn Checker
Кому любопытно, может почитать о schtasks в стандартной виндовой "справке и поддержке", я же отмечу только, что имя запускаемого скрипта-"проверяющего" - c:\temp\1.bat, имя 10-минутной повторяющейся задачи для диспетчера назначенных задач - Checker. После ввода команды (из-под cmd.exe) необходимо указать пароль.
Первый подводный камень ждёт нас именно тут. Ни хрена у меня нее заработал этот диспетчер задач. То есть он работал, писал, что "усе у порядке", но ничего на самом деле не делал, а в лог c:\windows\SchedLgU.Txt писал странности типа:
"Checker.job" (1.bat) 06.05.2004 0:37:58 ** ОШИБКА **
Попытка использования учетной записи задания окончилась неудачей, поэтому задание выполнено не было. Специфическая ошибка: 0x8007052e:
Вход в систему не произведен: имя пользователя или пароль не опознаны. Проверьте правильность указания имени пользователя и пароля и повторите попытку.
Возможны, что называется, варианты. Всё вылечилось явным заданием атрибутов пользователя:
с:\> schtasks /create /sc MINUTE /mo 10 /tr c:\temp\1.bat /tn Checker /s \\имямашиныБ /u Администратор /p *п*а*р*о*л*ь*
Теперь давайте определимся, как же мы сможем отследить работу службы сА на машине А. Поскольку мы юзеры неопытные и на с++ не ваяем, попытаемся снова обойтись средствами виндов. В голову первым делом приходит слово "tasklist". Вообще-то мне сначала хотелось замутить всё на pslist от
www.sysinternals.com, но... всё должно быть "родное виндовое"! Изучаем help tasklist. Изучаем ключи. Решение потихоньку оформляется. Для нашей цели нужно использовать команду вроде
c:\> tasklist /s \\имямашиныА /svc /FI "службы eq сА" /FI "Состояние eq Работает"
То есть мы проверяем наличие в списке процессов машины А процесса, который использует службу сА и при этом работает. Мы можем усилить фильтр за счёт указания дополнительного атрибута - имени владельца процесса (SYSTEM). Но... Встречаем второй подводный камень.
Кривые руки локализаторов (то ли из USA M$, то ли наших родных) привели к некорректной работе такого миленького и удобного приложения. Догадаться, какие имена используются при задании фильтров мне удалось далеко не сразу. В конце концов выяснилось, что один из фильтров задать вообще никогда не удастся - при выводе состояние работы писалось по-русски, а проверялось по-английски. WTF?, сказал я, и достал волшебный рашпиль.
Берём программку, позволяющую редактировать ресурсы экзешников. Я пользуюсь (и Вам советую) ResHack. Откройте с её помощью файл c:\windows\system32\tasklist.exe. Найдите в строковых ресурсах строку String Table\15\1049\226 и замените значение "running|not responding" на "Работает|not responding". Это исправит корявость фильтра. Теперь сохраним (после Compile Script) программу обратно, но под другим именем (правила хорошего тона обязывают), например как tasklist2.exe. Теперь для проверки скомандуйте
c:\> tasklist2 /V /FI "Пользователь eq NT AUTHORITY\SYSTEM" /FI "Состояние eq Работает"
Должна отобразится куча служб. Для сравнения:
c:\> tasklist /V /FI "Пользователь eq NT AUTHORITY\SYSTEM" /FI "Состояние eq running"
Пусто. Удивлены? Я - нет. Ну ладно, пора сращивать...
Ориентировочно, проверка наличия службы выглядит так (файл-батник c:\temp\1.bat):
Код:
![Выделить весь код](images/misc/selectcode.png)
c:\windows\system32\tasklist2.exe /svc /FI "службы eq сА" /FI "Состояние eq Работает" /FI "Пользователь eq NT AUTHORITY\SYSTEM"
if errorlevel 1 goto killthemall else goto exithere
:killthemall
> c:\temp\log.txt echo Этот гад остановил службу. Мочи козлов!!!
start c:\temp\log.txt
:exithere
Но тут мы нарываемся ещё на несколько плюх.
Во-первых, батник выполняется из-под cmd.exe, а текст мы пишем в ноутпаде. У кого как, а у меня сразу возникли неприятности с кодировкой. Введенный текст превратился "под досом" в нечитабельные крякозябли, приведя tasklist2.exe в дикий восторг. Я-то быстро решил проблему (у меня под рукой куча всяких recode, hiew и т.д.), а вот кому-то приётся попотеть. В качестве одного из вариантов могу предложить M$Word. Он умеет писать\читать DOS-текст.
Второй трабл в том, что запущенное из-под schtasks приложение не может интерактивно взаимодействовать с рабочим столом. Вообще-то данную проблему решить можно (например, с помощью psexec и т.п.), но меня заломало и я вывернулся просто: запуск ноутпада через start log.txt убираем, зато вставляем net send самому себе. Выглядит это гораздо веселее и дает возможность Админу закрыть сообщение.
Итак...
Вот что должно быть записано в проверяющем скрипте c:\temp\1.bat:
Код:
![Выделить весь код](images/misc/selectcode.png)
c:\windows\system32\tasklist2.exe /svc /FI "б«г¦Ўл eq xxxxxxxx" /FI "‘®бв®п*ЁҐ eq ђ Ў®в Ґв" /FI "Џ®«м§®ў ⥫м eq NT AUTHORITY\SYSTEM"
if errorlevel 1 (goto killthemall) else goto exithere
:killthemall
> c:\temp\log.txt echo Служба xxxxxxxx была отключена при последней проверке в
>> c:\temp\log.txt time /t
net send имямашиныБ ќв®в Ј ¤ ®бв *®ўЁ« б«г¦Ўг. Њ®зЁ Є®§«®ў!!!
:exithere
Вместо xxxxxxxx следует записать имя Вашей службы. Крякозябли оставьте, как есть (так и задумано). Теперь запустите задачку в расписании, как описано выше...
Подумал, и решил дать виндовый "перевод", а то вдруг в посте ещё что-нибудь переврётся...
c:\windows\system32\tasklist2.exe /svc /FI "службы eq xxxxxxxx" /FI "Состояние eq Работает" /FI "Пользователь eq NT AUTHORITY\SYSTEM"
if errorlevel 1 (goto killthemall) else goto exithere
:killthemall
> c:\temp\log.txt echo ‘«г¦Ў xxxxxxxx Ўл« ®вЄ«озҐ* ЇаЁ Ї®б«Ґ¤*Ґ© Їа®ўҐаЄҐ ў
>> c:\temp\log.txt time /t
net send имямашиныБ Этот гад остановил службу. Мочи козлов!!!
:exithere
Некоторые заключителные замечания.
1) После появления сообщения об отключенной службе не забудьте сказать
c:\> schtasks /delete /tn Checker
а то Вас будет продолжать засыпать мессагами. Можно добавить удаление задания в батник проверки, но я ещё не придумал, как сказать "йес" на запрос об удалении задания.
2) По поводу выключения злостного юзера - к нашим услугам множество программ типа shutdown.exe, psexec и т.д. Запихнём их в "следящий" батник и "дело в шляпе".
3) При необходимости следить за несколькими машинами можно делать их перебор через FOR, либо просто описать все проверки для каждой "подследственной" машины отдельно.
Специально для
vippy (если он сюда заглянет):
Данный механизм можно (по идее) использовать для обнаружения и перезапуска зависших программ на локальной машине. Нужно только через ResHack переименовать и "non responding" во что-то более вразумительное на русском (не знаю точно во что, руки не дошли, посмотрите tasklists /v и т.п.). Вопрос только в том, будет ли зависшее приложение при нулевой активности пользователя помечено как неотвечающее.
По поводу безопасности: вообще-то ожидаются некоторые неприянтности. Поскольку мы захотим запускать задачи "одной кнопкой", возникает искушение прописать пароль администратора внутрь батников. Лучше этого не делать, а набивать его вручную. Например, в случае с schtasks, указание /p без собственно пароля должно приостановить создание задачи, спросить в консоли пароль администратора, а затем собственно создать процесс. С tasklists тоже могут возникнуть осложнения, првда в моем случае всё было ok.
PS. Кульным хаЦкерам: При использовании материала с целью получения баблоса не забудьте указать источник:
www.forum.oszone.ru (ну и про меня не забывайте
![Rotate](images/smilies/rotate.gif)
)
PPS. Вопросы наверняка возникнут, особенно у неискушенных пользователей. Спрашивайте здесь, Вам кто-нибудь ответит непременно. Только совсем уж бестолковых вопросов не надо, ладно? А к профессионалам просьба - если заметите ошибки в рассуждениях или в синтаксисе, не поленитесь указать на них, плз.
[s]Исправлено:
hasherfrog, 9:24 6-05-2004[/s]