Как безопасно тестировать подозрительные .ps1-скрипты в PowerShell

Представьте ситуацию: вы получили PowerShell-скрипт от коллеги, скачали его из внутреннего репозитория или нашли в архиве старого проекта. Запускать как есть страшно — а вдруг там что-то удаляет, шифрует или отправляет данные наружу. Удалять жалко — скрипт может быть полезным. Что делать?

В этой статье разберёмся, как запустить подозрительный .ps1-файл так, чтобы он не навредил системе, но при этом вы могли понять, что он реально делает. Без теории про песочницы в общем — только конкретные инструменты и подходы, которые работают.

Почему просто «открыть и посмотреть» — плохая идея

Многие думают: открою скрипт в блокноте, прочитаю, пойму, безопасно ли. На практике это работает только с простыми скриптами на 20–30 строк. Реальные скрипты часто содержат:

  • динамическую загрузку модулей и удалённых ресурсов;
  • обфускацию — намеренное запутывание кода;
  • условные ветки, которые активируются только в определённой среде;
  • вызовы через Invoke-Expression, где команда собирается из строки в рантайме.

То есть даже если вы прочитаете каждую строку, вы можете не увидеть реального поведения. Скрипт может проверять, запущен ли он на реальной машине, и вести себя по-разному в разных условиях.

Что значит «безопасный режим» для PowerShell

Под безопасным режимом здесь понимаем не один конкретный переключатель, а комбинацию ограничений, которые не дают скрипту сделать что-то необратимое. У нас есть несколько уровней защиты, и их можно накладывать последовательно.

Уровень 1: Execution Policy

Это первый и самый базовый барьер. Execution Policy определяет, какие скрипты вообще разрешено запускать. Для тестирования подозрительного кода оптимально выставить:

Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned

Это означает: локальные скрипты можно запускать, но скачанные из интернета должны быть подписаны. Политика действует только в текущем процессе PowerShell, так что на систему в целом вы не влияете.

Если хотите совсем перестраховаться:

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Restricted

Тогда скрипты не запустятся вообще — но вы сможете изучить их содержимое и выполнить команды вручную, копируя по одной.

Уровень 2: Constrained Language Mode

Это уже серьёзнее. Constrained Language Mode ограничивает доступ к .NET-классам, COM-объектам и API, которые часто используются в вредоносных скриптах. Включить можно так:

$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"

В этом режиме скрипт не сможет обратиться к большинству системных функций напрямую. Если скрипт при этом падает с ошибкой — это сигнал: он пытался сделать что-то, что выходит за рамки базовой функциональности PowerShell.

Уровень 3: AppLocker или Windows Defender Application Control

Если у вас корпоративная среда или вы хотите максимальной изоляции, можно настроить AppLocker так, чтобы скрипты из определённой папки запускались с ограничениями. Это уже настройка на уровне системы, но для регулярного тестирования имеет смысл один раз настроить и использовать.

Практический сценарий: шаг за шагом

Вот как я обычно поступаю, когда нужно понять, что делает незнакомый скрипт.

  1. Скачиваю или копирую файл в изолированную папку. Например, C:\ScriptAnalysis\. Никаких путей к реальным рабочим данным.
  2. Открываю файл в редакторе и бегло просматриваю. Ищу явные красные флаги: Invoke-Expression, DownloadString, Net.WebClient, обращения к HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run (автозапуск), команды шифрования, удаление теневых копий через vssadmin.
  3. Запускаю PowerShell с минимальными привилегиями. Не от администратора. Это само по себе закрывает половину потенциально опасных операций.
  4. Устанавливаю Execution Policy для процесса и включаю Constrained Language Mode.
  5. Запускаю скрипт и смотрю, что происходит. Если он падает — анализирую ошибки. Если работает — проверяю, какие файлы были созданы, какие сетевые соединения открыты.
  6. Использую Process Monitor от Sysinternals. Запускаю ProcMon перед выполнением скрипта и фильтрую по имени процесса. Так видно каждый обращение к файловой системе и реестру.

Инструменты для анализа

Инструмент Что делает Когда использовать
Process Monitor (ProcMon) Показывает файловые операции, обращения к реестру, сетевую активность в реальном времени Когда нужно увидеть реальное поведение скрипта
PowerShell Transcript Записывает весь ввод и вывод сессии в лог-файл Для последующего анализа того, что произошло
PSScriptAnalyzer Статический анализ кода: находит подозрительные паттерны и потенциальные проблемы Перед запуском, чтобы быстро оценить код
Sandboxie / Windows Sandbox Полная изоляция на уровне ОС Когда скрипт выглядит совсем подозрительно и вы не хотите рисковать основной системой
Virtual Machine Максимальная изоляция: можно сделать снапшот и откатить Для скриптов, которые могут что-то сломать безвозвратно

