Decodieren eines PowerShell-Befehls in einem laufenden ProzessDecode a PowerShell command from a running process

Gelegentlich wird möglicherweise ein PowerShell-Prozess ausgeführt, der eine große Menge an Ressourcen beansprucht.At times, you may have a PowerShell process running that is taking up a large amount of resources. Dieser Prozess kann im Rahmen eines Aufgabenplanung-Auftrags oder eines SQL Server-Agent-Auftrags ausgeführt werden.This process could be running in the context of a Task Scheduler job or a SQL Server Agent job. Wenn mehrere PowerShell-Prozesse ausgeführt werden, kann eine Identifizierung schwierig sein, welcher Prozess das Problem darstellt.Where there are multiple PowerShell processes running, it can be difficult to know which process represents the problem. Dieser Artikel zeigt, wie Sie einen Skriptblock decodieren, der aktuell von einem PowerShell-Prozess ausgeführt wird.This article shows how to decode a script block that a PowerShell process is currently running.

Erstellen eines zeitintensiven ProzessesCreate a long running process

Um dieses Szenario zu veranschaulichen, öffnen Sie ein neues PowerShell-Fenster und führen den folgenden Code aus.To demonstrate this scenario, open a new PowerShell window and run the following code. Es führt einen PowerShell-Befehl aus, der 10 Minuten lang jede Minute eine Zahl ausgibt.It executes a PowerShell command that outputs a number every minute for 10 minutes.

powershell.exe -Command {
    $i = 1
    while ( $i -le 10 )
    {
        Write-Output -InputObject $i
        Start-Sleep -Seconds 60
        $i++
    }
}

Anzeigen des ProzessesView the process

Der Textkörper des Befehls, den PowerShell ausführt, wird in der Eigenschaft CommandLine der Klasse Win32_Process gespeichert.The body of the command which PowerShell is executing is stored in the CommandLine property of the Win32_Process class. Wenn der Befehl ein codierter Befehl ist, enthält die CommandLine-Eigenschaft die Zeichenfolge „EncodedCommand“.If the command is an encoded command, the CommandLine property contains the string "EncodedCommand". Mithilfe dieser Informationen kann der codierte Befehl über den folgenden Prozess entschleiert werden.Using this information, the encoded command can be de-obfuscated via the following process.

Starten Sie PowerShell als Administrator.Start PowerShell as Administrator. Es ist unerlässlich, dass PowerShell als Administrator ausgeführt wird, da andernfalls bei der Abfrage der ausgeführten Prozesse keine Ergebnisse zurückgegeben werden.It is vital that PowerShell is running as administrator, otherwise no results are returned when querying the running processes.

Führen Sie den folgenden Befehl aus, um alle PowerShell-Prozesse abzurufen, die über einen codierten Befehl verfügen:Execute the following command to get all of the PowerShell processes that have an encoded command:

$powerShellProcesses = Get-CimInstance -ClassName Win32_Process -Filter 'CommandLine LIKE "%EncodedCommand%"'

Der folgende Befehl erstellt ein benutzerdefiniertes PowerShell-Objekt, das die Prozess-ID und den codierten Befehl enthält.The following command creates a custom PowerShell object that contains the process ID and the encoded command.

$commandDetails = $powerShellProcesses | Select-Object -Property ProcessId,
@{
    name       = 'EncodedCommand'
    expression = {
        if ( $_.CommandLine -match 'encodedCommand (.*) -inputFormat' )
        {
            return $matches[1]
        }
    }
}

Jetzt kann der codierte Befehl decodiert werden.Now the encoded command can be decoded. Der folgende Codeausschnitt iteriert durch das Befehlsdetailobjekt, decodiert den codierten Befehl und fügt den decodierten Befehl zur weiteren Untersuchung dem Objekt erneut hinzu.The following snippet iterates over the command details object, decodes the encoded command, and adds the decoded command back to the object for further investigation.

$commandDetails | ForEach-Object -Process {
    # Get the current process
    $currentProcess = $_

    # Convert the Base 64 string to a Byte Array
    $commandBytes = [System.Convert]::FromBase64String($currentProcess.EncodedCommand)

    # Convert the Byte Array to a string
    $decodedCommand = [System.Text.Encoding]::Unicode.GetString($commandBytes)

    # Add the decoded command back to the object
    $commandDetails |
        Where-Object -FilterScript { $_.ProcessId -eq $_.ProcessId } |
        Add-Member -MemberType NoteProperty -Name DecodedCommand -Value $decodedCommand
}
$commandDetails[0]

Der decodierte Befehl kann jetzt durch Auswählen der decodierten Befehlseigenschaft überprüft werden.The decoded command can now be reviewed by selecting the decoded command property.

ProcessId      : 8752
EncodedCommand : IAAKAAoACgAgAAoAIAAgACAAIAAkAGkAIAA9ACAAMQAgAAoACgAKACAACgAgACAAIAAgAHcAaABpAGwAZQAgACgAIAAkAGkAIAAtAG
                 wAZQAgADEAMAAgACkAIAAKAAoACgAgAAoAIAAgACAAIAB7ACAACgAKAAoAIAAKACAAIAAgACAAIAAgACAAIABXAHIAaQB0AGUALQBP
                 AHUAdABwAHUAdAAgAC0ASQBuAHAAdQB0AE8AYgBqAGUAYwB0ACAAJABpACAACgAKAAoAIAAKACAAIAAgACAAIAAgACAAIABTAHQAYQ
                 ByAHQALQBTAGwAZQBlAHAAIAAtAFMAZQBjAG8AbgBkAHMAIAA2ADAAIAAKAAoACgAgAAoAIAAgACAAIAAgACAAIAAgACQAaQArACsA
                 IAAKAAoACgAgAAoAIAAgACAAIAB9ACAACgAKAAoAIAAKAA==
DecodedCommand :
                     $i = 1

                     while ( $i -le 10 )

                     {

                         Write-Output -InputObject $i

                         Start-Sleep -Seconds 60

                         $i++

                     }