AVZ 5. Руководство пользователя
×

16.51.15. Сканирование ПК и отправка результатов по FTP

Данный пример может быть полезен системным администраторам, желающим автоматически просканировать большое количество компьютеров и собрать протоколы исследования и карантины не опознанных AVZ или заподозренных в чем-то файлов для углубленного изучения.
 
var
 // Список хостов мониторинга, на которые посылаются статусы
 MonitoringHost : string;
 // Параметры подключения к FTP серверу
 FFtpServer, FFtpLogin, FFtpPasswd, FFtpPath : string;
 FTPPassiveMode : boolean;
 // Признак необходимости создать и отправить карантин
 isCreateQr : boolean;
 // Настройки задержки
 RandomDelay, RDTimer : integer;
 
// Запрос параметра командной строки по имени
function GetCmdLineParam(AParam, ADefVal : string) : string;
begin
 Result := GetParamByName(AParam);
 if Result = '' then
  Result := ADefVal;
end;
 
// Отправка событий смены статуса в SYSLOG
procedure SendStatusInfo(S : string);
var
 Tmp : string;
begin
 if MonitoringHost = '' then
  exit;
 // Перебор заданных в настройке хостов SYSLOG
 Tmp := MonitoringHost+';';
 while pos(';', Tmp) > 0 do begin
  SendSysLogMessage(Trim(copy(Tmp, 1, pos(';', Tmp)-1)),  
                    '['+DateTimeToStr(now)+'] '+
                    GetComputerName + '='+ S);
  delete(Tmp, 1, pos(';', Tmp));
 end;
end;
 
// Загрузка настроек из командной строки
function LoadSetup : boolean;
begin
 Result := false;
 // Параметры подключения к FTP
 FFtpServer := GetCmdLineParam('FtpServer', '--');
 FFtpLogin  := GetCmdLineParam('FtpLogin','--');
 FFtpPasswd := GetCmdLineParam('FtpPasswd','--');
 FFtpPath   := GetCmdLineParam('FtpPath','/');
 FTPPassiveMode := UpperCase(GetCmdLineParam('FtpPassiveMode','Y'))='Y';
 // Мониторинг SYSLOG (допускает использование нескольких хостов через разделитель ;)
 MonitoringHost := GetCmdLineParam('MonHost', '');
 MonitoringHost := StringReplace(MonitoringHost, ';;', ';');
 // Выключение создания карантина создания карантина
 isCreateQr := true;
 if UpperCase(GetCmdLineParam('NoCreateQR','N'))='Y' then
  isCreateQr := false;
 // Случайная задержка перед отправкой карантина
 RandomDelay := StrToInt(GetCmdLineParam('StartRandomDelay','0'));
 if (RandomDelay < 0) then
  RandomDelay := 0;
 if (RandomDelay > 1000) then
  RandomDelay := 1000;
 // Проверка наличия обязательных параметров
 Result := (FFtpServer<>'--') and
           (FFtpLogin<>'--') and
           (FFtpPasswd<>'--');
end;
 
// Отправка локального файла AFileName под именем ASaveName
function FSendFile(AFileName, ASaveName : string) : boolean;
begin
 Result := FTPSendFile(AFileName, FFtpServer, FFtpPath,
                       ASaveName,
                       FTPPassiveMode,
                       FFtpLogin, FFtpPasswd);
end;
 
 // ***************** Основной скрипт *************************
var
 WorkPath  : string;            // Рабочая папка в каталоге TEMP
 LogTimeStamp : string;         // Отметка времени для вставки в имя файла
 WinVersion, WinBuild : string; // Данные о версии Windows
