Поделиться через


Декодирование команды 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++
                     }