Share via


Decode a PowerShell command from a running process (Descodificar um comando do PowerShell a partir de um processo em execução)

Este exemplo só é executado em plataformas Windows.

Às vezes, você pode ter um processo do PowerShell em execução que está ocupando uma grande quantidade de recursos. Esse processo pode estar sendo executado no contexto de um trabalho do Agendador de Tarefas ou de um trabalho do SQL Server Agent . Onde há vários processos do PowerShell em execução, pode ser difícil saber qual processo representa o problema. Este artigo mostra como decodificar um bloco de script que um processo do PowerShell está executando no momento.

Criar um processo de longa duração

Para demonstrar esse cenário, abra uma nova janela do PowerShell e execute o código a seguir. Ele executa um comando do PowerShell que gera um número a cada minuto durante 10 minutos.

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

Ver o processo

O corpo do comando que o PowerShell está executando é armazenado na propriedade CommandLine da classe Win32_Process . Se o comando for um comando codificado, a propriedade CommandLine conterá a cadeia de caracteres "EncodedCommand". Usando essas informações, o comando codificado pode ser ofuscado através do seguinte processo.

Inicie o PowerShell como Administrador. É vital que o PowerShell esteja sendo executado como administrador, caso contrário, nenhum resultado será retornado ao consultar os processos em execução.

Execute o seguinte comando para obter todos os processos do PowerShell que têm um comando codificado:

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

O comando a seguir cria um objeto personalizado do PowerShell que contém a ID do processo e o comando codificado.

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

Agora o comando codificado pode ser decodificado. O trecho a seguir itera sobre o objeto de detalhes do comando, decodifica o comando codificado e adiciona o comando decodificado de volta ao objeto para investigação adicional.

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

O comando decoded agora pode ser revisado selecionando a propriedade decoded command.

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