Hunting des Living-off-the-Land Binaries sous Windows avec KQL
Requetes KQL pretes pour Microsoft Defender et Sentinel afin de traquer l'abus de LOLBins comme rundll32, mshta et certutil en environnement reel.

Dans cet article
Un attaquant competent n'a pas besoin de deposer son propre binaire sur le disque de la victime: il utilise ce qui est deja la. Rundll32, mshta, certutil, bitsadmin et regsvr32 sont des outils legitimes signes par Microsoft, ce qui pousse beaucoup d'EDR a traiter leurs executions comme du bruit. Cette technique s'appelle Living off the Land, les binaires eux-memes des LOLBins, catalogues dans le projet public LOLBAS. L'equipe Basilisk a passe les six derniers mois a analyser 47 incidents, et 31 comportaient au moins un LOLBin dans la kill chain. Ce billet livre les requetes KQL que l'on execute dans Microsoft Defender for Endpoint et Sentinel pour transformer ces executions en detections actionnables sans noyer le SOC de faux positifs.
Ce que sont les LOLBins et pourquoi ils passent#
Un LOLBin est un programme preinstalle et signe qui porte une fonction secondaire non prevue et utile a l'attaquant: telechargement, execution de code, persistance ou contournement de l'application control. Comme la signature vient de Microsoft, les allowlists naives ne declenchent pas, et un simple nom de processus comme indicateur ne vaut rien. La detection glisse donc de quel binaire vers quelle ligne de commande, quel processus parent, quel comportement en aval. C'est exactement pourquoi la ligne de commande du processus (ProcessCommandLine) est le champ le plus important de toute requete de hunting, suivi de InitiatingProcessFileName et des connexions reseau du meme processus.
Comprendre d'abord la baseline#
Avant d'ecrire la moindre regle, il faut comprendre la baseline de l'environnement. On lance un hunt large sur DeviceProcessEvents en groupant par FileName et en comptant les executions sur 30 jours par hote, pour cerner le normal de la flotte. Chez un client de 8 200 endpoints, mshta.exe n'apparaissait que sur 0,4% des machines, toutes au marketing pour un rapport legacy. Toute execution de mshta hors de ce groupe merite donc une alerte P2. Cette approche de rarete statistique est le socle du hunting moderne et rejoint Threat Hunting avec Sigma et Elastic: De l'Indicateur a la Regle de Detection, ou l'on passe de l'indicateur brut a la regle Sigma versionnee dans Git.
Rundll32 avec une ligne de commande suspecte#
La requete de base recommandee pour rundll32 est: DeviceProcessEvents | where FileName =~ 'rundll32.exe' | where ProcessCommandLine has_any ('javascript:', 'shell32.dll,Control_RunDLL', 'mshtml,RunHTMLApplication', '.cpl,', 'url.dll,OpenURL') | where InitiatingProcessFileName !in~ ('explorer.exe', 'svchost.exe') | project Timestamp, DeviceName, AccountName, ProcessCommandLine, InitiatingProcessFileName. Testee contre la technique T1218.011 de MITRE ATT&CK, elle a capture 9 des 10 executions du beacon Cobalt Strike en mode SMB pivot. Le reglage fin vient de l'exclusion des processus parents legitimes par departement, ce que l'on documente dans Adversary Emulation avec Caldera et MITRE ATT&CK en Lab d'Entreprise. Surveille particulierement rundll32 sans argument de DLL, signe fort de process hollowing.
Certutil: le couteau suisse#
Certutil merite son propre chapitre. Il telecharge des fichiers (-urlcache), decode du base64 (-decode) et calcule des hashes. Notre requete de chasse est: DeviceProcessEvents | where FileName =~ 'certutil.exe' | where ProcessCommandLine has_any ('-urlcache', '-decode', '-decodehex', '-ping', 'http://', 'https://') | where ProcessCommandLine !contains 'CertificateServices' | extend Stage = case(ProcessCommandLine has '-decode', 'staging', ProcessCommandLine has 'http', 'download', 'recon'). En 2025 on a vu certutil servir de seconde etape dans des campagnes demarrant par du phishing macro, un flux decrit cote offensif dans Initial Access Simule: Macros, LNK et ISO dans un Lab Windows 11 Isole que les blue teams doivent correler a l'evenement AD 4688.
Mshta et regsvr32: scriptlets distants#
Pour mshta et regsvr32 (T1218.010) la logique change. Mshta executant une URL est presque toujours malveillant hors systemes d'aide: DeviceProcessEvents | where FileName =~ 'mshta.exe' | where ProcessCommandLine has_any ('http://','https://','.hta','javascript:','vbscript:') donne un taux de faux positifs sous 2% dans la plupart des flottes. Regsvr32 avec /i: et une URL (la technique Squiblydoo) se capture pareil via ProcessCommandLine has_any ('/i:http','scrobj.dll'). Les deux profitent enormement de la correlation avec la couche reseau, car un appel localement anodin devient une vraie alerte via une connexion sortante.
Correlation multi-tables avec le reseau#
Combine la trouvaille de processus avec DeviceNetworkEvents dans la meme fenetre de 60 secondes via un join sur DeviceId et l'ID de processus, pour confirmer que la connexion venait bien du processus suspect: DeviceProcessEvents | where FileName =~ 'mshta.exe' | join kind=inner (DeviceNetworkEvents) on DeviceId, InitiatingProcessId | where NetworkTimestamp between (Timestamp .. Timestamp + 60s). Ce type de correlation multi-tables separe le hunting du simple log mining et se connecte a Mouvement Lateral en Lab: SMB, WMI et WinRM avec Focus Detection, ou les attaquants chainent les LOLBins via WMI distant et la vue reseau fournit le contexte decisif.
Le trio: bitsadmin, msiexec et wmic#
Bitsadmin, msiexec /i http et wmic distant forment le trio qui echappe le plus souvent aux regles par defaut. Pour msiexec, notre heuristique preferee utilise ProcessVersionInfoOriginalFileName pour detecter les binaires renommes, ce que des outils comme Sliver font par defaut: where FileName =~ 'msiexec.exe' and ProcessVersionInfoOriginalFileName !~ 'msiexec.exe'. Vois la perspective operateur dans Construire une Infra C2 avec Sliver en Lab Isole pour la Recherche Defensive. Capture bitsadmin via ProcessCommandLine has_any ('/transfer','/create','/addfile'), et wmic via process call create et /node: pour l'execution distante.
PowerShell et commandes encodees comme voisins#
Les LOLBins apparaissent rarement seuls; le plus souvent une etape PowerShell est juste a cote. Chasse les commandes encodees avec DeviceProcessEvents | where FileName in~ ('powershell.exe','pwsh.exe') | where ProcessCommandLine has_any ('-enc','-EncodedCommand','-e ','FromBase64String','IEX','Invoke-Expression','-w hidden','-nop'). La vraie mine d'or reste le module logging: active la telemetrie ScriptBlock (evenement 4104) via DeviceEvents et cherche-y le payload en clair que -enc cache sur la ligne de commande. Un rundll32 ou mshta dont le parent est un PowerShell encode est un loader de beacon quasi certain et merite une severite haute immediate plutot qu'un archivage silencieux.
Correler le drop de payload via DeviceFileEvents#
Un telechargement certutil sans le fichier qu'il ecrit ensuite n'est que la moitie de l'histoire. Joins l'execution avec DeviceFileEvents pour voir le payload reellement depose: fais un join sur DeviceId et InitiatingProcessId et filtre les evenements FileCreated recents dans %TEMP%, %APPDATA% ou C:\Users\Public. Enrichis le hit avec le SHA256 du fichier et confronte-le a tes sources de threat intel; un executable non signe fraichement ecrit par un LOLBin est une trouvaille qui justifie d'isoler l'hote. C'est exactement cette chaine processus, reseau et fichier qui transforme un indicateur faible en une histoire solide pour le rapport d'incident.
Operationnaliser dans Sentinel et Sigma#
Dans Sentinel, on materialise ces hunts en Analytics Rules avec entity mapping sur Account et Host, frequence de 5 minutes et suppression d'1 heure par entite, ce qui garde le bruit maitrisable. Chaque regle recoit un tag tactique/technique MITRE pour rendre la couverture mesurable. On exporte toujours la logique vers Sigma pour la portabilite SIEM, la meme philosophie que dans Purple Team en Pratique: Construire une Boucle de Feedback Red vs Blue. Ainsi la meme detection tourne que le client soit sur Defender, Elastic ou Splunk, et la red team la valide directement contre des attaques emulees.
Apprivoiser les faux positifs et pieges#
L'erreur la plus frequente est de vouloir eliminer les LOLBins; ils font partie de l'OS et sont utilises legitimement. SCCM appelle msiexec en routine, la distribution logicielle utilise bitsadmin, les jobs de sauvegarde lancent certutil pour le hashing. Regle par processus parent et contexte, jamais par binaire seul. Autre piege: has contre contains en KQL; has est tokenise et plus rapide mais ne matche pas les sous-chaines, ce qui laisse des trous sur des lignes de commande concatenees. Mesure le taux de faux positifs de chaque regle avant de l'armer et documente chaque exception avec justification.
Checklist#
Avant de deployer toute regle LOLBin: (1) baseline collectee sur au moins 30 jours; (2) filtre sur ProcessCommandLine, pas seulement FileName; (3) exclusions de processus parent documentees par departement; (4) correlation reseau la ou c'est pertinent; (5) binaires renommes couverts via OriginalFileName; (6) tag MITRE pose; (7) suppression par entite configuree; (8) exporte vers Sigma; (9) valide contre une attaque emulee; (10) taux de faux positifs mesure et sous seuil.
FAQ#
Bloquer les LOLBins via WDAC suffit-il? Rarement, car beaucoup sont critiques pour le metier; mieux vaut bloquer les invocations dangereuses (comme certutil -urlcache) plus la detection. Pourquoi ne pas alerter chaque telechargement certutil? Dans les grands environnements cela produit des centaines de hits quotidiens d'automatisation legitime; seule la combinaison d'un processus parent rare, d'une URL externe et d'un fichier cible non signe rend l'alerte fiable. Faut-il le P1 pour ces tables? DeviceProcessEvents et DeviceNetworkEvents relevent de Defender for Endpoint P2, et arrivent dans Sentinel via le data connector.
Comment gerer les LOLBins de persistance? schtasks.exe et sc.exe sont eux-memes des LOLBins quand ils creent des taches ou des services pointant vers un script ou un chemin inhabituel. Chasse-les avec DeviceProcessEvents | where FileName in~ ('schtasks.exe','sc.exe') | where ProcessCommandLine has_any ('/create','create','binPath=') | where ProcessCommandLine has_any ('powershell','cmd /c','\Users\','\Temp\','http'). Et si l'attaquant renomme le binaire? C'est pourquoi tu ne filtres jamais sur FileName seul; la combinaison de ProcessVersionInfoOriginalFileName, de la signature de ligne de commande et du processus parent survit au renommage, alors qu'un filtre de nom seul devient aveugle.
Pour finir, du concret: lance ceci dans ton tenant aujourd'hui: DeviceProcessEvents | where Timestamp > ago(30d) | where FileName in~ ('rundll32.exe','mshta.exe','certutil.exe','regsvr32.exe','bitsadmin.exe','msiexec.exe') | summarize Total=count(), Hosts=dcount(DeviceName) by FileName, bin(Timestamp, 1d) | order by Timestamp desc. La sortie est ta carte de baseline. Tout ce qui casse ce schema de 3 ecarts-types devient candidat a une regle. Tu n'elimines pas un LOLBin, tu l'observes avec discipline, et les equipes qui traitent la baseline comme un produit vivant detectent les intrusions en heures plutot qu'en mois.


