Пятый год подряд PowerShell входит в топ техник, которые Red Canary фиксирует у атакующих в реальных инцидентах. В отчёте за 2026 год — второе место. Не потому что PowerShell «взломан» или в нём дыра. А потому что он встроен в каждую Windows, его нельзя удалить, и он умеет дотянуться до всего: реестра, файлов, сети, памяти процессов, Active Directory.
Это и есть то, что в защите называют living off the land — «жить с земли». Не тащить с собой чужой инструмент, который поймает антивирус. Использовать то, что уже стоит в системе легально.
Материал создан в образовательных целях, для понимания того, как защититься и что искать в логах. Использование техник обхода защиты на системах без письменного разрешения владельца — уголовно наказуемо.
Если ты администрируешь Windows или просто интересуешься, как защищаются от таких атак — тебе нужно понимать PowerShell не как «чёрное окошко с командами», а как то, чем он на самом деле является.
Не CMD 2.0
Разница между CMD и PowerShell — как между сортировкой бумажных анкет по линейке и запросом в базу данных.
В CMD ты работаешь с текстом. Хочешь найти файл — берёшь строку вывода и ищешь в ней подстроку. Хочешь отсортировать процессы по памяти — команда sort считает символы слева направо и режет строку в заданной позиции. Если имя процесса длиннее обычного и сдвинуло колонку — сортировка ломается. Девятка окажется «больше» ста, потому что для текстовой сортировки «9» идёт после «1».
В PowerShell команда Get-Process возвращает не текст, а объекты. У каждого процесса есть свойство CPU — число, а не строка на экране. Когда ты пишешь Sort-Object CPU, PowerShell сравнивает именно это число, и ему всё равно, длинное имя у процесса или короткое. Данные и их отображение — это две разные вещи.
Отсюда и вся разница в возможностях. CMD показывает тебе текст. PowerShell даёт доступ к структуре системы.
Конвейер: команды передают друг другу не текст, а объекты
Ключевая идея PowerShell — конвейер (pipeline). Одна команда выдаёт объекты, следующая их фильтрует или сортирует, третья показывает результат.
powershell
Get-Process | Where-Object { $_.WorkingSet -gt 100MB } | Sort-Object WorkingSet -Descending
$_ — это «текущий объект в конвейере». $_.WorkingSet — его свойство, память в байтах. Ты не парсишь текст регулярками, как в CMD, — ты обращаешься к полю объекта напрямую.
Это же и делает PowerShell мощным инструментом автоматизации: администратор пишет пять строк, и они разбирают, фильтруют, экспортируют данные с любой машины в домене.
Execution Policy — не защита
Многие думают, что Execution Policy защищает от вредоносных скриптов. Это не так, и Microsoft прямо пишет в документации: это не граница безопасности (security boundary).
Execution Policy не даёт случайно запустить скрипт двойным щелчком. От целенаправленной атаки она не защищает вообще:
powershell
powershell -ExecutionPolicy Bypass -File script.ps1
Или ещё проще — вставить код прямо в консоль. На прямой ввод политика не распространяется.
Реальная защита — это не запрет запуска, а видимость того, что было запущено.
Что реально ловит вредоносный PowerShell
AMSI (Antimalware Scan Interface) — встроенный в Windows стандарт, через который PowerShell отправляет содержимое скрипта антивирусу перед выполнением. Важный момент: проверка происходит уже после того, как код раскрыл сам себя — деобфусцировался. Поэтому обфускация сама по себе AMSI не обманывает.
Script Block Logging — записывает в журнал событий (Event ID 4104) реальный текст выполненного кода, уже в раскрытом виде. Без него расследовать инцидент постфактум почти невозможно: видно, что PowerShell запускался, но не видно, что он делал.
Constrained Language Mode — режим, в котором PowerShell разрешает только базовые команды и запрещает прямой вызов Win32 API и произвольных .NET-объектов. Включается автоматически, когда в системе работает AppLocker или WDAC в режиме Enforce — и это касается вообще всех, включая администраторов.
Три уровня защиты работают вместе: даже если атакующий обошёл один — остаются другие.
Что сделать прямо сейчас
- Проверь, какой у тебя языковой режим:
powershell
$ExecutionContext.SessionState.LanguageMode
Если не FullLanguage — значит, кто-то (возможно, ты сам) уже настроил ограничение.
- Проверь, включено ли логирование блоков скриптов:
powershell
Get-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging"
Если команда выдаёт ошибку — значит, раздел реестра не создан, и логирование через GPO не настроено. Для домашней машины это норм. Для рабочей — стоит спросить у админа.
- Посмотри, какие антивирусы зарегистрированы как AMSI-провайдеры:
powershell
Get-ChildItem "HKLM:\SOFTWARE\Microsoft\AMSI\Providers"
Готовые скрипты в моём GitHub.

