Анализ подозрительного PowerShell в SIEM: обфускация Base64 и AMSI-bypass на реальном образце

По данным CrowdStrike Global Threat Report 2025, 79% атак в 2024 году обошлись без доставки отдельного вредоносного файла. Атакующие используют то, что уже есть на машине, и PowerShell — их любимый инструмент. В SOC это выглядит знакомо: SIEM выдаёт событие с блоком текста на три экрана, каждый второй символ — часть Base64-строки, между ними — вызовы .NET-классов. Под кодировкой прячется отключение антивирусного сканирования и загрузчик полезной нагрузки. Итог для организации — криптомайнер на серверах, RAT (троян удалённого доступа) в корпоративной сети или выгрузка данных. И всё это без единого «настоящего» вредоносного файла на диске.
Разберём, как SOC-аналитику вручную декодировать такой образец, что искать в логах и какие правила обнаружения настроить в SIEM.
Зачем атакующие прячут команды в Base64 и ломают AMSI
Прежде чем лезть в логи — разберёмся, зачем атакующие вообще усложняют себе жизнь обфускацией. Это часть цепочки атаки (kill chain — модель, описывающая этапы от начального доступа до достижения цели), где каждый этап решает конкретную задачу.
Типичная цепочка:
- Initial Access — жертва открывает фишинговое вложение или переходит по ссылке.
- Execution — из документа или ярлыка (.lnk) запускается PowerShell-команда. В базе MITRE ATT&CK (открытая база тактик и техник атак; T-коды вроде T1059.001 — идентификаторы конкретных техник) это техника T1059.001. PowerShell — легитимный инструмент Windows, его запуск сам по себе не вызывает подозрений у антивируса.
- Defense Evasion — команда закодирована в Base64 (T1027.010 — Command Obfuscation), чтобы сигнатурный анализ антивируса не распознал вредоносные строки. Base64 — способ кодирования двоичных данных в текстовую строку из ASCII-символов. Саму кодировку часто используют для легитимных задач, поэтому антивирус не блокирует её автоматически. Дополнительно вредонос отключает AMSI (T1562.001 — Disable or Modify Tools), чтобы следующие скрипты не сканировались.
- Command & Control — после обхода защит скрипт скачивает основную нагрузку (майнер, RAT, бэкдор) с внешнего сервера.
AMSI (Antimalware Scan Interface) — интерфейс Windows, через который антивирус сканирует скрипты и команды прямо перед выполнением. Когда антивирус (Windows Defender, Kaspersky Endpoint Security или другой продукт с поддержкой AMSI) получает через этот интерфейс содержимое скрипта, он проверяет его по сигнатурам. Если атакующий сначала «ломает» AMSI, все последующие команды в этом процессе PowerShell выполняются без проверки — антивирус их просто не видит.
Подход Living off the Land («живём за счёт ресурсов жертвы») делает атаку труднообнаружимой: PowerShell есть на каждой Windows-машине, Base64-кодирование — стандартная функция, а AMSI-bypass выполняется в памяти и не оставляет файлов на диске. Вот почему эти техники так популярны.
Что видит SIEM: ScriptBlock Logging и Event ID 4104
Главный источник телеметрии для обнаружения вредоносного PowerShell — Event ID 4104 из журнала Microsoft-Windows-PowerShell/Operational. Это событие генерируется механизмом ScriptBlock Logging (запись содержимого выполняемых скриптов в журнал событий Windows).
Ключевой момент, который стоит запомнить: ScriptBlock Logging записывает уже декодированный код. Даже если атакующий запускает PowerShell с флагом -EncodedCommand и передаёт туда Base64-строку, в Event ID 4104 попадёт расшифрованное содержимое. Тут возникает парадокс: AMSI-bypass нужен, чтобы скрыть код от антивируса, но сам bypass-скрипт записывается в лог до того, как AMSI отключён. По данным Red Canary, этот парадокс — одна из главных причин, почему детект AMSI-bypass через ScriptBlock Logging работает так хорошо.
Два уровня логирования PowerShell:
- Automatic ScriptBlock Logging — включён по умолчанию начиная с PowerShell 5.0. Записывает скрипты, содержащие «подозрительные» ключевые слова из списка Microsoft (туда входят
Invoke-Expression,FromBase64String,AmsiUtils). Для большинства атак этого достаточно. - Global ScriptBlock Logging — записывает всё, что выполняется в PowerShell, без фильтрации. Нужно включить отдельно. Генерирует большой объём событий, зато не даёт атакующему шанс проскочить мимо фильтра.
Дополнительные источники событий:
- Module Logging (Event ID 800 / 4103) — фиксирует загруженные модули и содержимое
Add-Type. Полезно, когда атакующий компилирует C#-код прямо в PowerShell. - Sysmon Event ID 7 — записывает загрузку DLL. Если процесс (например,
notepad.exe) загружаетSystem.Management.Automation.dll, это означает, что внутри запущен PowerShell-движок без видимого окнаpowershell.exe. Подход описан в проекте Sysmon Modular Олафа Хартонга и рекомендуется Red Canary как дополнение к ScriptBlock Logging.
Как включить расширенное логирование PowerShell
Для настройки через групповую политику (GPO — Group Policy Object, механизм централизованного управления настройками Windows в домене Active Directory):
- Откройте
gpedit.msc→ Computer Configuration → Administrative Templates → Windows Components → Windows PowerShell. - Turn on PowerShell Script Block Logging → Enabled. Поставьте галочку «Log script block invocation start / stop events» для полной трассировки.
- Turn on Module Logging → Enabled. В поле Module Names укажите
*для записи всех модулей. - Выполните
gpupdate /forceна целевых машинах. - Убедитесь, что события из журнала
Microsoft-Windows-PowerShell/Operationalпересылаются в SIEM. Для Splunk это настраивается черезinputs.conf, для Microsoft Sentinel — через Data Connector «Windows Security Events via AMA», для Elastic — через Winlogbeat.
После включения проверьте, что события типа 4104 поступают: выполните в PowerShell любую команду (например, Get-Process) и найдите соответствующее событие в вашем SIEM. Нет события — значит где-то по пути пересылка сломалась, и дальше двигаться бессмысленно.
Деобфускация Base64-пейлоада: пошаговый разбор
Требования к окружению
- ОС: Windows 10/11 или Server 2016+ с PowerShell 5.1 для анализа; для безопасного исследования — изолированная VM (FLARE VM подходит, 4 ГБ RAM минимум, 8 ГБ рекомендуется, без доступа к продуктивной сети)
- Инструменты: PowerShell ISE (входит в состав Windows), CyberChef (запускается в браузере, установка не нужна — gchq.github.io/CyberChef)
- SIEM: Splunk Enterprise 8.x+ / Microsoft Sentinel / Elastic 8.x+ / MaxPatrol SIEM с подключённым источником PowerShell-событий
- Права: доступ на чтение к индексу PowerShell-логов в SIEM (права администратора на конечных точках не нужны)
Находим подозрительное событие и декодируем
Шаг 1 — поиск в SIEM. Ищем события Event ID 4104, содержащие характерные маркеры обфускации. Для Splunk запрос: index=wineventlog EventCode=4104 ("FromBase64String" OR "EncodedCommand"). Для Microsoft Sentinel (KQL): SecurityEvent | where EventID == 4104 | where EventData contains "FromBase64String". Для Elastic: фильтр event.code: "4104" с поиском по powershell.scriptblock.text. Если результаты есть — переходим к анализу. Если нет — вернитесь к предыдущему разделу и убедитесь, что ScriptBlock Logging включён.
Шаг 2 — извлекаем ScriptBlock. Вот типичный подозрительный ScriptBlock из Event ID 4104 (пример адаптирован из реального образца, описанного Pentest Laboratories):
# Содержимое поля ScriptBlockText в Event ID 4104
[Ref].Assembly.GetType(
'System.Management.Automation.' +
$([Text.Encoding]::Unicode.GetString(
[Convert]::FromBase64String('QQBtAHMAaQBVAHQAaQBsAHMA')))
).GetField(
$([Text.Encoding]::Unicode.GetString(
[Convert]::FromBase64String('YQBtAHMAaQBJAG4AaQB0AEYAYQBpAGwAZQBkAA=='))),
'NonPublic,Static'
).SetValue($null,$true)
На первый взгляд — мешанина .NET-вызовов и Base64. Сейчас разберём по шагам.
Шаг 3 — декодируем Base64-строки. В примере две закодированные строки: QQBtAHMAaQBVAHQAaQBsAHMA и YQBtAHMAaQBJAG4AaQB0AEYAYQBpAGwAZQBkAA==. Декодировать можно тремя способами:
- CyberChef (самый безопасный): откройте CyberChef в браузере, добавьте рецепт From Base64 → Decode text (UTF-16LE, потому что PowerShell использует Unicode/UTF-16). Вставьте первую строку — результат:
AmsiUtils. Вставьте вторую — результат:amsiInitFailed. - PowerShell ISE на изолированной VM: выполните
[Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('QQBtAHMAaQBVAHQAaQBsAHMA'))— в консоли появитсяAmsiUtils. Для второй строки аналогично —amsiInitFailed. - Linux:
echo 'QQBtAHMAaQBVAHQAaQBsAHMA' | base64 -d | iconv -f UTF-16LE -t UTF-8вернётAmsiUtils.
Шаг 4 — подставляем результат обратно. Теперь скрипт читается: [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true).
Это классический AMSI-bypass, впервые опубликованный исследователем Мэттом Грэбером: через рефлексию .NET скрипт устанавливает внутренний флаг amsiInitFailed в значение $true. После этого AMSI «считает», что инициализация провалилась, и прекращает сканирование для текущего процесса PowerShell. Все последующие команды в этой сессии выполняются без проверки антивирусом. Одна строчка — и антивирус ослеп.
Как понять, что декодирование прошло верно: результат содержит читаемые строки с осмысленными именами .NET-классов. Если вместо текста «мусор» — попробуйте ASCII вместо UTF-16 или проверьте, не сжато ли содержимое дополнительно через GZip (паттерн IO.Compression.GzipStream + FromBase64String).
AMSI-bypass техники: что искать в логах PowerShell
Разобранный выше пример — одна из техник, причём самая простая. По данным Trend Micro, AMSI-bypass активно используется в реальных атаках: от криптомайнеров до RAT. В одном из задокументированных Trend Micro кейсов цепочка выглядела так: powershell "IEX(New-Object Net.WebClient).DownloadString(...)" → AMSI-bypass через WriteInt32 и строковое форматирование → загрузка XMRig-майнера. Pentest Laboratories описывает минимум семь методов обхода AMSI, каждый с характерными артефактами в Event ID 4104.
Основные AMSI-bypass техники и их маркеры в ScriptBlockText:
| Техника | Что искать в ScriptBlockText | MITRE ATT&CK |
|---|---|---|
| Установка флага amsiInitFailed | amsiInitFailed, AmsiUtils, SetValue($null,$true) |
T1562.001 |
| Патчинг AmsiScanBuffer в памяти | AmsiScanBuffer, VirtualProtect, Marshal::Copy, байты 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3 |
T1562.001 |
| PowerShell Downgrade до v2 | powershell -version 2 в Event ID 4688 / Sysmon EID 1 (в 4104 этих событий нет — PowerShell 2.0 не поддерживает ScriptBlock Logging) |
T1562.001 |
| Строковая конкатенация | '{0}m{1}{2}' -f, разбитые переменные $w = 'System.Management.Automation.A' |
T1027.010 |
| Загрузка и распаковка GZip | IO.Compression.GzipStream, IO.MemoryStream, FromBase64String в связке с IEX (алиас Invoke-Expression) |
T1140 |
Атакующие часто комбинируют техники: сначала кодируют AMSI-bypass в Base64 и сжимают GZip, затем, после отключения AMSI, загружают основную нагрузку — антивирус её уже не сканирует. По наблюдениям s3cur3th1ssh1t, почти все публичные PoC-снипеты AMSI-bypass добавляются в сигнатуры антивирусов в течение нескольких недель после публикации. Поэтому атакующие вынуждены постоянно модифицировать код — менять имена переменных, применять конкатенацию, использовать форматирование строк. Гонка вооружений в чистом виде.
Обнаружение AMSI-bypass: ограничения по вендорам
[Применимо: внутренний пентест, любая Windows-инфраструктура с настроенным ScriptBlock Logging. В средах с отключённым логированием или PowerShell 2.0 детект через Event ID 4104 неприменим.]
- Windows Defender (Windows 10/11, Server 2016+): встроенный AMSI-провайдер. ScriptBlock Logging фиксирует bypass-попытку до её выполнения — но только при включённом логировании. Если Automatic ScriptBlock Logging не настроен, события 4104 не генерируются. Тут всё просто: нет логов — нет детекта.
- Kaspersky Endpoint Security 12.x+ / EDR Expert: поддерживает AMSI как дополнительный источник телеметрии. При обнаружении патчинга
amsi.dllв памяти генерирует отдельное событие, которое можно пересылать в SIEM через syslog. - CrowdStrike Falcon: детектирует AMSI-bypass через собственные сенсоры на уровне ядра, не полагаясь только на ScriptBlock Logging. Событие попадает в Falcon Console и может пересылаться в SIEM через Falcon Data Replicator или API.
- Elastic Security 8.x+ с Elastic Defend: использует комбинацию ScriptBlock Logging и собственных behavior-правил. Из коробки содержит detection rules для AMSI-bypass в категории «Defense Evasion».
Слепая зона — PowerShell Downgrade. Если атакующий запускает powershell -version 2, ScriptBlock Logging не работает вообще. Детект возможен только через анализ командной строки процесса в Event ID 4688 или Sysmon EID 1: наличие флага -version 2 в аргументах. Рекомендация — полностью удалить компонент PowerShell 2.0: Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root. Серьёзно, если у вас ещё стоит PowerShell 2.0 — удалите его сегодня.
SIEM-правила обнаружения подозрительного PowerShell
Sigma-правило для AMSI-bypass и обфускации
Sigma — открытый формат описания правил обнаружения, который конвертируется в запросы для конкретного SIEM (Splunk SPL, Sentinel KQL, Elastic EQL) через утилиту Sigma CLI. Один раз написал правило — используешь везде.
title: AMSI Bypass Attempt in PowerShell ScriptBlock
logsource:
product: windows
service: powershell/scriptblock
detection:
selection:
EventID: 4104
ScriptBlockText|contains|any:
- 'AmsiUtils'
- 'amsiInitFailed'
- 'AmsiScanBuffer'
- 'VirtualProtect'
condition: selection
level: high
После конвертации в SPL для Splunk: index=wineventlog EventCode=4104 (ScriptBlockText="*AmsiUtils*" OR ScriptBlockText="*amsiInitFailed*" OR ScriptBlockText="*AmsiScanBuffer*"). Для KQL в Microsoft Sentinel: SecurityEvent | where EventID == 4104 | where EventData has_any ("AmsiUtils", "amsiInitFailed", "AmsiScanBuffer").
Для обнаружения Base64-обфускации добавьте отдельное правило с ключевыми словами FromBase64String, [Convert]::FromBase64String в связке с Invoke-Expression или его алиасом IEX. Комбинация Base64-декодирования и IEX в одном ScriptBlock — один из самых надёжных индикаторов вредоносной активности.
Ограничения сигнатурных правил
Сигнатурные правила (те, что ищут конкретные строки) — первый рубеж обороны, но не панацея:
- Строковая конкатенация: атакующий разбивает
AmsiUtilsна$a = 'Amsi'; $b = 'Utils'; $a + $b— прямое совпадение не сработает. Решение: детект по поведению — комбинация вызововGetType+GetField+SetValueв одном ScriptBlock. - Переименование переменных: замена
$base64binaryна$xне влияет на функциональность, но обойдёт простую сигнатуру. Решение: ищите .NET-методы (FromBase64String,Reflection.Assembly), а не имена переменных. - Кастомные обфускаторы: инструменты типа Invoke-Obfuscation генерируют множество вариантов одного скрипта. Но, как отмечает s3cur3th1ssh1t, скрипты после Invoke-Obfuscation часто детектируются в мониторируемых средах — сама обфускация становится индикатором. Ирония: чем сильнее запутан скрипт, тем подозрительнее он выглядит.
Поведенческие правила — второй рубеж. Они сложнее в написании и дают больше ложных срабатываний, но обходить их значительно труднее. Пример: правило SIEM-корреляции, срабатывающее при сочетании «запуск PowerShell от дочернего процесса Word/Excel» + «сетевое соединение на внешний IP» в рамках одного хоста за 5 минут. По данным PT Research, атакующему в корне изменить своё поведение при атаке — задача нерешаемая, в отличие от смены строковых сигнатур.
Чеклист: настройка обнаружения PowerShell-угроз
Готовый список действий для передачи сисадмину или включения в аудиторский отчёт:
- Включить ScriptBlock Logging через GPO:
Computer Configuration → Administrative Templates → Windows PowerShell → Turn on PowerShell Script Block Logging → Enabled. - Включить Module Logging через GPO:
Turn on Module Logging → Enabled, Module Names =*. - Удалить PowerShell 2.0:
Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root. - Настроить пересылку событий из
Microsoft-Windows-PowerShell/Operationalв SIEM (WEF, Winlogbeat или агент SIEM). - Создать правило обнаружения AMSI-bypass: Event ID 4104 с ключевыми словами
AmsiUtils,amsiInitFailed,AmsiScanBuffer,VirtualProtect. - Создать правило обнаружения Base64-обфускации: Event ID 4104 с
FromBase64String+IEX/Invoke-Expressionв одном ScriptBlock. - Настроить алерт на
powershell -version 2в Event ID 4688 или Sysmon EID 1. - Развернуть Sysmon с конфигурацией Sysmon Modular — Event ID 7 для загрузки
System.Management.Automation.dllнестандартными процессами. - Рассмотреть Constrained Language Mode через WDAC или AppLocker — блокирует большинство AMSI-bypass на уровне политики.
- Проверить через 7 дней: события 4104 поступают, правила генерируют алерты на тестовых кейсах, ложные срабатывания не превышают допустимого порога.
Каждый пункт — конкретная задача. Первые четыре закрывают телеметрию (без неё обнаружение невозможно), пункты 5-7 — базовый детект, 8-10 — усиление позиции. OWASP A09:2021 (Security Logging and Monitoring Failures) прямо указывает: без настроенного логирования нарушения не обнаруживаются. NIST CSF 2.0 в подкатегории DE.AE-01 требует установить baseline и отслеживать отклонения — анализ логов PowerShell ложится точно сюда.
Большинство SOC-команд останавливаются на первом уровне: включают ScriptBlock Logging, пишут пару Sigma-правил на известные строки и считают задачу решённой. Формально — алерты приходят. На практике — атакующие давно знают эти строки и обходят их конкатенацией, форматированием, GZip-сжатием. Разница между «у нас есть правило на PowerShell» и «мы реально ловим обфусцированный PowerShell» — в поведенческих правилах и в рутине ручного разбора.
CyberChef плюс десять минут на декодирование Base64 → GZip → ещё раз Base64 — вещь, которую автоматика не заменяет, потому что каждый образец уникален. Пока SOC полагается только на сигнатуры, атакующий с Invoke-Obfuscation опережает на два шага. Когда аналитик умеет разбирать руками — сигнатуры становятся первым фильтром, а не последней линией обороны. Это и есть главный навык, который отличает L1-оператора, закрывающего алерт кнопкой, от L2-аналитика, способного вытащить из закодированного блока конкретный индикатор компрометации (хеш, URL, IP-адрес) и понять, что именно хотел сделать атакующий. Если ты переходишь в ИБ из IT и хочешь системно разобраться в таких задачах — на IB Basics эту цепочку разбирают с лабами за пару месяцев.
Эту тему и смежные навыки разбирают на практике в курсе «Аналитик SOC» Codeby Academy.