DLL Notification List Injection : comment utiliser cette technique pour insérer du code malveillant dans un processus ciblé ?

DLL Notification List Injection : comment utiliser cette technique pour insérer du code malveillant dans un processus ciblé ?
Romain LOISEL
juillet 01, 2024

L‘objectif de cet article est de présenter une technique d’attaque par injection, nommée « DLL Notification List Injection », qui utilise une fonctionnalité Windows nommée « DLL Notification List ». Cette technique permet de forcer un processus signé à exécuter du code malveillant, et de l’exécuter avec le niveau de confiance et les droits du processus signé.

Pour comprendre ce qu’est une DLL notification List injection, il faut tout d’abord comprendre ce qu’est une DLL.

Les DLL sont des bibliothèques de fonctions pouvant être utilisées par d’autres programmes

Les DLL ou « Dynamic Link Libraries » sont des fichiers contenant des fonctions et des codes qui, sous un système d’exploitation Microsoft Windows, peuvent être utilisés par différents programmes.

Les DLL permettent de partager du code réutilisable entre plusieurs applications. Autrement dit, les DLL sont des bibliothèques de fonctions que les programmes peuvent utiliser pour effectuer des tâches spécifiques sans avoir à réécrire ces fonctions à chaque fois dans les programmes.

Contrairement aux SLL « Static Link Libraries » qui sont incluses et compilées avec le programme, les DLL sont chargées de manière dynamique, c’est-à-dire au moment où le programme en a besoin.

Par exemple, le processus explorer.exe, qui gère l’exploration des fichiers Windows, charge et décharge une DLL toutes les 5s environ.

DLL Notification List est une fonctionnalité Windows qui permet d’enregistrer et d’exécuter des fonctions lors du chargement ou déchargement d’une DLL

DLL Notification List est un mécanisme de Windows permettant aux développeurs d’enregistrer et d’exécuter des fonctions au chargement ou déchargement d’une DLL au sein d’un programme.

DLL Notification List se présente sous la forme d’une liste doublement chainée, c’est-à-dire que chaque case de la liste référence à la fois l’adresse de la case suivante, et de la case précédente.

Représentation de la liste doublement chaînée

Pour mieux comprendre ce mécanisme, voici un petit programme en Go, adapté du code C++ de Mor Davidovich. Ce code permet d’ajouter un Callback dans une Notification List.

Code Go permettant de visualiser le mécanisme de DLL Notification List, inspiré du code C++ de Mor Davidovich

Plus précisément, ce programme permet de créer une fonction Callback qui a pour but d’afficher « [MyCallback] DLL loaded : [nom de la DLL] » à chaque chargement de DLL (L54-58).

Puis, il charge la DLL « ntdll.dll » (L25) dans le but de récupérer la fonction permettant d’enregistrer une fonction de « Callback » dans la Notification List (L29 et L33).

Enfin, le programme va charger une DLL « USER32.dll » volontairement afin de déclencher le parcours de la Notification List et d’exécuter la fonction précédemment créée (L46).

Après compilation et exécution du programme Go, nous obtenons bien le comportement attendu avec l’affichage du chargement des différentes DLL, via les appels à la fonction MyCallBack.

Exécution du programme Go

Pourquoi utiliser DLL Notification List pour réaliser une attaque informatique ?

Historiquement, il était possible de réaliser des attaques par chargement de DLL malveillantes. Cependant, la plupart de ces techniques d’injection de DLL dans la mémoire d’un programme sont maintenant détectées par les antivirus et les EDR.

Le mécanisme de DLL Notification List fournit un moyen d’effectuer sensiblement le même type d’attaque.

Nous pouvons donc utiliser la Notification List d’un autre programme connu à l’avance, comme explorer.exe, pour insérer une nouvelle case dans la liste doublement chaînée qui aura pour but d’exécuter une charge malveillante. Dans notre exemple, nous utiliserons ce dispositif pour démarrer la calculatrice de Microsoft Windows.

Comment utiliser DLL Notification List pour faire exécuter du code malveillant ?

Nous avons vu que DLL Notification List permet d’enregistrer une fonction qui sera appelée à chaque chargement de DLL.

Nous allons ainsi créer un programme permettant de réaliser une injection dans la DLL Notification List d’un programme tiers. Pour ce faire nous allons nous inspirer et reprendre le code C++ de Mor Davidovich (Shorsec).

