Cómo decodificar un comando de PowerShell codificado
- Copia la línea de comandos completa de la alerta, del evento de creación de proceso o de la consola del EDR y pégala en Línea de comandos o Base64. Las comillas alrededor del Base64 no molestan.
- El decodificador encuentra el argumento
-EncodedCommanden cualquiera de sus abreviaturas (-e,-ec,-enc, etc., con-o/) y lo decodifica. - El estado indica qué juego de caracteres se usó: UTF-16LE, como espera PowerShell, o UTF-8 cuando los bytes no parecen UTF-16.
- Lee el Script decodificado. Si contiene literales
[Convert]::FromBase64String('…'), se listan debajo con el tipo detectado y el tamaño. Las cargas de texto se abren en el panel de salida, las comprimidas (gzip, zlib o raw deflate, como las que se usan conGzipStreamyDeflateStream) tienen un botón para descomprimirlas, y las demás cargas binarias se pueden guardar como archivo.
Un ejemplo inofensivo:
powershell.exe -NoP -NonI -W Hidden -Enc VwByAGkAdABlAC0ATwB1AHQAcAB1AHQAIAAnAGgAZQBsAGwAbwAnAA==
se decodifica en Write-Output 'hello'. El mismo texto en Base64 UTF-8 sería V3JpdGUtT3V0cHV0ICdoZWxsbyc=, que PowerShell rechazaría o leería mal.
Reconocer comandos codificados en los logs
Por culpa de UTF-16LE, el inicio de un script codificado tiene una forma Base64 reconocible. Las reglas de detección buscan estas:
| El Base64 empieza por | El script empieza por |
|---|---|
JAB | $ (una asignación de variable; p. ej., JABzAD0A es $s=) |
SQBFAFgA | IEX |
aQBlAHgA | iex |
SQBuAHYAbwBrAGUALQBFAHgAcAByAGUAcwBzAGkAbwBuAA | Invoke-Expression |
SQBuAHYAbwBrAGUALQBXAGUAYgBSAGUAcQB1AGUAcwB0AA | Invoke-WebRequest |
TgBlAHcALQBPAGIAagBlAGMAdAA | New-Object |
WwBDAG8AbgB2AGUAcgB0AF0AOgA6AEYAcgBvAG0AQgBhAHMAZQA2ADQAUwB0AHIAaQBuAGcA | [Convert]::FromBase64String |
Estas formas solo valen justo al principio. Más adentro del script, la misma palabra tiene tres grafías Base64 posibles según su desplazamiento en bytes módulo 3, y por eso buscar en los logs una sola grafía deja escapar las otras dos.
Analizar un comando sospechoso de forma segura
Los comandos codificados son una forma habitual de ocultar un script a quien echa un vistazo rápido a la lista de procesos. Cuando aparece uno en una alerta:
- Solo decodifica. Esta página convierte texto y no puede conectarse a otros servidores. No pegues el comando en una ventana de PowerShell y nunca pases la salida decodificada a
iex. - Lee buscando la intención y los indicadores. Anota URL, dominios, direcciones IP, rutas de archivo, claves del registro y nombres de tareas programadas para tus notas del incidente y tus listas de bloqueo.
- Busca más capas. Las llamadas anidadas a
FromBase64String,IO.Compression.DeflateStreamoGzipStream, los-joinsobre códigos de carácter y la inversión de cadenas son envoltorios habituales. Decodifica cada capa de la misma forma. - Trata los binarios extraídos como muestras. Una carga guardada desde la lista de anidadas puede ser malware. Calcula su hash y analízala solo en un entorno aislado.
- Revisa los logs que ya tienen el texto plano. Con Script Block Logging activado, Windows registra el script decodificado como evento 4104 en
Microsoft-Windows-PowerShell/Operational. Los eventos de creación de proceso (Security 4688 con auditoría de línea de comandos, o el evento 1 de Sysmon) registran la propia línea de comandos codificada.
Usos legítimos y la pestaña de codificación
Los administradores usan -EncodedCommand para evitar problemas de comillas cuando un script pasa por cmd.exe, una tarea programada, una shell remota o una herramienta de gestión de configuración. Codificar script genera el argumento: escribe el script, elige el prefijo en Comando (powershell -NoProfile -EncodedCommand, pwsh -NoProfile -EncodedCommand, powershell -enc o Solo Base64) y copia. Aparece un aviso cuando el resultado supera el límite de 8.191 caracteres por línea de comandos de cmd.exe.
Decodificar en Python y PowerShell
import base64
script = base64.b64decode(b64).decode("utf-16-le")
$script = [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($b64))
Ambos solo devuelven texto. Hay más sobre la parte de la codificación en la página de Base64 en PowerShell y en el convertidor UTF-16 a Base64.
Problemas habituales
- La salida parece texto en chino: es Base64 UTF-8 decodificado como UTF-16. La herramienta recurre a UTF-8 cuando el patrón de bytes no encaja con UTF-16, y la línea de estado indica qué juego de caracteres usó.
- Base64 no válido: el comando se cortó por el límite de un campo de log o se partió en varias líneas. Une los trozos y quita todo lo que vaya después del Base64 y no forme parte de él.
- La línea de comandos no se decodifica en absoluto: puede que el Base64 esté dentro de una cadena
-Command "…FromBase64String('…')…"en lugar de seguir a-EncodedCommand. Pega solo la cadena Base64; si no es texto UTF-16, el decodificador Base64 o Base64 a archivo te muestran qué es.
Preguntas frecuentes
¿Qué hace powershell -enc?
-enc es una forma abreviada de -EncodedCommand. PowerShell decodifica el argumento Base64 como texto UTF-16LE y lo ejecuta como script. También acepta otras abreviaturas, como -e y -ec.
¿Es seguro decodificar aquí un comando de PowerShell malicioso?
Decodificar es una conversión de texto; no se ejecuta nada, y la Content Security Policy de esta página bloquea todas las peticiones de red salvo las del contador de visitas de Cloudflare. Nunca ejecutes el script decodificado para ver qué hace, y maneja las cargas binarias guardadas solo dentro de un entorno de análisis aislado.
¿Por qué en el Base64 hay una A cada dos caracteres?
PowerShell espera UTF-16LE, donde cada carácter ASCII va seguido de un byte cero. Esos bytes cero producen el patrón repetido de A, como en VwByAGkAdABlAC0A para Write-.
¿Cómo decodifico -EncodedCommand sin ejecutarlo en PowerShell?
Usa [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($b64)), que solo devuelve el texto. No pases el resultado por una tubería a Invoke-Expression ni a iex.