Декодирование команды PowerShell из выполняемого процесса
Этот пример выполняется только на платформах Windows.
Иногда у вас может быть запущен процесс PowerShell, который занимает большое количество ресурсов. Этот процесс может быть запущен в контексте задания планировщика задач или задания агента SQL Server. Если запущено несколько процессов PowerShell, может быть трудно определить, какой процесс представляет проблему. В этой статье показано, как декодировать блок скрипта, который в данный момент выполняется процессом PowerShell.
Создание длительного процесса
Для демонстрации этого сценария откройте новое окно PowerShell и выполните следующий код. Он выполняет команду PowerShell, которая выводит число каждую минуту в течение 10 минут.
powershell.exe -Command {
$i = 1
while ( $i -le 10 )
{
Write-Output -InputObject $i
Start-Sleep -Seconds 60
$i++
}
}
Представление процесса
Текст команды, выполняемой PowerShell, хранится в свойстве CommandLine класса Win32_Process. Если команда является зашифрованной, свойство CommandLine содержит строку EncodedCommand. Используя эту информацию, зашифрованная команда может быть удалена с помощью следующего процесса.
Запустите PowerShell от имени администратора. Крайне важно, чтобы PowerShell выполнялась от имени администратора, в противном случае результаты не возвращаются при запросе выполняемых процессов.
Выполните следующую команду, чтобы получить все процессы PowerShell с закодированной командой:
$powerShellProcesses = Get-CimInstance -ClassName Win32_Process -Filter 'CommandLine LIKE "%EncodedCommand%"'
Следующая команда создает пользовательский объект PowerShell, который содержит идентификатор процесса и зашифрованную команду.
$commandDetails = $powerShellProcesses | Select-Object -Property ProcessId,
@{
name = 'EncodedCommand'
expression = {
if ( $_.CommandLine -match 'encodedCommand (.*) -inputFormat' )
{
return $matches[1]
}
}
}
Теперь зашифрованная команда может быть декодирована. Следующий фрагмент перебирает объект сведений о команде, декодирует зашифрованную команду и добавляет декодированную команду обратно к объекту для дальнейшего изучения.
$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 *
Теперь можно просмотреть декодированную команду, выбрав ее свойство.
ProcessId : 8752
EncodedCommand : IAAKAAoACgAgAAoAIAAgACAAIAAkAGkAIAA9ACAAMQAgAAoACgAKACAACgAgACAAIAAgAHcAaABpAGwAZQAgACgAIAAkAGkAIAAtAG
wAZQAgADEAMAAgACkAIAAKAAoACgAgAAoAIAAgACAAIAB7ACAACgAKAAoAIAAKACAAIAAgACAAIAAgACAAIABXAHIAaQB0AGUALQBP
AHUAdABwAHUAdAAgAC0ASQBuAHAAdQB0AE8AYgBqAGUAYwB0ACAAJABpACAACgAKAAoAIAAKACAAIAAgACAAIAAgACAAIABTAHQAYQ
ByAHQALQBTAGwAZQBlAHAAIAAtAFMAZQBjAG8AbgBkAHMAIAA2ADAAIAAKAAoACgAgAAoAIAAgACAAIAAgACAAIAAgACQAaQArACsA
IAAKAAoACgAgAAoAIAAgACAAIAB9ACAACgAKAAoAIAAKAA==
DecodedCommand :
$i = 1
while ( $i -le 10 )
{
Write-Output -InputObject $i
Start-Sleep -Seconds 60
$i++
}
PowerShell