Avant toute chose, il faut d’abord récupérer l’adresse mémoire de la première case de la Notification List du programme dans lequel on souhaite effectuer une injection. Pour ce faire, nous allons définir une fonction de callback vide.

Création de la fonction Callback vide (extrait du code C++ de Mor Davidovich)

Ceci nous permet par la suite d’enregistrer notre « DummyCallback » et de récupérer un pointeur sur l’adresse de la première case de la liste. Une fois l’adresse récupérée, nous pouvons retirer la fonction « DummyCallback » pour la suite.

Utilisation du DummyCallBack pour récupérer un pointeur vers l’adresse de la première case de la liste, puis retrait du DummyCallback (extrait du code C++ de Mor Davidovich)

Note : pour utiliser la fonctionnalité de DLL Notification List, chaque processus charge la même DLL « ntdll.dll ». Dans ce cadre, l’adresse de la première case de la Notification List sera au même emplacement mémoire pour tous les processus chargeant ntdll.dll. Ainsi si nous savons où se trouve cet emplacement au sein d’un programme que nous maîtrisons, nous pourrons utiliser la même adresse mémoire lors d’une attaque avec un autre processus.

Maintenant que nous avons l’adresse mémoire de la première case de la liste DLL Notification, nous devons récupérer le « handle » du processus que nous souhaitons cibler. Le « handle » est un mécanisme Windows utilisé pour identifier différents processus et d’interagir directement avec eux notamment pour gérer les ressources ou l’espace mémoire.

Dans notre programme nous allons demander à l’utilisateur d’entrer le nom du processus à cibler puis nous allons récupérer le « handle » de ce processus.

Code C++ de Mor Davidovich, qui permet de récupérer le handle d’un processus à partir de son nom

Maintenant que nous avons le « handle » du processus ciblé ainsi que l’emplacement mémoire de la première case de la DLL Notification List, nous pouvons parcourir la liste et afficher les éléments qu’elle contient.

Nous pouvons alors également préparer notre injection de code. L’objectif est d’insérer un callback malveillant dans la chaîne DLL Notification List.

Pour cela, nous allons insérer le code malveillant entre la première case et la deuxième case de la DLL Notification List. Dans une liste doublement chaînée, il faut pour cela créer une case dans la liste, référencer les cases 1 et 2, puis supprimer les anciens liens et les faire pointer vers la nouvelle case insérer.

Représentation du processus d’injection du code malveillant dans la DLL Notification List

Nous pouvons alors utiliser le code suivant :

Insertion du code malveillant dans la DLL Notification List
Suppression des anciens liens entre les cases 1 et 2 de la DLL Notification List, afin d’appeler directement notre code malveillant

Le programme rédigé permet ainsi d’insérer du code malveillant directement via la DLL Notification List d’un programme tiers. Ici, cela provoque l’ouverture de la calculatrice Windows.

Démonstration du résultat obtenu

Pourquoi les injections de DLL dans la DLL Notification List sont à surveiller ?

Comme dit précédemment, les antivirus et EDR modernes bloquent les attaques d’injections de DLL classiques. Cependant, la méthode présentée ici utilise une fonctionnalité légitime du point de vue système, qui permet de camoufler ce type d’attaque auprès de certains EDR. Ceci est particulièrement vrai lorsque l’on cible des processus systèmes qui ouvrent beaucoup de DLL.

De plus, si cette attaque est effectuée en ciblant un processus qui dispose de plus de droits, il est possible que le code malveillant lancé grâce à cette attaque dispose des mêmes droits que le processus ciblé, générant ainsi une élévation de privilèges.

Notons que l’exploitation de cette méthode d’attaque nécessite de bien préparer le code malveillant, car si celui-ci n’est pas camouflé ou chiffré, l’injection dans la DLL Notification List génère immédiatement une alerte sur les EDR modernes.

Pour aller plus loin

Les personnes qui souhaitent étudier davantage cette méthode d’attaque peuvent consulter l’article de Mor Davidovich sur https://shorsec.io/blog/dll-notification-injection/ et le code malveillant de Sektor7 sur https://institute.sektor7.net/, ou encore le code rédigé pour ce projet sur https://github.com/Darkiros/DLL_Notification_injection.

Vous avez des questions ?

Vous souhaitez une démonstration ?

Contactez-nous et nos experts reviendront vers vous sous 24h.

Votre demande