Skip links

Contournement avancé des EDR : Analyse des syscalls directs et indirects

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èque Kernel32.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.