Een PowerShell-opdracht decoderen vanuit een actief proces

Dit voorbeeld wordt alleen uitgevoerd op Windows-platforms.

Soms hebt u mogelijk een PowerShell-proces dat een grote hoeveelheid resources in beslag neemt. Dit proces kan worden uitgevoerd in de context van een Taakplanner-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 decoderen dat momenteel wordt uitgevoerd door een PowerShell-proces.

Een langlopend proces maken

Als u dit scenario wilt demonstreren, opent u een nieuw PowerShell-venster en voert u de volgende code uit. Er wordt een PowerShell-opdracht uitgevoerd waarmee elke minuut een getal gedurende 10 minuten wordt uitgevoerd.

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

Het proces weergeven

De hoofdtekst van de opdracht die PowerShell uitvoert, 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 via het volgende proces ongedaan worden gemaakt.

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

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. Het volgende codefragment doorloopt het object met opdrachtdetails, decodeert de gecodeerde opdracht en voegt de gedecodeerde opdracht weer toe 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 opdrachteigenschap 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++
                     }