begin
 // Определение версии ОС на случай использования в скрипте
 WinVersion := Trim(RegKeyStrParamRead('HKEY_LOCAL_MACHINE',
               'SOFTWARE\Microsoft\Windows NT\CurrentVersion',
               'CurrentVersion'));
 WinBuild   := Trim(RegKeyStrParamRead('HKEY_LOCAL_MACHINE',
               'SOFTWARE\Microsoft\Windows NT\CurrentVersion',
               'CurrentBuildNumber'));
 // Загрузка настроек, при неуспешности прерывание работы скрипта                                                                                                        
 if not(LoadSetup) then begin
  ExitAVZ;
  exit;             
 end;
 // Создание рабочего каталога
 WorkPath := NormalDir('%Tmp%\AVZ_TEMP\');
 CreateDirectory(WorkPath);
 // Формирование отметки времени для уникальности имен лога и карантина
 LogTimeStamp := FormatDateTime('YYYYMMDDHHNNSS', Now);
 // Карантин размещать в папке Temp ПК (важно в случае запуска AVZ из сетевой папки)
 SetupAVZ('QuarantineBaseFolder='+WorkPath);
 // Полная очистка карантинов
 ClearQuarantineEx(true);
 // Включение фильтра - в качестве примера исключим карантин документов и журналов
 AddQuarantineFilter('*.docx');
 AddQuarantineFilter('*.xlsx');
 
 // ********* Настройка AVZ *********
 SetupAVZ('UseQuarantine=Y');    // Включить карантин подозрительных
 SetupAVZ('Priority=-1');        // Пониженный приоритет
 SetupAVZ('EvLevel=3');          // Эвристика на максимум
 SetupAVZ('ExtEvCheck=Y');       // Расширенный анализ включен
 SetupAVZ('HiddenMode=3');       // GUI блокирован
 SetupAVZ('KeyloggerSearch=N');  // Антикейлоггер блокирован
 SetupAVZ('SaveIPToLog=Y');      // Запись IP адреса ПК в протокол
 //SetupAVZ('QrOnlyEXE=Y');      // Карантин только исполняемых файлов - по необходимости
 
 // Заголовка для неких кастомизированных настроек, зависящих от версии Windows
 if WinVersion = '6.2' then begin
  // Некие настройки для заданной версии Windows
 end;
 // Настройки для x64 систем
 if IsWow64 then begin
   SetupAVZ('AntiRootKitSystemKernel=N');
 end;
 
 // Активирование сторожевого таймера на 45 минут
 ActivateWatchDog(60 * 45);
  
 SendStatusInfo('Начало работы');
 // Запуск сканирования (предварительно снимаем перехваты UserMode)
 SearchRootkit(true, false);
 RunScan;
 if isCreateQr then begin
  SendStatusInfo('Карантин файлов');
  // Автокарантин
  ExecuteAutoQuarantine;
  // При необходимости принудительный карантин неких файлов по заданным критериям
  //QuarantineFileF('%PF%', '*.exe,*.dll', true, 'PF-QR', 1000, 1000000);
  // Создание архива с карантином
  CreateQurantineArchive(WorkPath + 'avz_qr.zip');
 end;
 
 // Выполнение исследования системы
 SendStatusInfo('Исследование системы');
 ExecuteSysCheckEX(WorkPath + 'avz_log.htm', $FFFFFFFF, true, 1+4+8+16+64);
 
 // Отправка архива с карантином на сервер
 SendStatusInfo('Отправка протокола');
 FSendFile(WorkPath + 'avz_log.zip', GetComputerName+'_'+LogTimeStamp+'_log.zip');
 if isCreateQr then begin
  if RandomDelay > 0 then begin
   RDTimer := Trunc(Random * RandomDelay);
   SendStatusInfo('Задержка отправки карантина на '+IntToStr(RDTimer)+' сек.');
   Sleep(RDTimer);
  end;
  SendStatusInfo('Отправка карантина');
  FSendFile(WorkPath + 'avz_qr.zip', GetComputerName+'_'+LogTimeStamp+'_qr.zip');
 end;
 
 // Очистка карантина и архива с ним (после отправки они не нужны)
 ClearQuarantineEx(true);
 // Чистка следов AVZ
 ExecuteStdScr(6);
 SendStatusInfo('Процесс завершен');
 // Выход из AVZ
 ExitAVZ;
end.
 
 
 
Рассмотрим сначала функции, определенные в скрипте для выделения логически завершенных операций, выполняемых в ходе работы:
  • GetCmdLineParam - данная функция расширяет возможности стандартной GetParamByName и позволяет при отсутствии параметра вернуть значение по умолчанию.
  • SendStatusInfo - отправляет информацию о смене статуса на один или несколько серверов SYSLOG. Данную функцию несложно переписать и реализовать некий иной алгоритм отправки информационных событий.
  • LoadSetup - выполняет загрузку и верификацию настроек. В данном примере функция загружает настройки из параметров командной строки. Для ряда параметров применяются значения по умолчанию, в частности, по умолчанию применяется пассивный режим FTP, а файлы копируются в корневую папку сервера.
  • FSendFile - выполняет отправку файла. Изменив реализацию данной функции можно реализовать некий иной механизм отправки, например, по электронной почте или через сетевые шары.
 
Логика самого скрипта достаточно простая, и сводится к следующим шагам:
1. Путем чтения параметров реестра с помощью функции RegKeyStrParamRead заполняются переменные WinVersion и WinBuild, содержащие сведения о версии операционной системы. Непосредственно для решения поставленной задачи они не нужны, но их наличие позволяет при необходимости реализовать некую логику настройки, зависящую от версии ОС.
2. При помощи созданной нами функции LoadSetup выполняется загрузка настроек и их верификация. Если настройки не позволяют продолжать исследование системы, процесс прерывается. Важно отметить, что для этого применяется пара функций: ExitAVZ и exit. Первая из них отправляет AVZ указание на то, что при первой возможности необходимо прекратить работу, но она не гарантирует немедленную остановку скрипта на следующей команде, что отличает ее от exit, которая решает обратную задачу - прерывает работу скрипта, но не обеспечивает завершение процесса работы AVZ. Их совместное использование дает гарантию того, что процесс прекратит работу и скрипт не будет выполняться далее.
3. В переменной WorkPath формируется полный путь к папке, применяемой для хранения карантинов и временных файлов. Алгоритм ее формирования может быть любым, в текущей реализации папка размещается в каталоге TEMP. При помощи параметра QuarantineBaseFolder эта папка указывается как базовая для карантинов всех типов. Подобная настройка не обязательна, но очень важна в случае, если AVZ запускается с сетевого диска - если не сделать такую настройку, карантины разных пользователей смещаются друг с другом, или будет сбой по причине нехватки прав для записи на сетевой диск.
4. При помощи ClearQuarantineEx выполняется очистка карантина. Данный шаг необходим на случай, если предыдущий запуск был неуспешен и в карантине что-то осталось.
5. При помощи AddQuarantineFilter выполняется настройка фильтра карантина. Эта операция не обязательна, но при применении в корпоративных сетях может быть полезна для исключения карантина каких либо определенных файлов. В данном примере показано, как исключить попадание в карантин файлов с расширение *.docx и *.xlsx.
6. Настройка AVZ перед сканированием и исследованием ПК. Выполняется при помощи SetupAVZ, причем в качеств примера показаны как общие настройки, так и выполняемые для заданной версии операционной системы или только для x64 версий ОС. Стоит отметить, что один и тот же параметр может меняться SetupAVZ многократно, и используется только последнее значение. Это позволяет сделать общую настройку, а затем скорректировать ее в условных блоках.
7.  При помощи ActivateWatchDog настраивается сторожевой таймер, который прервет работу AVZ через 45 минут.
8. Выполняется поиск перехватчиков при помощи SearchRootkit, после чего идет сканирование путем запуска RunScan. Диски для проверки в настройках не заданы, и это сделано умышленно - сигнатурный поиск AVZ против современных malware не эффективен, и основная цель RunScan - изучение запущенных процессов, а также выполнение многочисленных эвристических проверок системы.
9. Если в настройках указана необходимость сборка карантина (режим по умолчанию), то переменная isCreateQr будет равна true и будет выполнен автоматический карантин при помощи вызова ExecuteAutoQuarantine. Закомментированный вызов QuarantineFileF является заготовкой для карантина файлов по заданным критериям. Подобная операция может быть для карантина файлов по неким критериям, определенным администратором. Аналогично может применяться вызов QuarantineFile - для карантина конкретных файлов. После карантина путем вызова CreateQurantineArchive создается архив с стандартным паролем virus.
10. Выполняется исследование системы путем вызова ExecuteSysCheckEX.
11. Выполняется отправка архивов с карантином и протоколами исследования по FTP. В качестве примера перед отправкой карантина может быть выдержана случайная задержка на время от нуля до заданного количества секунд. Эта задержка не обязательна, и полезна в случае массового одновременно запуска исследования на большом количестве ПК - в этом случае исследование системы завершится в примерно одно время, и все ПК попытаются одновременно отправить файлы, перегрузив FTP сервер и сеть. Случайная задержка на 10-20 минут существенно ослабляет данный эффект. Отправляемые файлы имеют уникальные имена, содержащие имя компьютера, отметку времени и суффикс _log для протокола и _qr для карантина.
12. При помощи ClearQuarantineEx выполняется очистка карантина, чтобы в папке TEMP не оставался мусор.
13. На всякий случай вызывается ExecuteStdScr(6) - стандартный скрипт №6, удаляющий следы драйверов AVZ из системы. Он не обязателен.
14. Завершается работа скрипта
 
В ключевых точках скрипта при помощи декларированной в начале скрипта SendStatusInfo производится отправка информации, позволяющей отслеживать и протоколировать ход процесса.
 
Пример командной строки для запуска данного скрипта (предполагается, что он хранится в папке AVZ, имя файла scan.txt):
 
avz5.exe script=scan.txt FtpServer=192.168.0.2 FtpLogin=avz FtpPasswd=avz MonHost=192.168.0.2
В этом случае предполагается, что FTP сервер имеет адрес 192.168.0.2, на него же по протоколу SYSLOG ведется отправка событий.
 
Пример режима без сбора и передачи карантинов:
avz5.exe script=scan.txt FtpServer=192.168.0.2 FtpLogin=avz FtpPasswd=avz MonHost=192.168.0.2 NoCreateQR=Y
 
Данный скрипт достаточно универсален, и путем незначительных доработок может быть адаптирован под конкретные задач.