Dekódování příkazu PowerShellu z běžícího procesu

Tato ukázka běží jenom na platformách Windows.

Někdy můžete mít spuštěný proces PowerShellu, který zabírá velké množství prostředků. Tento proces může být spuštěn v kontextu úlohy plánovače úloh nebo úlohy agenta SQL Serveru. Pokud je spuštěno více procesů PowerShellu, může být obtížné zjistit, který proces představuje problém. Tento článek ukazuje, jak dekódovat blok skriptu, který je aktuálně spuštěný proces PowerShellu.

Vytvoření dlouhotrvajícího procesu

Pokud chcete tento scénář předvést, otevřete nové okno PowerShellu a spusťte následující kód. Spustí příkaz PowerShellu, který každých minutu vypíše číslo po dobu 10 minut.

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

Zobrazení procesu

Tělo příkazu, který PowerShell spouští, je uložen v CommandLine vlastnost Win32_Process třídy. Pokud je příkaz kódovaný příkaz, vlastnost CommandLine obsahuje řetězec "EncodedCommand". Pomocí těchto informací lze kódovaný příkaz defuscovat pomocí následujícího procesu.

Spusťte PowerShell jako Správa istrator. Je důležité, aby PowerShell běžel jako správce, jinak se při dotazování spuštěných procesů nevrací žádné výsledky.

Spuštěním následujícího příkazu získejte všechny procesy PowerShellu, které mají kódovaný příkaz:

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

Následující příkaz vytvoří vlastní objekt PowerShellu, který obsahuje ID procesu a kódovaný příkaz.

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

Teď lze kódovaný příkaz dekódovat. Následující fragment kódu iteruje objekt podrobností příkazu, dekóduje kódovaný příkaz a přidá dekódovaný příkaz zpět do objektu pro další šetření.

$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 *

Dekódovaný příkaz je teď možné zkontrolovat výběrem dekódované vlastnosti příkazu.

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