Как включить логирование всего, что делает PowerShell

Это важный момент, который многие пропускают. Если вы не включили логирование заранее, вы не сможете потом восстановить, что именно выполнил скрипт.

Включите Script Block Logging — он записывает каждый выполненный блок кода, даже обфусцированный:

# Включить логирование скрипт-блоков
Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 1

И включите Module Logging для записи вызовов командлетов:

Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ModuleLogging" -Name "EnableModuleLogging" -Value 1
Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ModuleLogging\ModuleNames" -Name "*" -Value "*"

После этого всё будет записываться в журнал событий Windows, раздел «Microsoft-Windows-PowerShell/Operational». Можно будет вернуться и посмотреть каждый шаг.

Что выбрать в зависимости от ситуации

Ситуация 1: скрипт от коллеги, которому вы доверяете, но хотите перестраховаться.

Достаточно Constrained Language Mode + запуск без прав администратора + ProcMon для наблюдения. Быстро, без настройки виртуальных машин.

Ситуация 2: скрипт из неизвестного источника, скачан из интернета.

Запускайте в Windows Sandbox или виртуальной машине. Сделайте снапшот перед запуском. Включите все виды логирования. Не подключайте общие папки к хостовой системе.

Ситуация 3: нужно понять логику сложного скрипта без запуска.

Используйте PSScriptAnalyzer для статического анализа. Разбивайте скрипт на блоки и выполняйте по частям в интерактивной консоли. Комментируйте подозрительные строки и смотрите, как меняется поведение.

Ситуация 4: скрипт явно вредоносный, нужно понять механизм для защиты.

Только виртуальная машина без сетевого доступа. Никаких общих буферов обмена с хостом. После анализа — полный сброс к снапшоту.

Частые ошибки при тестировании

Вот что регулярно делают неправильно — и к чему это приводит.

  • Запуск от администратора «чтобы точно сработало». Это снимает половину защиты. Если скрипт вредоносный, у него будут полные права на систему. Запускайте от обычного пользователя — если скрипту нужны повышенные привилегии, он сам упадёт, и вы это увидите.
  • Тестирование на рабочей машине без резервной копии. Даже если вы уверены, что скрипт безопасен, сделайте точку восстановления или хотя бы скопируйте важные файлы. Быстрая осторожность лучше, чем час восстановления данных.
  • Отключение Execution Policy глобально. Некоторые руководства советуют Set-ExecutionPolicy Unrestricted без указания scope. Это меняет настройку для всей системы. Всегда используйте -Scope Process — тогда изменение исчезнет при закрытии окна.
  • Игнорирование сетевой активности. Скрипт может выглядеть безобидным, но при этом отправлять данные на внешний сервер. Проверяйте сетевые соединения во время выполнения через netstat или ProcMon.
  • Запуск скрипта в одной сессии с рабочими процессами. Откройте отдельное окно PowerShell специально для тестирования. Не смешивайте с текущей работой.

Практические рекомендации

Если вы регулярно имеете дело с незнакомыми скриптами, настройте себе рабочий процесс один раз:

  1. Создайте отдельную учётную запись на компьютере без прав администратора — используйте её для тестирования.
  2. Настройте Windows Sandbox — он встроен в Pro-версии Windows 10/11 и включается через «Компоненты Windows». Каждый раз получаете чистую среду, которая удаляется при закрытии.
  3. Установите PSScriptAnalyzer и добавьте его в привычку: прогоняйте через него каждый незнакомый скрипт перед запуском.
  4. Включите логирование PowerShell на постоянной основе — это не сильно нагружает систему, но даёт возможность разобраться постфактум.
  5. Заведите шаблон виртуальной машины с чистой Windows — сделайте снапшот и используйте для особо подозрительных случаев.

Итог

Безопасное тестирование PowerShell-скриптов — это не одна магическая настройка, а слои защиты. Начните с малого: запускайте без прав администратора, включите Constrained Language Mode, смотрите за поведением через ProcMon. Для серьёзных случаев используйте виртуальную машину или Windows Sandbox.

Главный принцип: вы должны понимать, что делает скрипт, до того как запустите его в рабочей среде. Если после анализа остаются сомнения — не запускайте. Лучше потратить лишний час на проверку, чем восстанавливать систему после выполнения вредоносного кода.

Оцените статью
PEFile — Безопасность и технологии простым языком