Een PowerShell-opdracht decoderen vanuit een actief proces

Soms hebt u mogelijk een PowerShell-proces dat een grote hoeveelheid resources in gebruik neemt. Dit proces kan worden uitgevoerd in de context van een Task Scheduler-taak of een SQL Server Agent-taak. Wanneer er meerdere PowerShell-processen worden uitgevoerd, kan het lastig zijn om te weten welk proces het probleem vertegenwoordigt. In dit artikel wordt beschreven hoe u een scriptblok decodeert dat momenteel door een PowerShell-proces wordt uitgevoerd.

Een langlopende procedure maken

Als u dit scenario wilt demonstreren, opent u een nieuw PowerShell-venster en voer u de volgende code uit. Er wordt een PowerShell-opdracht uitgevoerd die tien minuten lang elke minuut een getal uitvoert.

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

Het proces weergeven

De body van de opdracht die door PowerShell wordt uitgevoerd, wordt opgeslagen in de eigenschap CommandLine van de Win32_Process klasse. Als de opdracht een gecodeerde opdracht is, bevat de eigenschap CommandLine de tekenreeks 'EncodedCommand'. Met behulp van deze informatie kan de gecodeerde opdracht worden ontsleuteld via het volgende proces.

Start PowerShell als beheerder. Het is essentieel dat PowerShell wordt uitgevoerd als beheerder, anders worden er geen resultaten geretourneerd bij het uitvoeren van query's op de processen die worden uitgevoerd.

Voer de volgende opdracht uit om alle PowerShell-processen met een gecodeerde opdracht op te halen:

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

Met de volgende opdracht maakt u een aangepast PowerShell-object dat de proces-id en de gecodeerde opdracht bevat.

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

De gecodeerde opdracht kan nu worden gedecodeerd. In het volgende codefragment wordt het object met opdrachtdetails doorgenomen, de gecodeerde opdracht gedecodeerd en wordt de gedecodeerde opdracht weer toegevoegd aan het object voor verder onderzoek.

$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 $currentProcess.processId } |
        Add-Member -MemberType NoteProperty -Name DecodedCommand -Value $decodedCommand
}
$commandDetails[0] | Format-List -Property *

De gedecodeerde opdracht kan nu worden gecontroleerd door de gedecodeerde opdracht-eigenschap te selecteren.

ProcessId      : 8752
EncodedCommand : IAAKAAoACgAgAAoAIAAgACAAIAAkAGkAIAA9ACAAMQAgAAoACgAKACAACgAgACAAIAAgAHcAaABpAGwAZQAgACgAIAAkAGkAIAAtAG
                 wAZQAgADEAMAAgACkAIAAKAAoACgAgAAoAIAAgACAAIAB7ACAACgAKAAoAIAAKACAAIAAgACAAIAAgACAAIABXAHIAaQB0AGUALQBP
                 AHUAdABwAHUAdAAgAC0ASQBuAHAAdQB0AE8AYgBqAGUAYwB0ACAAJABpACAACgAKAAoAIAAKACAAIAAgACAAIAAgACAAIABTAHQAYQ
                 ByAHQALQBTAGwAZQBlAHAAIAAtAFMAZQBjAG8AbgBkAHMAIAA2ADAAIAAKAAoACgAgAAoAIAAgACAAIAAgACAAIAAgACQAaQArACsA
                 IAAKAAoACgAgAAoAIAAgACAAIAB9ACAACgAKAAoAIAAKAA==
DecodedCommand :
                     $i = 1
                     while ( $i -le 10 )
                     {
                         Write-Output -InputObject $i
                         Start-Sleep -Seconds 60
                         $i++
                     }