Introduction à l'injection de processus

L'injection de processus sous Windows est un sujet de recherche fabuleux compte tenu de la vastité de cet OS. Au sein de ce chapitre nous verrons quelles sont les différents types d'injection, comment les POCer et comment les détecter sur un système hôte.

Mais avant de plonger dans ce fabuleux monde il m'a paru nécessaire de faire une petite introduction afin de rappeler quelques notions qui me semblent importantes.

I/ Thread vs processus

La première notion à connaître sur le bout des doigts c'est la différence entre un processus et un thread. Un processus c'est un exécutable que l'on a mappé en mémoire entendez par là qu'on lui  a attribué un espace mémoire afin que ce dernier puisse fonctionner. Au sein de cet espace mémoire sont stockées les variables (initialisées ou non) mais aussi le code (les instructions) de notre programme. Ce mappage est réalisé par le kernel.

On pourrait résumer ce qu'est un processus en disant que c'est une instance d'un programme. Chaque processus dispose de son propre espace mémoire. Autrement dit si on lance l'exécutable test.exe deux fois, deux espaces mémoires différents seront allouées.

Chaque processus dispose d'au moins un thread qui est en fait le fil d'instructions de notre programme. Un processus peut avoir plusieurs threads et tous ces thread partagent le même espace mémoire:

C'est d'ailleurs parce que les threads se partagent un espace mémoire identique que des problématiques d'accès à la mémoire existent. En effet que se passe-t-il si deux threads modifient en même temps une même variable ? Et bien on ne sait pas, le programme pourrait buguer, planter ou continuer de fonctionner normalement.

C'est d'ailleurs pour cela qu'il existe l'option EXITFUNC sour Metasploit. Cette option permet de spécifier la manière dont on veut que notre payload soit terminé. Par exemple il est intéressant d'utiliser la méthode process lorsque l'on sait que le processus ciblé est monitoré par un daemon. Ainsi si on exploite un buffer overflow sur telnet on pourra clore le processus puisque de toute manière ce dernier sera relancé dans la foulée. A l'inverse utiliser la méthode thread est plus intéressante sur un serveur web puisqu'elle n'affectera pas l'état du serveur une fois l'exécution du payload terminé. Enfin SEH est une valeur un peu particulière puisqu'elle va nous permettre de faire appel à une exception et ainsi rendre le fil d'exécution au processus légitime.

Ok maintenant qu'on sait ce qu'est un thread et un processus on va voir trois nouvelles notions: vulnérabilité, exploit et payload.

II/ Vulnérabilité, exploit et payload

Une vulnérabilité c'est un défaut de programmation, une faiblesse au sein du code source d'une application. Cela peut être un débordement de tampon (Buffer overflow), une format string ou encore une race condition.

Une fois qu'une vulnérabilité est découverte il faut encore pouvoir l'exploiter. En effet c'est bien d'avoir un buffer overflow sur le protocole SMB mais dans l'état il ne nous sert à rien tant que l'on a pas de shellcode à y insérer. Il faut donc développer ce qu'on appelle un exploit.

Un exploit c'est du code qui prend à parti la vulnérabilité afin de prendre le contrôle du processus et donc permettre une exécution de code. Le code que l'on exécutera c'est ce qu'on appelle un payload.

Si on reprend la chaîne d'exécution d'une RCE (Remote Code Execution) on a en premier la découverte d'une vulnérabilité, exemple un buffer overflow sur le protocole SMB:

Sans exploit le serveur SMB va juste crasher ce qui va créer un BSOD (Blue screen of death) sur le serveur et l'obliger à redémarrer. En revanche si un exploit est développé alors on pourra écraser l'espace mémoire alloué au processus SMB et à la place y insérer un shellcode:

Pour rappel, un shellcode est une suite d'instructions écrites sous forme hexadécimal que l'on va directement insérer dans la mémoire d'un processus cible. Suivant le payload inclus dans notre shellcode on pourra exécuter différentes actions mais la majorité du temps on s'en servira dans le but de récupérer un shell distant tel qu'un reverse shell Meterpreter:

​​

Meterpreter est probablement le payload le plus connu dans le monde de la cybersécurité. Ce payload développé par Sparke pour la verison 2 de Metasploit est aujourd'hui devenu un outil presque indispensable pour la majorité des pentester et ce pour plusieurs raisons. Premièrement Meterpreter n'est pas juste un reverse shell, c'est un payload multifonctionnel qui va, entre autre, nous permettre d'exécuter des commandes, dumper la base SAM, faire de l'upload/download de fichiers ou encore mettre en place du port forwarding.

Mais ce qui fait de Meterpreter un outil si fantastique c'est qu'il ne laisse aucune trace de son exécution sur le système de fichier de la cible. En effet Meterpreter est injecté directement dans la mémoire du processus ciblé via la technique de l'injection de DLL. Grosso modo l'injection de DLL consiste à injecter du code dans la mémoire d'un processus et de créer un thread qui exécutera ce code (on verra dans le prochain article comme fonctionne cette attaque).

Comme le payload est en mémoire, il ne sera jamais écrit sur le disque et donc presque indétectable. Voilà, avec ces quelques notions on va pouvoir attaquer l'injection de processus.