Ablaufverfolgung und Protokollierung von Skripts

Während PowerShell bereits über die Gruppenrichtlinieneinstellung LogPipelineExecutionDetails verfügt, um den Aufruf von Cmdlets zu protokollieren, bietet die PowerShell-Skriptsprache mehrere Features, die Sie ggf. protokollieren und überwachen möchten. Das neue Feature zur detaillierten Ablaufverfolgung von Skripts stellt eine detaillierte Nachverfolgung und Analyse der Verwendung von PowerShell-Skriptaktivitäten auf einem System bereit. Nachdem Sie die detaillierte Ablaufverfolgung von Skripts aktiviert haben, protokolliert PowerShell alle Skriptblöcke im ETW-Ereignisprotokoll Microsoft-Windows-PowerShell/Operational. Wenn ein Skriptblock einen anderen Skriptblock erzeugt, z. B. durch Aufrufen von Invoke-Expression, wird der aufgerufene Skriptblock ebenfalls protokolliert.

Die Protokollierung wird über die Gruppenrichtlinieneinstellung „Protokollierung von PowerShell-Skriptblöcken aktivieren“ unter Administrative Vorlagen –>Windows-Komponenten –>Windows PowerShell aktiviert.

Die Ereignisse sind wie folgt:

Channel Bei Betrieb
Ebene Ausführlich
Opcode Erstellen
Aufgabe CommandStart
Schlüsselwort Runspace
EventId Engine_ScriptBlockCompiled (0x1008 = 4104)
`Message` Skriptblocktext erstellen (%1 von %2):
%3
ScriptBlock-ID: %4

Der in der Meldung eingebettete Text gibt das Ausmaß des kompilierten Skriptblocks an. Die ID ist eine GUID, die für die Gültigkeitsdauer des Skriptblocks beibehalten wird.

Wenn Sie die ausführlichen Protokollierung aktivieren, schreibt das Feature die Markierungen „begin“ und „end“:

Channel Bei Betrieb
Ebene Ausführlich
Opcode Öffnen/Schließen
Aufgabe CommandStart/CommandStop
Schlüsselwort Runspace
EventId ScriptBlock_Invoke_Start_Detail (0x1009 = 4105) /
ScriptBlock_Invoke_Complete_Detail (0x100A = 4106)
`Message` Aufruf der ScriptBlock-ID gestartet/abgeschlossen: %1
Runspace-ID: %2

Die ID ist die GUID, die den Skriptblock darstellt (der mit der Ereignis-ID 0x1008 korreliert werden kann). Die Runspace-ID stellt den Runspace dar, in dem dieser Skriptblock ausgeführt wurde.

Prozentzeichen in der Aufrufmeldung stellen strukturierte ETW-Eigenschaften dar. Wenngleich sie im Meldungstext durch die tatsächlichen Werte ersetzt werden, empfiehlt sich für den Zugriff darauf eher das Abrufen der Meldung mit dem Cmdlet „Get-WinEvent“ und dann das Untersuchen des Bereichs Eigenschaften der Meldung.

Hier ist ein Beispiel, wie diese Funktionalität helfen kann, einen böswilligen Versuch zum Verschlüsseln und Verschleiern eines Skripts zu erkennen:

## Malware
function SuperDecrypt
{
    param($script)
    $bytes = [Convert]::FromBase64String($script)

    ## XOR "encryption"
    $xorKey = 0x42
    for($counter = 0; $counter -lt $bytes.Length; $counter++)
    {
        $bytes[$counter] = $bytes[$counter] -bxor $xorKey
    }
    [System.Text.Encoding]::Unicode.GetString($bytes)
}

$decrypted = SuperDecrypt "FUIwQitCNkInQm9CCkItQjFCNkJiQmVCEkI1QixCJkJlQg=="
Invoke-Expression $decrypted

Bei Ausführen dieses Befehls werden die folgenden Einträge generiert:

Compiling Scriptblock text (1 of 1):
function SuperDecrypt
{
    param($script)
    $bytes = [Convert]::FromBase64String($script)
    ## XOR "encryption"
    $xorKey = 0x42
    for($counter = 0; $counter -lt $bytes.Length; $counter++)
    {
        $bytes[$counter] = $bytes[$counter] -bxor $xorKey
    }
    [System.Text.Encoding]::Unicode.GetString($bytes)

}
ScriptBlock ID: ad8ae740-1f33-42aa-8dfc-1314411877e3

Compiling Scriptblock text (1 of 1):
$decrypted = SuperDecrypt "FUIwQitCNkInQm9CCkItQjFCNkJiQmVCEkI1QixCJkJlQg=="
ScriptBlock ID: ba11c155-d34c-4004-88e3-6502ecb50f52

Compiling Scriptblock text (1 of 1):
Invoke-Expression $decrypted
ScriptBlock ID: 856c01ca-85d7-4989-b47f-e6a09ee4eeb3

Compiling Scriptblock text (1 of 1):
Write-Host 'Pwnd'
ScriptBlock ID: 5e618414-4e77-48e3-8f65-9a863f54b4c8

Wenn die Länge eines Skriptblocks größer als die Kapazität eines einzelnen Ereignisses ist, teilt PowerShell das Skript in mehrere Teile auf. Hier ist Beispielcode für das erneute Zusammenzusetzen der Protokollmeldungen eines Skripts:

$created = Get-WinEvent -FilterHashtable @{ ProviderName="Microsoft-Windows-PowerShell"; Id = 4104 } |
  Where-Object { $_.<...> }
$sortedScripts = $created | sort { $_.Properties[0].Value }
$mergedScript = -join ($sortedScripts | % { $_.Properties[2].Value })

Wie alle Protokollierungssysteme, die einen begrenzten Aufbewahrungspuffer haben, besteht eine Angriffsmöglichkeit auf diese Infrastruktur darin, dass Protokoll mit gefälschten Ereignissen zu überfluten, um ein früheres Vorkommen zu vertuschen. Um sich vor diesen Angriffen zu schützen, stellen Sie sicher, dass Sie eine Form der Ereignisprotokollerfassung eingerichtet haben, z. B. Windows-Ereignisweiterleitung. Weitere Informationen finden Sie unter Use Azure Monitor to integrate with SIEM tools (Verwenden von Azure Monitor für die Integration in SIEM-Tools).