L’injection de DLL démystifiée

Les événements de ces derniers jours m’ont donné envie de me renseigner du coté des backdoors, des techniques de persistance, de communication ou encore d’évasion. Une des techniques d’évasion (j’entends par là le fait de camoufler des activités au yeux des antivirus, firewall) est l’injection de DLL ou de code au sein d’un processus légitime.

Lors de mes recherches j’ai principalement rencontré les mêmes problèmes : des tutoriels en C++ pas en C, une documentation de windows.h pas très orthodoxe lorsque l’on débute avec celle-ci et un débug compliqué à mettre en place. Je vais donc dans ce poste la partir de la base pour que les plus débutants d’entre vous puisse suivre.

 

 

0x01 Qu’est ce que l’injection de code

L’injection de code est le fait d’allouer de la mémoire dans un processus victime puis d’y ajouter du code directement exécutable (shellcode). Une fois le code injecté dans la zone mémoire il suffira d’ouvrir un thread pointant vers celle-ci pour que notre code soit exécuté par le processus victime.

Quand j’ai découvert cette technique il y a quelques mois je suis tout de suite dit : mais si on peut injecter du code aussi facilement pourquoi on se casse la tête à trouver des vulnérabilités ? Avec cette technique on écrit en mémoire n’importe quand, on peut donc faire faire au programme ce que l’on veut !

Oui sauf que l’on ne peut écrire dans un programme uniquement si on a les droits dessus ainsi on ne peut pas faire exécuter du code à un programme admin si on a pas les droits admin

Par contre le fait que ça soit un programme trusted qui exécute du code nous permet de ne pas éveiller les soupçons aux yeux d’un antivirus. En dehors de ça l’injection de DLL est surtout utiliser pour modder des jeux en ajoutant des fonctionnalités ou en accédant aux ressources du processus !

 

 

0x02 Les étapes et fonctions à utiliser

Il existe une différence entre l’injection de DLL et l’injection de code (shellcode) au sein d’un programme mais globalement le process reste le même. Il existe également deux façons d’exécuter le code :

  • On crée un nouveau thread en parallèle du premier
  • On suspend le premier, lance le second et revient au premier

Ici je n’expliquerai que la première méthode.

 

0x02.3 Les étapes pour l’injection de code
  1. On récupère le PID du processus victime
  2. On l’ouvre grâce à la fonction OpenProcess()
  3. On y alloue un peu de mémoire avec VirtualAllocEx()
  4. On écrit dans notre page précédement alloué notre code avec WriteProcessMemory()
  5. On change la protection de la page avec VirtualProtectEx()
  6. Finalement on crée notre thread avec CreateRemoteThread()

 

0x02.4 Les étapes pour l’injection de DLL
  1. On récupère le PID du processus victime
  2. On l’ouvre grâce à la fonction OpenProcess()
  3. On récupère l’adresse de LoadLibraryA avec GetProcAddress() <– 
  4. On y alloue un peu de mémoire avec VirtualAllocEx()
  5. On écrit dans notre page précédement alloué notre code avec WriteProcessMemory()
  6. On change la protection de la page avec VirtualProtectEx()
  7. Finalement on crée notre thread avec CreateRemoteThread()

Comme vous le voyez les 2 techniques sont presque identiques.

 

 

0x04 Générer nos payloads

Maintenant il s’agit de générer le code que l’on va injecter, qu’il s’agisse d’un shellcode ou d’une DLL. Soit on écrit nous même le shellcode et la DLL si on a besoin d’exécuter des instructions précises soit on peut directement générer un shellcode ou DLL avec msfvenom de Metasploit pour obtenir un reverse shell. Je sais coder des shellcodes mais pas des DLL donc pour cette démonstration je m’appuierais sur ceux générer par msfvenom.

Msfvenom est un composant de la Metsaploit qui est de base sur Kali sinon rendez-vous sur le site officiel de rapid7 pour le download gratuitement (la community edition)

  • -p spécifie le type de payload que l’on souhaite, ici un reverse shell via TCP
  • -a l’architecture x64
  • -f le format raw pour un shellcode et dll pour une DLL
  • LHOST correspond à l’IP du PC ou viendra se connecter la victime
  • LPORT correspond au port via lequel le reverse shell viendra se connecter sur la machine attaquante

Voilà comment générer un shellcode en 5 secondes, sinon il existe des bibliothèque de shellcode comme shell-storm ou exploit-db  /!\ N’utiliser un shellcode écrit par un autre uniquement si vous êtes sûr de ce qu’il fait /!\

 

 

0x05 Le code et le debug

Bon déjà le debug il y en pas ou presque pas :

  • Lors de VirtualAllocEx() vérifier que l’espace mémoire alloué augmente avec Process Explorer
  • Bien vérifier que l’appel à chaque fonction est réussi if(function() == 0) do …
  • Faire un dump mémoire du processus (chiant)

 

Cette fonction permet de retourner un buffer contenant notre shellcode en allouant de la mémoire dans le heap de la taille du shellcode. Je ne détails pas car c’est du C basique

Ce bout de code va retourner le PID du processus voulu il suffit de donner le nom du processus. Il fait un snapshot des processus en cours, les parcours un à un et si le nom de notre processus victime apparaît il en retourne le PID

Bon la c’est le gros bout mais tout est détailler en commentaire donc ça ne devrait pas poser de soucis. Je ne détaille pas les paramètres des fonctions car tout est dans la doc Microsoft et je ne suis pas assez à l’aise pour entrer dans ce genre de détails.

Maintenant que l’on a notre injecteur de shellcode / DLL on va pouvoir sortir msfconsole pour récupérer la connexion

On obtient bien un shell avec les droits de la personne qui possède sublime_text.exe ! On peut observer certains détails avec Process Explorer. Ici on peut voir les connexions TCP IP, une est ouverte vers le port 4444. Je trouve ça pas spécialement rassurant même si les dev’ d’antivirus connaisse cette technique les chances de détections restent relativement faibles (au moment ou j’écris l’article).

Pour détecter des connexions peu habituelles je vous conseille GlassWire Firewall qui vous notifie à chaque fois qu’une nouvelle connexion est ouverte et vers quel hôte ainsi que le nombre de mo échangé etc. Cela m’a permis de voir que explorer.exe contacter régulièrement des machines à l’étranger … Pas rassurant du tout.

 

 

0x06 Injectme

Injectme est un petit soft développé par Intrinsec sécurité c’est une version plus avancé de mon SouyeInjector. En même temps les gars qui dev ça sont des pros ! Il permet entre autre de lister les processus et voir si ils sont injectables ou non. Le code est disponible ici avec des vidéos et des slides de présentations assez sympathiques mais bon c’est codé en C++ ..

 

 

0x07 Conclusion et erreurs à éviter

J’ai perdu une journée à cause d’une erreur bête, un simple problème d‘architecture x86 / x64. En effet mon programme était compilé en 32bits mais mon PC est un x64 et j’utilise Sublime Text x64 (logique) et donc CreateRemoteThread ne marchait absolument pas. J’ai du installer la version x64 de MinGW et ferme quelques petites modifications.

Sinon comme je l’ai dit plus haut le débug est compliqué donc veiller à bien vérifier les paramètres. Je vous mets les liens qui m’ont pas mal aidé pendant la découverte de cette technique, ils peuvent vous apporter quelques précisions sur le sujet !