Verschleierte PowerShell erkennen: Script Block Logging richtig nutzen

Kurzfassung: Angreifer nutzen PowerShell (ATT&CK T1059.001) mit kodierten und verschleierten Befehlen (T1027), weil sie auf jedem Windows-System vorhanden ist und keine Datei hinterlässt. Erkennung: Event 4688 oder Sysmon 1 mit -enc oder -EncodedCommand, verkürzten Parametern und verdächtigen Elternprozessen, und vor allem Event 4104 mit dem entschleierten Skriptblock, das Script Block Logging liefert. Zwei Sigma-Regeln, Atomic-Test und Tuning unten.

Einen PowerShell-Angriff erkennen ist die Erkennung mit dem besten Verhältnis von Aufwand zu Wirkung, die ein Blue Team bauen kann: PowerShell ist auf jedem Windows-System vorhanden, Angreifer benutzen sie in fast jedem Vorfall, und Windows protokolliert auf Wunsch jeden ausgeführten Skriptblock im Klartext, egal wie sehr er vorher verschleiert war. Dieser Beitrag beschreibt, wie Angreifer PowerShell einsetzen, welche Ereignisse das zeigen, warum Event 4104 das wichtigste davon ist, zwei Sigma-Regeln, den Test und die Fehlalarme, die in jeder Umgebung mit Verwaltungsskripten entstehen.

Was der Angreifer tut

PowerShell ist für Angreifer aus drei Gründen attraktiv: Sie ist signiert und vertrauenswürdig, sie kann Code direkt aus dem Netz laden und im Speicher ausführen, ohne eine Datei auf die Platte zu schreiben, und sie hat vollen Zugriff auf .NET und die Windows-API. Der typische Ablauf: Ein Makro, eine Verknüpfung oder ein Skript startet powershell.exe mit einem Base64-kodierten Befehl (-EncodedCommand, meist als -enc abgekürzt), oft mit -NoProfile, -WindowStyle Hidden und -ExecutionPolicy Bypass. Der kodierte Befehl lädt per DownloadString oder Invoke-WebRequest die nächste Stufe und führt sie mit Invoke-Expression aus. Die Verschleierung, in ATT&CK als T1027 geführt, kommt dazu: Zeichenketten werden zerlegt und zusammengesetzt, Befehle in Variablen versteckt, mehrfach kodiert, mit Ticks und Groß-Klein-Schreibung unkenntlich gemacht. Ziel ist, dass die Befehlszeile für Regeln und Analysten nichts Lesbares enthält. Genau das ist der Punkt, an dem die Erkennung ansetzt, denn was PowerShell ausführt, muss sie irgendwann entschleiern.

Welche Logquellen die Technik zeigen

QuelleEreignisWas du siehst
PowerShell/Operational4104, Skriptblock-ProtokollierungDer tatsächlich ausgeführte Code nach der Entschleierung, in Blöcken, mit Skriptblock-ID und Pfad, falls aus Datei. Die wichtigste Quelle.
PowerShell/Operational4103, ModulprotokollierungAufgerufene Cmdlets mit Parametern; gesprächig, aber für die Rekonstruktion wertvoll.
Security-Log4688, Prozess erstellt, mit Befehlszeilepowershell.exe oder pwsh.exe mit Parametern, Elternprozess. Ohne die Richtlinie für die Befehlszeile nur der Start.
Sysmon1, Prozess erstelltWie 4688, dazu Hash, Signatur und die vollständige Elternkette; zeigt Office oder Browser als Elternprozess.
Sysmon3 und 22, Netzwerkverbindung und DNSDer Download der nächsten Stufe, dem Prozess zugeordnet.
Windows PowerShell (klassisch)400 und 800Engine-Start mit Hostanwendung und Version; zeigt, wenn eine alte PowerShell-Version 2 ohne Logging genutzt wird.

Script Block Logging ist eine Gruppenrichtlinie unter Windows-Komponenten, Windows PowerShell, und sie ist in der Standardkonfiguration aus. Microsoft beschreibt die Einstellungen in der Dokumentation zur PowerShell-Protokollierung unter Windows. Auch ohne die Richtlinie protokolliert PowerShell seit Version 5 Skriptblöcke mit verdächtigen Mustern automatisch auf Stufe Warnung; das ist ein Sicherheitsnetz, kein Ersatz. Wer die Richtlinie setzt, bekommt jeden Block, und wer die Überwachungsrichtlinie für die Befehlszeile dazu setzt, bekommt beide Sichten: den Aufruf und den Inhalt.

