Будем использовать Zabbix для слежения за списком установленных служб/сервисов Windows.
Это важно по нескольким причинам:
- Вирусы часто устанавливают в системе новые службы, а это значит, что нужно следить за появлением новых служб.
- Бывает, что некоторые службы Windows , имеющие тип запуска auto или delayed-auto не работают, а это повод проверить их настройки.
Замечание 1.
Способ установки Python 2.7 описан тут: https://www.mihanik.net/tihaja-ustanovka-python-2-7/
Замечание 2.
Способ становки Zabbix-агента (клиента) описан тут: https://www.mihanik.net/ustanovka-zabbix-klienta/
1. Собираем данные по установленным программам при помощи скрипта.
Скрипт написан на Python 2.7, он собирает данные по установленным службам и формирует 3 файла:
-
- Полный список служб — ‘C:\Zabbix\scripts\soft_list\service_list.lst’
- Список недавно установленных/удалённых служб — ‘C:\Zabbix\scripts\soft_list\service_diff.lst’
- Список служб, с установленным способом запуска Auto или Delayed-auto, но не работающих — ‘C:\Zabbix\scripts\soft_list\service_stoped.lst’.
Нужно отметить, что некоторые автоматически запускаемые службы Windows могут прекращать работу. Для каких-то служб это нормально, поэтому, чтобы не поднимать панику раньше времени, скрипт использует файл со списком служб за которыми не нужно наблюдать — ‘C:\Zabbix\scripts\soft_list\NotMonitoredServices.txt’.
Сам скрипт сохранён под именем C:\Zabbix\scripts\soft_list\serviceslist.py.
Текст скрипта:
# -*- coding: utf-8 -*-
import os
import sys
import ctypes
import errno
import _winreg
import codecs
import wmi
#
# Функция проверки наличия прав администратора
# Вход: нет
# Выход: true - есть права администратора,
# false - нет прав администратора
#
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
#
# Функция удаления дубликатов из списка
# Вход: список
# Выход: список без дубликатов
#
def DuplicateRemoval ( InboundList ):
OutboundList = []
for i in InboundList:
if i not in OutboundList:
OutboundList.append(i)
return OutboundList
#
# Функция загрузки списка из файла
# Вход: путь к файлу со списком
# Выход: список
#
def ListLoad ( InboundFileName ):
OutboundList = []
# Если указанного файла не существует возвращаем пустой список
if not os.path.exists( InboundFileName ):
return OutboundList
if not os.path.isfile( InboundFileName ):
return OutboundList
# Читаем файл построчно
f = open( InboundFileName,'r')
try:
OutboundList = f.read().splitlines()
except Exception:
pass
finally:
f.close()
return OutboundList
#
# Функция сохранения списка в файл
# Вход: список, путь к файлу
# Выход: true - успешная запись, false - ошибка при записи
#
def ListSave ( OutboundList, OutboundFileName ):
# Записываем файл построчно
f = open( OutboundFileName,'w')
try:
for line in OutboundList:
f.write(line + '\n')
except Exception:
MyResult = False
else:
MyResult = True
finally:
f.close()
return MyResult
#
# Функция получения списка установленных служб Windows имеющих способ запуска auto или Delayed-auto, но не работающих
# Вход: нет
# Выход: список установленных служб Windows имеющих способ запуска auto или Delayed-auto, но не работающих
#
def StopedServicesList():
List = []
c = wmi.WMI ()
stopped_services = c.Win32_Service (StartMode="Auto", State="Stopped")
for Service in stopped_services:
List.append (Service.Name + ' - ' + Service.Caption + ' - ' + Service.State)
stopped_services = c.Win32_Service (StartMode="Delayed-auto", State="Stopped")
for Service in stopped_services:
List.append (Service.Name + ' - ' + Service.Caption + ' - ' + Service.State)
List.sort()
return List
#
# Функция получения списка всех установленных служб Windows
# Вход: нет
# Выход: список всех установленных служб Windows
#
def ServicesList():
List = []
c = wmi.WMI ()
Services = c.Win32_Service ()
for Service in Services:
List.append (Service.Name + ' - ' + Service.Caption)
List.sort()
return List
################################################################################
# Начало программы
################################################################################
def main(argv=None):
# Проверяем наличие прав админа.
if not is_admin ():
sys.exit ('Not enough permissions to run the script !!!')
# Устанавливаем кодировку по умолчанию.
reload(sys)
sys.setdefaultencoding('utf8')
# Зададим имена файлам, которые будем использовать
# Полный список служб
MyServicesListFile=r'C:\Zabbix\scripts\soft_list\service_list.lst'
# Список установленных/удалённых служб
MyServicesDiffFile=r'C:\Zabbix\scripts\soft_list\service_diff.lst'
# Список не работающих служб
MyServicesStopedFile=r'C:\Zabbix\scripts\soft_list\service_stoped.lst'
# Список не наблюдаемых служб
MyServicesNotMonitored=r'C:\Zabbix\scripts\soft_list\NotMonitoredServices.txt'
# Получаем список установленных служб Windows
List = ServicesList()
# Получаем прежний список из файла
OldList = ListLoad ( MyServicesListFile )
# Ищем установленные/удалённые службы Windows
DeletedList = []
InstalledList = []
# Получаем список свежеустановленных служб Windows
for i in List:
if i not in OldList:
InstalledList.append(i)
# Получаем список удалённых служб Windows
for i in OldList:
if i not in List:
DeletedList.append(i)
# Сохраняем список изменений в diff-файл построчно
f = open( MyServicesDiffFile,'w')
try:
f.write('Deleted:'+ '\n')
for line in DeletedList:
f.write(line + '\n')
f.write('\n')
f.write('Installed:'+ '\n')
for line in InstalledList:
f.write(line + '\n')
except Exception:
pass
finally:
f.close()
# Сохраняем текущий список установленных служб Windows в файл
if not ListSave (List, MyServicesListFile):
sys.exit ('Unable to save installed services list!!!')
# Сохраняем текущий список установленных служб Windows имеющих способ запуска auto, но не работающих в файл.
# Предварительно из этого списка уберём упоминание тех служб, за которыми не нужно следить.
List = StopedServicesList()
NotMonitored = ListLoad ( MyServicesNotMonitored )
for i in NotMonitored:
for ListItem in List:
if i in ListItem:
List.remove(ListItem)
if not ListSave (List, MyServicesStopedFile):
sys.exit ('Unable to save stoped services list!!!')
if __name__ == "__main__":
sys.exit(main())
2. Устанавливаем скрипт в системе.
Скрипт лучше запускать каждый час, — не слишком часто, но и не слишком редко.
Запланировать выполнение скрипта можно при помощи планировщика Windows. Задание планировщика можно создать вручную, а можно и при помощи bat-файла.
Я обычно это делаю при помощи «батника», имя своему батнику я дал INSTALL_get_services_list.bat .
Текст скрипта:
@echo off
Rem Предполагаем, что на Windows XP скрипт запускается администратором.
Rem Для более старших систем это неверно.
rem Получаем версию ОС
ver | find "5.1."
rem Windows XP ?
If %errorlevel%==0 (
rem Пропускаем проверку админских прав
GOTO SKIPADMIN
)
SET HasAdminRights=0
FOR /F %%i IN ('WHOAMI /PRIV /NH') DO (
IF "%%i"=="SeTakeOwnershipPrivilege" SET HasAdminRights=1
)
IF NOT %HasAdminRights%==1 (
ECHO .
ECHO Not enough permissions to run the script !!!
ECHO .
GOTO END
)
:SKIPADMIN
rem Получаем версию ОС
rem Windows XP ?
ver | find "5.1."
If %errorlevel%==0 (
rem Windows XP
SCHTASKS /Create /RU "NT AUTHORITY\SYSTEM" /SC HOURLY /ST 00:05:00 /TN "InstalledServices" /TR "python \"C:\zabbix\scripts\soft_list\serviceslist.py\""
) else (
rem НЕ Windows XP
SCHTASKS /Create /RU "NT AUTHORITY\SYSTEM" /SC DAILY /ST 00:05 /RI 60 /DU 24:00 /TN "InstalledServices" /TR "python \"C:\zabbix\scripts\soft_list\serviceslist.py\"" /RL HIGHEST /F
)
cd "C:\Zabbix\scripts\soft_list"
python "C:\zabbix\scripts\soft_list\serviceslist.py"
:END
EXIT /B
3. Формируем шаблон в Zabbix.
В Zabbix при этом добавляем несложный шаблон.
Сначала приведу описание шаблона в картинках.
Создаём шаблон с именем : Active Computer — Python — ServicesList…
Добавляем группу элементов данных…
Теперь добавляем 3 элемента данных…
И, наконец, пару несложныйх триггеров, которые будут срабатывать при изменении списка служб или при остановке какой-то службы…
А вот и готовый для импорта заархивированный файл с описанным выше шаблоном: zbx_export_templates_serviceslist.xml
Описанные ранее скрипты можно найти в этом архиве: soft_list
4. Сбор данных.
Осталось назначить созданный шаблон соответствующему узлу сети и ждать начала поступления данных. 🙂
Всё.
🙂