Introduction
Dans le paysage actuel de la cybersécurité, les solutions de détection et de réponse aux incidents sur les points de terminaison, ou EDR (Endpoint Detection and Response), est une tendance dans la défense des systèmes informatiques contre les menaces avancées. Ces systèmes surveillent les activités suspectes et les comportements malveillants, fournissant une couche essentielle de sécurité pour identifier et contrer les attaques en temps réel. Cependant, l’évolution des technologies de sécurité s’accompagne d’une adaptation des techniques utilisées par les acteurs malveillants pour contourner ces nouvelles mesures de protection.
Une des méthodes sophistiquées employées pour échapper à la détection par les solutions EDR
implique l’utilisation de syscalls directes ou même parfois syscalls indirectes. Cette approche permet aux attaquants de mener des activités malveillantes en dessous du radar des mécanismes traditionnels de surveillance, défiant ainsi les capacités des solutions EDR
à détecter et répondre efficacement aux intrusions.
Cet article vise à déconstruire cette méthode avancée de contournement des EDR
. Nous débuterons par une exploration des pré-requis nécessaires à la compréhension de cette technique, incluant une introduction aux concepts de hooking
, callstack
et syscalls
. Ensuite, nous plongerons dans le cœur du sujet en détaillant comment les appels systèmes peuvent être exécutés au travers ntdll.dll
pour effectuer un bypass efficace des EDR
, tout en analysant les implications et les défis de cette approche. Par la compréhension de ces techniques avancées, les professionnels de la sécurité informatique peuvent mieux anticiper cette stratégie d’attaque.
Pré-requis
Pour comprendre en profondeur la technique de bypass d’EDR
utilisant des syscalls
directs, il est essentiel de se familiariser avec plusieurs concepts clés de la sécurité informatique et de l’architecture des systèmes. Cette section établira les fondements essentiels en matière de syscalls et d’architecture système, nécessaires pour appréhender les techniques avancées de contournement d’EDR que nous examinerons en détail dans la suite de cet article.
Comment fait-on pour créer un processus
Une image vaut mille mots…
Dans le schéma ci-dessus, nous illustrons le processus d’appel système impliqué lors de la création d’un nouveau processus dans un environnement Windows
, du point de vue d’une application malveillante (Malware
) jusqu’à l’exécution en mode noyau (Kernel Land
).
- L’application malveillante initie un appel à la fonction
CreateProcess
fournie par la bibliothèqueKernel32.DLL
dans l’espace utilisateur (User land
). - Ensuite redirigé à travers une fonction intermédiaire,
CreateProcessInternal
. - Le flux se poursuit vers le bas, atteignant la bibliothèque
NTDLL.DLL
.où l’appel àNtCreateUserProcess
est effectué. - Cette derniere étape se charge de faire un
syscall
pour assurer la transition entre l’espace utilisateur et le mode noyau, marquant le passage à un niveau de privilège plus élevé nécessaire pour créer effectivement un processus.
Pile d’appel
La pile d’appel (call stack) est une structure de données utilisée par les programmes pour stocker des informations sur les fonctions actives, comme les adresses de retour et les variables locales.
Concrètement, un appel à une fonction en assembleur se fait à travers l’instruction call
et le retour d’une fonction à travers ret
.
L’instruction call
s’occupe de mettre l’adresse de la prochaine instruction à exécuter après le retour de la fonction, et sautera dans le code de la fonction cible.
Le curseur d’instruction à exécuter continue à avancer.
L’instruction ret
fera la logique inverse en récupérant l’adresse stockée par call
et sautera dans cette adresse.
Hooking
Le hooking est une technique utilisée en programmation et en sécurité informatique pour intercepter et modifier les appels à certaines fonctions ou événements. Dans le contexte de la sécurité, le hooking est souvent employé par les solutions EDR
pour surveiller et analyser le comportement des applications en temps réel. En interceptant les appels système, les lectures et écritures de fichiers, ou encore les connexions réseau, les EDR
peuvent détecter des comportements anormaux ou malveillants.
Concrètement, si nous reprenons notre schéma de tout à l’heure, voici ou la majorité des EDR
vont se mettre à l’écoute.
Une liste des hooks
utilisés par les principaux EDR
sur ce projet github Mr-Un1k0d3r/EDRs.
EDR Bypass
Direct syscalls
Les appels système, ou syscalls
, sont des interfaces fournies par le noyau du système d’exploitation permettant aux programmes de demander des services ou des ressources au niveau du système, comme la création de processus, la lecture de fichiers ou la gestion de la mémoire.
Les applications malveillantes vont donc essayer d’appeler directement le noyau :
Les syscalls
peuvent être appelés trivialement en implémentant le code assembleur ci-dessous :
mov r10, 0 ;premier parametre
mov rdx, 0 ;deuxieme parametre
mov eax, XX ; le numero de l'appel système
syscall ;Appel noyau
Habituellement, dans la convention d’appel Windows
, le premier paramètre d’une fonction est passé via le registre RCX
. Cependant, lors de l’utilisation directe d’un syscall
pour invoquer une fonction du noyau, le premier paramètre doit être passé dans le registre R10
au lieu de RCX
. Cette spécificité est due au fait que le contenu du registre RCX
est modifié lors de l’exécution de l’instruction syscall
.
Une deuxième spécificité, est que le registre eax
devrait contenir l’identifiant du syscall
.
La liste de ces identifiants est activement maintenue sur ce site.
Ces appels système sont détectables à travers une analyse statique du binaire.
Ils sont également détectables par un EDR qui voit qu’une instruction syscall
provient d’un espace mémoire n’appartenant pas à ntdll.dll
.
Lors de l’utilisation de syscalls directs, la pile d’appels présente une anomalie notable : l’exécution du syscall et son retour se produisent dans l’espace mémoire du malware
du processus en cours d’exécution, plutôt que dans la mémoire de ntdll.dll.
Indirect direct syscalls
Pour éviter qu’une instruction provienne de l’espace mémoire de notre process, il suffirait de trouver cette instruction dans l’espace mémoire de ntdll.dll
et l’appeler depuis notre programme.
mov r10, 0 ;premier paramètre
mov rdx, 0 ;deuxième paramètre
mov eax, XX ; le numero de l'appel système
call [ADR_DE_SYSCALL_DANS_NTDLL]
Les syscalls indirects, produisent une pile d’appels qui ressemble davantage à celle d’un processus légitime. Dans ce cas, l’exécution du syscall et l’instruction de retour se déroulent dans la mémoire de ntdll.dll, ce qui est le comportement attendu pour des processus d’application normaux. Cette approche rend la détection plus difficile pour les `qui se basent uniquement sur l’analyse de la zone mémoire d’où proviennent les syscalls et leurs retours.
Se défendre
La connaissance de cette technique sert autant pour les équipes offensives que défensives. Pour une équipe défensive, la simple connaissance de son existence leur permettra d’identifier rapidement les binaires l’utilisant à travers une analyse manuelle du binaire ou moyennant un code basique d’émulation.
Détection par ETW (Event Tracing for Windows) : Les EDR avancés qui utilisent ETW peuvent analyser la pile d’appels complète. Même si les syscalls indirects produisent une pile d’appels plus légitime en apparence, ETW peut encore révéler des anomalies subtiles dans la structure globale de la pile.