Das Muster im Log

Auf der Ebene der Befehlszeile gibt es fünf Signale, die selten legitim zusammen auftreten: ein kodierter Befehl, ein verstecktes Fenster, umgangene Ausführungsrichtlinie, kein Profil, und ein Elternprozess, der keine PowerShell starten sollte, also Office-Anwendungen, Browser, PDF-Reader, der WMI-Provider oder ein Webserver-Prozess. Zwei oder drei davon zusammen sind ein Alarm wert, alle fünf sind fast immer ein Angriff. Auf der Ebene des Skriptblocks in 4104 kommen die Schlüsselwörter dazu, die Verschleierung nicht verstecken kann, weil PowerShell sie zum Ausführen braucht: FromBase64String, DownloadString, IEX oder Invoke-Expression, Net.WebClient, -join mit Zeichenarrays, [char]-Konvertierungen in Serie, Reflection.Assembly und VirtualAlloc für Code im Speicher, dazu die Namen bekannter Werkzeuge wie Invoke-Mimikatz oder PowerView. Ein drittes Muster ist die Menge: Ein Skriptblock mit tausenden Zeichen ohne Zeilenumbruch, oder hunderte 4104-Ereignisse in einer Sekunde, weil ein verschleiertes Skript sich in Blöcken entpackt. Und ein viertes: der Versuch, das Logging selbst abzuschalten, sichtbar als Skriptblock, der auf AMSI-Klassen oder die Logging-Einstellungen zugreift, denn dieser Block wird protokolliert, bevor er wirkt.

Zwei Sigma-Regeln

Die erste Regel arbeitet auf der Prozesserstellung und fängt den Aufruf, die zweite auf dem Skriptblock und fängt den Inhalt. Beide gehören aktiviert, weil sie verschiedene Dinge sehen.

Sigma
title: PowerShell Encoded Command From Suspicious Parent
id: 4a2c8e1d-6f3b-4d9a-b7c5-2e1f0a9b8c7d
status: test
description: PowerShell mit kodiertem Befehl, gestartet aus einer Anwendung,
  die keine PowerShell starten sollte.
references:
  - https://attack.mitre.org/techniques/T1059/001/
author: Blue Team
date: 2026-09-13
tags:
  - attack.execution
  - attack.t1059.001
  - attack.defense_evasion
  - attack.t1027
logsource:
  category: process_creation
  product: windows
detection:
  selection_ps:
    Image|endswith:
      - '\powershell.exe'
      - '\pwsh.exe'
  selection_flags:
    CommandLine|contains:
      - ' -enc '
      - ' -e '
      - '-EncodedCommand'
      - '-ec '
  selection_parent:
    ParentImage|endswith:
      - '\winword.exe'
      - '\excel.exe'
      - '\outlook.exe'
      - '\msedge.exe'
      - '\chrome.exe'
      - '\wmiprvse.exe'
      - '\w3wp.exe'
      - '\mshta.exe'
  condition: selection_ps and selection_flags and selection_parent
falsepositives:
  - Selten; Add-ins, die PowerShell mit kodierten Befehlen aus Office starten
level: high
Sigma
title: PowerShell Script Block With Download And Execute Pattern
id: 9b7d3f2a-1c5e-4a8b-9d6f-3e2a1b0c9d8e
status: test
description: Skriptblock, der Code aus dem Netz laedt und im Speicher
  ausfuehrt, oder Base64 dekodiert und ausfuehrt.
references:
  - https://attack.mitre.org/techniques/T1059/001/
author: Blue Team
date: 2026-09-13
tags:
  - attack.execution
  - attack.t1059.001
logsource:
  product: windows
  category: ps_script
detection:
  selection_download:
    ScriptBlockText|contains:
      - 'DownloadString'
      - 'DownloadFile'
      - 'Invoke-WebRequest'
      - 'Net.WebClient'
  selection_execute:
    ScriptBlockText|contains:
      - 'IEX'
      - 'Invoke-Expression'
      - 'FromBase64String'
      - 'Reflection.Assembly'
  filter_known_scripts:
    Path|startswith:
      - 'C:\ProgramData\Verwaltung\'
      - 'C:\Program Files\Softwareverteilung\'
  condition: selection_download and selection_execute and not filter_known_scripts
falsepositives:
  - Verwaltungsskripte, die Module aus internen Quellen laden; nach Pfad und Signatur ausnehmen
level: high

