Avkoda ett PowerShell-kommando från en process som körs
Ibland kan du ha en PowerShell-process som tar upp en stor mängd resurser. Den här processen kan köras i kontexten för ett Schemaläggaren jobb eller ett SQL Server Agent-jobb. Om flera PowerShell-processer körs kan det vara svårt att veta vilken process som representerar problemet. Den här artikeln visar hur du avkodar ett skriptblock som en PowerShell-process körs för närvarande.
Skapa en långvarig process
För att demonstrera det här scenariot öppnar du ett nytt PowerShell-fönster och kör följande kod. Den kör ett PowerShell-kommando som matar ut ett tal varje minut i 10 minuter.
powershell.exe -Command {
$i = 1
while ( $i -le 10 )
{
Write-Output -InputObject $i
Start-Sleep -Seconds 60
$i++
}
}
Visa processen
Brödtexten i kommandot som PowerShell kör lagras i egenskapen CommandLine för den Win32_Process klassen. Om kommandot är ett kodat kommando innehåller egenskapen CommandLine strängen "EncodedCommand". Med den här informationen kan det kodade kommandot de-obfuscated via följande process.
Starta PowerShell som administratör. Det är viktigt att PowerShell körs som administratör, annars returneras inga resultat när du kör frågor mot de processer som körs.
Kör följande kommando för att hämta alla PowerShell-processer som har ett kodat kommando:
$powerShellProcesses = Get-CimInstance -ClassName Win32_Process -Filter 'CommandLine LIKE "%EncodedCommand%"'
Följande kommando skapar ett anpassat PowerShell-objekt som innehåller process-ID och det kodade kommandot.
$commandDetails = $powerShellProcesses | Select-Object -Property ProcessId,
@{
name = 'EncodedCommand'
expression = {
if ( $_.CommandLine -match 'encodedCommand (.*) -inputFormat' )
{
return $matches[1]
}
}
}
Nu kan det kodade kommandot avkodas. Följande kodfragment itererar över objektet med kommandoinformation, avkodar det kodade kommandot och lägger till det avkodade kommandot i objektet igen för vidare undersökning.
$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 *
Det avkodade kommandot kan nu granskas genom att välja den avkodade kommandoegenskapen.
ProcessId : 8752
EncodedCommand : IAAKAAoACgAgAAoAIAAgACAAIAAkAGkAIAA9ACAAMQAgAAoACgAKACAACgAgACAAIAAgAHcAaABpAGwAZQAgACgAIAAkAGkAIAAtAG
wAZQAgADEAMAAgACkAIAAKAAoACgAgAAoAIAAgACAAIAB7ACAACgAKAAoAIAAKACAAIAAgACAAIAAgACAAIABXAHIAaQB0AGUALQBP
AHUAdABwAHUAdAAgAC0ASQBuAHAAdQB0AE8AYgBqAGUAYwB0ACAAJABpACAACgAKAAoAIAAKACAAIAAgACAAIAAgACAAIABTAHQAYQ
ByAHQALQBTAGwAZQBlAHAAIAAtAFMAZQBjAG8AbgBkAHMAIAA2ADAAIAAKAAoACgAgAAoAIAAgACAAIAAgACAAIAAgACQAaQArACsA
IAAKAAoACgAgAAoAIAAgACAAIAB9ACAACgAKAAoAIAAKAA==
DecodedCommand :
$i = 1
while ( $i -le 10 )
{
Write-Output -InputObject $i
Start-Sleep -Seconds 60
$i++
}