Compartir a través de


Descodificación de un comando de PowerShell desde un proceso en ejecución

Este ejemplo solo se ejecuta en plataformas Windows.

En ocasiones, es posible que tenga un proceso de PowerShell en ejecución que ocupa una gran cantidad de recursos. Este proceso podría ejecutarse en el contexto de un trabajo del Programador de tareas o de un trabajo del Agente SQL Server . Cuando se ejecutan varios procesos de PowerShell, puede ser difícil saber qué proceso representa el problema. En este artículo se muestra cómo descodificar un bloque de script que se está ejecutando actualmente un proceso de PowerShell.

Creación de un proceso de larga duración

Para demostrar este escenario, abra una nueva ventana de PowerShell y ejecute el código siguiente. Ejecuta un comando de PowerShell que genera un número cada minuto durante 10 minutos.

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

Visualización del proceso

El cuerpo del comando que ejecuta PowerShell se almacena en la propiedad CommandLine de la clase Win32_Process . Si el comando es un comando codificado, la propiedad CommandLine contiene la cadena "EncodedCommand". Con esta información, el comando codificado se puede desuscar mediante el siguiente proceso.

Inicie PowerShell como administrador. Es fundamental que PowerShell se ejecute como administrador; de lo contrario, no se devuelve ningún resultado al consultar los procesos en ejecución.

Ejecute el siguiente comando para obtener todos los procesos de PowerShell que tienen un comando codificado:

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

El comando siguiente crea un objeto de PowerShell personalizado que contiene el identificador de proceso y el comando codificado.

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

Ahora se puede descodificar el comando codificado. El siguiente fragmento de código recorre en iteración el objeto de detalles del comando, descodifica el comando codificado y vuelve a agregar el comando descodificado al objeto para una investigación más detallada.

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

El comando descodificado ahora se puede revisar seleccionando la propiedad de comando descodificada.

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