Die Logquelle ps_script ist die Sigma-Abstraktion für Event 4104, das Feld ScriptBlockText der Inhalt. Wer nur eine Regel aktivieren kann, nimmt die zweite: Sie sieht den Inhalt nach der Entschleierung, und sie sieht auch Angriffe, die PowerShell nicht über powershell.exe starten, sondern die Engine direkt in einen anderen Prozess laden. Beide Regeln gibt es in ähnlicher Form in der Community-Sammlung; die Filter für eigene Skriptpfade sind das, was in jeder Umgebung angepasst werden muss, wie im Beitrag zu Sigma-Regeln beschrieben.

Der Test

Atomic Red Team hat für T1059.001 mehrere Tests, darunter einen kodierten Befehl, einen Download mit Ausführung im Speicher und Aufrufe bekannter Werkzeuge. Im Homelab ist der einfachste Test ein Einzeiler auf dem Client: einen harmlosen Befehl wie Get-Date Base64-kodieren und mit powershell.exe -enc starten. Innerhalb von Sekunden müssen drei Ereignisse im SIEM stehen: 4688 mit dem kodierten Befehl, Sysmon 1 mit dem Elternprozess und 4104 mit Get-Date im Klartext. Wenn 4104 fehlt, ist die Richtlinie nicht gesetzt oder der Kanal nicht angebunden, und das ist das Ergebnis des Tests, nicht die Regel. Für die erste Regel wird der Aufruf aus Word heraus wiederholt, etwa über ein Makro im Lab-Dokument; für die zweite reicht ein Skriptblock mit DownloadString auf eine interne Testadresse und IEX. Ergebnis und Datum wandern in den Navigator, und die Regel gilt erst danach als vorhanden.

Fehlalarme und Tuning

  • Verwaltungsskripte mit kodierten Befehlen. Softwareverteilung, Monitoring-Agenten und manche Backup-Lösungen starten PowerShell mit -enc, weil es Anführungszeichen spart. Sie kommen aus bekannten Elternprozessen und Pfaden und werden darüber ausgenommen, nicht über den Benutzer. Die erste Regel ist deshalb auf verdächtige Elternprozesse eingeschränkt; eine zweite Variante ohne diese Einschränkung läuft als Suche für das Hunting, nicht als Alarm.
  • Module aus internen Quellen. Skripte, die Module per Invoke-WebRequest von einem internen Server laden und ausführen, sehen wie die zweite Regel aus. Sie bekommen einen Filter nach Pfad und, besser, eine Signatur; danach ist der Filter auf signierte Skripte aus dem Verwaltungspfad eng genug.
  • Volumen von 4104. Mit Script Block Logging erzeugen Systeme mit vielen Skripten Megabytes pro Tag. Das Volumen wird nicht durch Abschalten reduziert, sondern durch Filterung bekannter Blöcke vor dem SIEM anhand von Pfad und Skriptblock-ID, wie im Beitrag zum SIEM beschrieben.
  • PowerShell Version 2. Die alte Engine kennt kein Script Block Logging, und Angreifer starten sie gezielt mit -Version 2. Das Gegenmittel ist keine Regel, sondern das Entfernen der Version-2-Engine als Windows-Feature; bis dahin ist jeder Aufruf mit -Version 2 ein Alarm für sich.
  • Die Gegenmaßnahme, die die Regel entlastet. Constrained Language Mode über eine Anwendungssteuerung, Makros aus dem Internet blockiert, und das Logging so geschützt, dass ein Angreifer es nicht per Registry abschalten kann, ohne dass Event 4719 oder eine Änderung im Sysmon-Registry-Ereignis erscheint.

Fazit

Verschleierte PowerShell ist die Technik, bei der der Angreifer am meisten Aufwand in das Verstecken steckt und Windows am meisten davon wieder aufdeckt, sofern jemand die Richtlinie gesetzt hat. Event 4104 zeigt den Code, den der Angreifer nicht zeigen wollte, und zwei Regeln, eine auf den Aufruf und eine auf den Inhalt, decken den Großteil dessen ab, was in echten Vorfällen über PowerShell läuft. Nach Kerberoasting ist das die zweite Erkennung, die ein Blue Team baut, und die erste, die fast täglich etwas findet.

NH

$ whoami

Norbert Hofmann

Cyber Defense Analyst im Security Operations Center eines Managed Security Service Providers. Red und Blue Teaming, Malware-Analyse, Incident Response und Security-Awareness-Trainings. Finalist bei „Deutschlands bester Hacker“ 2022, mehrere CVE-Einträge für WordPress-Plugins.