Compartilhar via


Decodificar um comando do PowerShell por meio de um processo em execução

Este exemplo é executado apenas 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 em execução no contexto de um trabalho do Agendador de Tarefas ou de um trabalho do SQL Server Agent . Quando 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á sendo executado 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 por 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 por meio do processo a seguir.

Inicie o PowerShell como Administrador. É vital que o PowerShell esteja em execução 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 de código 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 posterior.

$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 decodificado agora pode ser revisado selecionando a propriedade de comando decodificada.

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