Dans un monde de plus en plus connecté, les entreprises sont de plus en plus exposées aux risques d’attaques informatiques. Pour se protéger contre ces menaces, de nombreuses entreprises utilisent des solutions de sécurité telles que les antivirus et les EDR (Endpoint Detection and Response). Ces outils ont pour but de protéger les collaborateurs des menaces informatiques en assurant différents types d’analyses techniques.
Cependant, comme toutes technologies, ces solutions de sécurité peuvent être contournées. Les pirates informatiques sont constamment à la recherche de nouvelles techniques d’attaques, et les entreprises doivent être prêtes à faire face à ces menaces.
Découvrez dans cet article les différents mécanismes de sécurité, leurs limites et comment elles peuvent être contournées.
Plusieurs techniques existent pour détecter et prévenir les menaces de sécurité informatique. Parmi les plus courantes on retrouve l’analyse statique, l’analyse dynamique ou encore l’analyse comportementale. Ces techniques visent à identifier et éviter toute attaque informatique qui pourrait nuire à la sécurité d’une entreprise. Le diagramme ci-dessous présente ces trois analyses que nous détaillerons plus bas.
L’analyse statique est l’analyse la plus courant proposée par les moteurs antivirus, consistant à examiner le code d’un fichier pour détecter des signaux malicieux sans exécuter le fichier.
Comment ? En utilisant des algorithmes de détection de menace pour rechercher des éléments dans le code qui seraient malveillants. Par exemple, si un malware est détecté, l’analyse statique peut informer l’utilisateur et lui fournir des options pour supprimer le fichier infecté manuellement ou automatiquement.
Cette approche est considérée comme plus sûre que l’analyse dynamique, qui quant à elle consiste à exécuter le fichier suspect sur un système puis observer son comportement. Nous aborderons cette notion plus bas.
L’analyse statique fonctionne par un mécanisme de comparaison entre une base de données virale contenant des IOC (Indicateurs de Compromission) et des hash ou des adresses IP détectées dans un binaire. Ce n’est qu’après le téléchargement ou lorsque le fichier est exécuté que l’analyse commence…
Par définition, un hash est une valeur numérique unique qui est associée à un fichier. Les analyses antivirus utilisent des hash afin d’identifier les fichiers reconnus comme malveillants.
Par exemple, si un fichier a le même hash qu’un fichier connu comme malveillant, il est considéré comme suspect et peut être bloqué ou supprimé.
Par ailleurs, les analyses antivirus vont utiliser les adresses IP pour vérifier si un fichier est téléchargé depuis une source connue comme malveillante. A titre d’illustration, si un fichier est téléchargé depuis une adresse IP connue comme malveillante, il est considéré comme suspect et peut être bloqué ou supprimé.
L’analyse statique avec une base de données d’IOC consiste à utiliser ces informations pour détecter les menaces potentielles sans exécuter le fichier suspect. Les informations sur les hash et les adresses IP peuvent être mises à jour en temps réel pour refléter les nouvelles menaces et les mises à jour de sécurité, c’est pourquoi il est important de garder sa solution antivirus à jour. Par exemple, si le programme tente de communiquer avec C&C (Command & Control) connu, il estimera que ce programme est une copie d’un autre virus connu en base de données.
Les attaquants peuvent utiliser des méthodes d’obfuscation pour camoufler leur programme malveillant et contourner l’analyse antivirus.
L’obfuscation est une technique utilisée par les développeurs de programmes malveillants pour masquer leur code et échapper à la détection des antivirus. L’obfuscation va rendre le code difficile à comprendre.
Comment ? En utilisant des techniques telles que le brouillage de noms de variables, la modification de la structure du code et l’utilisation de méthodes chiffrées.
L’analyse statique peut être contournée par l’obfuscation car le code obfusqué est difficile à analyser pour détecter les indicateurs de compromission. Cependant, les analyses antivirus modernes utilisent des techniques avancées pour détecter les menaces obfusquées, telles que l’analyse de décompilation pour récupérer le code source original ou encore l’utilisation d’algorithmes de reconnaissance de motifs pour rechercher des signatures de malware connues.
En fin de compte, l’obfuscation peut rendre l’analyse statique bien plus difficile. Elle ne garantit pas l’échappatoire à la détection par les outils de sécurité, notamment lorsque le programme malveillant se lance, il déchiffre à ce moment-là toute ou une partie du code et laisse transparaître des IOC.
L’analyse dynamique proposée par les moteurs d’antivirus modernes consiste à exécuter le fichier suspect sur un système (appelé ‘sandbox’) pour détecter les menaces potentielles.
Comment ? En utilisant des techniques d’observation et de suivi pour surveiller le comportement du fichier pendant son exécution. Si un comportement malveillant est détecté, l’analyse dynamique peut informer l’utilisateur et lui fournir des options pour supprimer le fichier infecté.
Cette approche est considérée plus efficace que l’analyse statique pour détecter les nouvelles et les menaces émergentes, mais elle est considérée comme moins sûre car elle nécessite l’exécution du fichier suspect sur un système.
L’analyse dynamique reprend les mêmes concepts que l’analyse statique, mais seulement en exécutant le binaire dans une machine virtuelle spécifiquement dédiée.
L’avantage majeur est que le binaire vérolé, précédemment non détecté en analyse statique, doit se révéler (déchiffrement loader ou autre) pour pouvoir être exécuté. C’est à ce moment précis que la sandbox peut analyser les communications (adresses IP, etc.) et les différents changements (registres, processus mémoire, etc.)
via sa base donnée d’indicateurs. Si de tels indicateurs semblent corroborer alors l’antivirus pourra prendre une décision en la mise en quarantaine, de tuer le processus cible et/ou de supprimer le fichier en question.
Cette technique se base donc sur le comportement du programme malveillant.
Bien que l’analyse dynamique soit plus précise que l’analyse statique, elle peut être contournée facilement par les virus émergeants. Ces derniers vont effectuer des vérifications avant de se lancer pour savoir s’ils sont dans une sandbox et ainsi s’arrêter automatiquement pour éviter leur analyse.
Il existe plusieurs moyens de contourner l’analyse dynamique, mais il est important de noter que les attaquants cherchent constamment à trouver de nouvelles méthodes pour échapper à la détection.
Les moyens couramment utilisés pour contourner l’analyse dynamique incluent :
La détection de la résolution de nom de domaine : les attaquants peuvent vérifier si leurs requêtes DNS sont résolues à des adresses connues comme appartenant à des environnements de simulation pour une analyse dynamique.
La détection des ressources système : les attaquants peuvent vérifier si des ressources système telles que les processeurs, la mémoire et les disques sont limités, ce qui peut être un indicateur d’un environnement de simulation pour une analyse dynamique.
La détection de l’environnement de fichier : les attaquants peuvent vérifier si des dossiers et des fichiers qui ne sont habituellement pas présents sur un système sont présents, ce qui peut indiquer un environnement de simulation pour une analyse dynamique (fichiers temporaires de navigation Firefox, Word, etc.).
La détection de l’interface réseau : les attaquants peuvent vérifier si les informations sur l’interface réseau sont différentes de celles d’un environnement normal, ce qui peut indiquer un environnement de simulation pour une analyse dynamique (carte réseau virtualisée, ou autre).
Gonfler la taille du binaire pour échapper à son analyse (qui surchargerait aussi le réseau), de détecter la présence de certaines fonctionnalités qui ne peuvent être virtualisées ou encore certaines valeurs de temps ou autre…
Ces quelques exemples démontrent que les attaquants peuvent utiliser des techniques très variées pour détecter un environnement de simulation pour une analyse dynamique et s’échapper à la détection. C’est pourquoi l’analyse basée sur le comportement fait surface avec l’apparition des technologies appelées EDR.
L’EDR (Endpoint Detection and Response) est une technologie de sécurité qui se concentre sur l’analyse comportementale. L’EDR surveille en temps réel les activités sur les terminaux pour détecter les comportements malveillants et les menaces avancées.
En cas de menace détectée, l’EDR peut utiliser une action automatisée afin d’empêcher la diffusion de la menace et fournir des informations détaillées sur la menace pour aider les équipes de sécurité à investiguer et à résoudre le problème.
Les fonctionnalités de l’EDR incluent :
La détection en temps réel
La réponse automatisée
La collecte de données
L’analyse de sécurité.
L’analyse comportementale consiste à surveiller les comportements des programmes en temps réel pour détecter les anomalies qui peuvent indiquer une activité malveillante. Contrairement à l’analyse statique, qui examine le code source d’un programme, l’analyse comportementale se concentre sur les actions effectuées par un programme lorsqu’il est exécuté directement sur un système.
Fréquemment, les virus cherchent à charger les fichiers NTDLL.DLL et KERNEL32.DLL, car ce sont des bibliothèques système fondamentales qui fournissent des fonctionnalités de base pour les programmes exécutés sur un ordinateur Windows.
En chargeant ces bibliothèques, les virus peuvent accéder à un large éventail de fonctionnalités système, telles que la gestion des processus, des fichiers et des réseaux, ce qui leur permet de masquer leur activité et de se propager davantage. Par conséquent, la surveillance de l’accès à ces bibliothèques peut être un indicateur de l’existence d’une activité malveillante.
Lorsqu’un EDR effectue une analyse comportementale, il peut surveiller les programmes pour savoir s’ils cherchent à charger NTDLL.DLL et KERNEL32.DLL, et si oui, comment ils les utilisent. Si le logiciel détecte une utilisation anormale de ces bibliothèques, cela peut indiquer l’existence d’un virus ou d’une autre menace, et le logiciel peut alors décider de bloquer l’exécution du programme ou d’alerter l’utilisateur. Pour cela l’EDR utilise le hooking dynamique de NTDLL.DLL par exemple, pour surveiller les activités sur un système Windows. Le hooking quesaco ? Le hooking consiste à remplacer une fonction dans NTDLL.DLL avec une version modifiée qui effectue des actions supplémentaires lorsque la fonction est appelée.
Lorsqu’un EDR utilise le hooking de NTDLL.DLL, il intercepte les appels aux fonctions système fournies par cette bibliothèque et les analyse pour détecter les activités malveillantes. Par exemple, l’EDR peut surveiller les appels à la fonction de création de processus pour détecter les tentatives de lancement de programmes malveillants.
En utilisant le hooking de NTDLL.DLL, l’EDR peut effectuer une analyse en temps réel des activités sur un système d’exploitation Windows et fournir une défense proactive contre les programmes malveillants.
Pour illustrer notre propos, voici un exemple de hooking dynamique de ntdll.dll par un EDR :
L’EDR installe un hook sur la fonction NtCreateFile de NTDLL. Cette fonction est appelée lorsque le système d’exploitation Windows ouvre un fichier ou un répertoire.
Lorsqu’une application tente d’ouvrir un fichier, elle appelle la fonction NtCreateFile de NTDLL.
Au lieu d’utiliser la fonction NtCreateFile originale de NTDLL, l’EDR utilise la version modifiée qu’il a installée précédemment.
L’EDR analyse les arguments passés à la fonction NtCreateFile pour déterminer si l’application tente d’ouvrir un fichier malveillant. Si tel est le cas, l’EDR peut bloquer l’ouverture du fichier et envoyer une notification d’alerte.
Si l’application tente d’ouvrir un fichier légitime, l’EDR exécute la fonction NtCreateFile originale de NTDLL pour permettre à l’application d’ouvrir le fichier comme prévu.
Cet exemple montre comment un EDR peut utiliser le hooking dynamique de NTDLL pour surveiller les activités de fichier sur un système d’exploitation Windows et bloquer les activités malveillantes. Cette technique permet à l’EDR de fournir une défense proactive contre les programmes malveillants sans affecter le fonctionnement normal du système d’exploitation.
Lorsqu’un virus est exécuté sur un système, il utilise la fonction VirtualAlloc pour allouer de la mémoire. Cela permet au virus d’avoir accès à une zone mémoire protégée où il peut déchiffrer sa charge utile en toute sécurité.
Le virus déchiffre sa charge utile en utilisant la fonction WriteProcessMemory. Cela permet au virus de déchiffrer sa charge utile directement dans l’espace mémoire alloué sans l’écrire sur le disque dur, ce qui peut attirer l’attention des solutions de sécurité.
Une fois que le code est déchiffré, le virus utilise la fonction CreateThread pour exécuter le nouveau code dans l’espace mémoire alloué. Cela permet au virus de s’exécuter dans une zone mémoire protégée et donc d’éviter les détections des solutions de sécurité.
Séquence d’actions caractéristiques : les trois étapes décrites ci-dessus sont souvent considérées comme une séquence d’actions caractéristique des programmes malveillants.
Les solutions EDR peuvent utiliser des hooks pour détecter cette séquence d’actions et arrêter le virus avant qu’il ne puisse s’exécuter sur le système. Les hooks peuvent également détecter l’utilisation des fonctions VirtualAlloc, WriteProcessMemory et CreateThread et bloquer l’exécution du virus.
NTDLL / KERNEL32 est une bibliothèque de fonctions système qui fournit des fonctions d’interface avec le noyau du système d’exploitation. NtAllocateVirtualMemory / VirtualAlloc est une fonction de ntdll.dll qui permet d’allouer de la mémoire virtuelle dans le système d’exploitation.
La différence entre VirtualAlloc et NtAllocateVirtualMemory réside dans les fonctionnalités qu’ils fournissent et la façon dont ils sont implémentés. VirtualAlloc est destiné à être utilisé par les applications Windows, tandis que NtAllocateVirtualMemory est destiné à être utilisé par les fonctions système Windows internes. NtAllocateVirtualMemory fournit des fonctionnalités plus avancées et plus flexibles que VirtualAlloc, mais est généralement plus complexe à utiliser.
L’EDR va placer son hook dans NTDLL au moment où le processus entre en mémoire. Cela lui permet de surveiller les actions du processus dès son lancement et de détecter tout comportement malveillant potentiel.
Le hook va remplacer la fonction cible par une fonction personnalisée qui peut surveiller ou modifier les entrées et sorties de la fonction originale. Lorsque le processus va appeler la fonction cible, le hook intercepte l’appel et exécute du code personnalisé avant ou après l’exécution de la fonction originale.
La première chose pour contourner le hooking EDR est d’avoir une version ‘propre’ de NTDLL, la technique consiste à la lire directement à partir du disque dur, sans la charger en mémoire. Cela peut être utile pour s’assurer que la version de ntdll.dll utilisée n’a pas été modifiée par un EDR. NTDLL est seulement modifiée quand l’EDR est chargé dans le processus.
Pour avoir un copie toute neuve de NTDLL, on peut voir ces modèles :
Lire NTDLL directement à partir du disque peut être une bonne technique, car on sait que ntdll.dll n’est généralement pas modifié avant que l’EDR ne place son hook en mémoire. On peut aller directement à son emplacement d’origine sur le disque et le charger dans notre processus, puis le réécrire pour remplacer la version modifiée de ntdll.dll en mémoire.
Démarrer un processus dans un état suspendu et copier NTDLL de là peut aussi être une bonne technique pour éviter que l’EDR ne place ses hooks dans le nouveau processus. En effet, l’EDR n’installe ses hooks que lors de certaines étapes d’exécution, et en démarrant le processus en état suspendu, nous pouvons copier ntdll.dll avant qu’il ne soit modifié.
Attention cependant, accéder à NTDLL à partir du disque est souvent détecté par les EDR, car c’est une technique dîtes ‘classique’ pour bypasser les hooks. De même pour les appels APIs qui viennent réécrire ntdll.dll, car ces mêmes appels sont déjà hookés au préalable (résident dans un hook NTDLL). En soit, faire appel à NTDLL est un indicateur suspect pour les EDR qui surveillent de près les commandes associées.
Cette technique consiste à enlever les hooks du processus en communiquant directement avec le noyau sans passer par NTDLL. C’est une des techniques les plus couramment utilisées ces dernières années par les loaders. Pour cela, nous implémentons nos propres appels système dans notre virus. Pour effectuer ces syscalls, nous avons besoin d’un paramètre appelé numéro de service système (SSN). Cela nous permet d’identifier quel appel système nous utilisons. Ici, le nombre 18 fera référence à NTAllocateVirtualMemory.
SysWhispers2 est une technique utilisée pour obtenir le numéro de service système (SSN), un paramètre nécessaire pour effectuer des appels système personnalisés dans un virus. Cette technique est souvent utilisée pour contourner les hooks du processus en communiquant directement avec le noyau sans passer par NTDLL.
Voici un exemple de code en Go qui montre comment effectuer un syscall en utilisant la bibliothèque “unsafe” pour accéder à l’interface nécessaire du noyau:
Dans ce code, nous appelons la fonction syscall.Syscall en passant en premier paramètre le numéro de service système (SYS_WRITE), puis les arguments fd, buf et count. Le syscall écrit “Hello World\n” dans la sortie standard.
Le problème avec cette technique est que le numéro SSN varie en fonction de la version de Windows. Si nous connaissons à l’avance la version exacte, nous pouvons durcir le code de l’appel système avec le numéro SSN correspondant. Cependant, le problème est que nous ne savons jamais exactement avec quoi s’exécute le virus. Il est toujours possible de trouver ce numéro de manière dynamique en utilisant la fonction NTDLL qui n’est pas hookée.
Une autre technique s’appelle “l’instruction syscall”. Elle permet de changer notre contexte et d’interagir directement avec le noyau une fois que le bon numéro de service système (SSN) est spécifié. Cependant, il y a également un problème avec cette technique.
Avoir des syscalls en instructions assembleur compilées dans un exécutable n’est pas commun et peut-être désigné suspect / malicieux par un EDR.
En utilisant directement l’instruction syscall dans notre malware, nous pourrions être détectés par l’analyse statique de l’EDR simplement s’il voit l’instruction syscall. Cependant, en créant un loader et en injectant notre charge utile dans un thread, nous ne désactiverons pas notre processus, ce qui signifie que seul le chargeur pourra contourner l’EDR, mais tout ce qui se passera par la suite sera détecté par l’EDR (communication C2C).
Au lieu d’appeler directement SYSCALL, nous pouvons trouver le numéro de service système (SSN) de manière dynamique et sauter vers une instruction système trouvée dans NTDLL. Un appel système via NTDLL plutôt que directement à partir de notre virus, ainsi, nous ne serons pas détectés par l’analyse statique de l’EDR. L’instruction sera appelée à partir de NTDLL après que les hooks aient été mis en place. Pour rappel, passer par NTDLL est la façon dont Windows fonctionne.
Les deux premières analyses sont réalisées par les logiciels d’antivirus. La première va simplement regarder le fichier dans sa composition pour déterminer s’il est malveillant ou non par rapport à sa base de données. La seconde va lancer l’analyse dans une sandbox (machine virtuelle) pour révéler des informations que l’analyse statique ne peut pas détecter. Enfin, la troisième n’est possible qu’avec la technologie EDR (qui lui combine aussi les 2 premières également) et laisse le programme s’exécuter sur l’ordinateur et l’arrêtera juste à temps si un comportement est considéré malveillant.
Avoir une protection maximale, c’est d’abord avoir une bonne hygiene informatique. Toute technologie a ses faiblesses et les éditeurs de protection sont à l’affut pour couvrir les nouvelles menaces émergeantes. C’est une course sans fin…
Quick Links
Legal Stuff