Sommaire
Salut les petits loups 😊.
Merci d'avoir cliqué sur cet article. Comme toujours, j'espère qu'il vous plaira 😁.
Aujourd'hui, on va aller dans le dur. Récemment, j'ai eu l'occasion d'expérimenter des choses qui m'ont rappelé mon adolescence, du coup, j'ai décidé d'en faire un article.
Attention : il faut utiliser le contenu de cet article à des fins éducatives uniquement. Ne faites rien d'illégal.
Le but ici, c'est d'apprendre comment ça fonctionne, et je trouve ça passionnant. D'ailleurs, je vais faire exprès d'omettre certains détails... Ce ne sera donc pas une solution clé en main, mais plutôt un moyen de voir "globalement comment ça marche".
Dix ans, c'est le temps qui me sépare de maintenant et de la dernière fois où Windows a été mon système d'exploitation principal.
Entre-temps, je suis passé sous Linux, puis sous macOS, ce qui m'a permis d'accéder à un terminal Unix tout en ayant accès à des logiciels commerciaux (Adobe, Microsoft Office, etc.).
Mais bon, après quatre ans de freelancing à temps plein, je me suis rendu compte qu'il y a un "problème" à être sous macOS comme système principal.
Pour faire simple : le monde de l'entreprise.
Microsoft (et Windows) est omniprésent dans le monde de l'entreprise, il n'y a que ça.
Dans mes différents projets, j'ai souvent eu affaire à l'environnement Microsoft...
Par exemple : déployer un environnement de développement PHP / Symfony sous Windows avec WSL2, gérer un "Active Directory" dans le cloud avec Entra ID, etc.
D'ailleurs, prochainement, il faudra que je fasse un article sur le meilleur environnement pour développer avec Symfony sous Windows... C'était initialement l'article prévu cette semaine, ça reviendra plus tard.
Des articles sur Windows, il devrait y en avoir quelques-uns prochainement.
Si, dans le gestionnaire des tâches, vous mettez fin au processus "explorer.exe", vous vous rendrez compte qu'en plus de la barre des tâches, le fond d'écran disparaît également...
Cela signifie donc que lorsque explorer.exe est chargé, c'est à ce moment-là que le fond d'écran est défini.
On va altérer ça... On va empêcher explorer.exe de charger le fond d'écran.
Avant toute chose, il faut qu'on comprenne ce qui se passe. À son lancement, explorer.exe fait appel à une API Windows pour définir le fond d'écran...
L'API en question est "SystemParametersInfoW", qui se trouve dans le fichier "user32.dll".
Elle est appelée avec le paramètre "SPI_SETDESKWALLPAPER", qui correspond à la valeur "0x0014".
Petite aparté : sur Windows, les API finissent souvent en "A" ou en "W" : "A" pour ASCII et "W" pour WideChar.
Historiquement, Windows était basé sur l'encodage ANSI (Windows 95, 98, ME), où les caractères étaient stockés sur 1 octet (char
). Cependant, avec l'arrivée de Windows NT et son support natif de l’Unicode (UTF-16), Microsoft a introduit des versions Unicode des fonctions API.
Maintenant qu'on sait comment explorer.exe définit le fond d'écran, il "suffit" donc de remplacer la fonction et de répondre à explorer.exe à la place de l'API Windows lorsque celui-ci l'appelle.
Facile, non ?
Bah oui... 😛.
Depuis tout à l'heure, je vous parle d'injecter du code dans explorer.exe, forcément, il ne va pas être d'accord.
Pour résumer, c'est très simple : si on crée un .exe qui "tue" explorer.exe, puis le recrée pour injecter du code avant qu'il fasse appel à l'API, Windows Defender bloquera le fichier .exe en le considérant comme malveillant.
Et en même temps... il a raison.
Et oui... Windows Defender est moins regardant lorsque le fichier .exe est signé numériquement avec un certificat reconnu.
Après, je n'ai pas poussé le vice jusqu'à acheter un certificat à 300 euros juste pour une expérience.
Pour un même code, dans un fichier .exe et dans une .dll, Windows Defender ne détectera pas le fichier .dll, même si celui-ci contient exactement le même code que dans le .exe.
En me rendant compte de ça, j'ai eu plein d'idées. Par exemple : plutôt que d'écrire du code en C++ qui sera compilé en binaire, essayer de coder un "injecteur" écrit en C# (donc en .NET) qui injectera du code dans explorer.exe.
L'idée, c'est qu'un .exe écrit en .NET n'est pas un vrai binaire, c'est du code interprété par le framework .NET, donc moins suspect.
Cependant, ce n'est pas la solution que j'ai retenue. J'ai trouvé quelque chose de plus marrant et de "plus safe".
Comme je l'ai dit plus haut, si un .exe est signé avec un certificat propre et valide, alors Windows Defender est moins regardant.
Et si notre code n'était pas exécuté par un .exe à nous, mais par un .exe qui est "de confiance" pour Windows Defender ? Ce serait fou de pouvoir faire ça... non ?
Eh oui, ce que je viens de dire est possible 😁.
Par défaut, lorsqu'un .exe a besoin d'une DLL, il va d'abord chercher dans son propre dossier. Si la bibliothèque n'est pas trouvée, alors il va la chercher dans le $PATH
(généralement System32
).
Mais beaucoup d'applications sont codées de manière à bien vérifier que la DLL chargée est bien une DLL légitime...
"Beaucoup" ne veut pas dire "toutes"...
En fouinant sur le net, on trouve une liste d'applications vulnérables au "DLL Hijacking".
Un exemple : "Notepad++", dans certaines versions, est vulnérable au DLL Hijacking.
Oui, pour cette partie, j'ai bien du code qui fonctionne et qui exploite Notepad++. Cependant, je ne le mettrai pas ici, et nous allons rester très théoriques.
Si vous téléchargez Notepad++, l'une des versions concernées par la vulnérabilité, alors vous verrez qu'il a bien été signé avec un certificat valide et que, pour Windows, tout est OK.
Pour le voir, faites un clic droit sur le .exe, puis "Propriétés", puis "Signature numérique".
L'une des premières choses que va faire Notepad++, c'est charger la bibliothèque "UxTheme.dll".
Donc, si dans le dossier de l'exécutable, on met un fichier "UxTheme.dll" qui exporte les mêmes fonctions que la DLL originale, alors Notepad++ exécutera ce code et restera sous le radar de Windows Defender (car le .exe est signé).
C'est donc ce à quoi il va falloir s'atteler : créer une DLL qui exporte les mêmes fonctions qu'UxTheme.dll .
Les fonctions n'ont pas besoin d'être réellement réimplémentées. D'ailleurs, l'une d'elles, par exemple "OpenThemeData", pourrait contenir notre code "spécial".
Après, le code pourrait aussi être appelé dans la fonction exécutée au chargement de la DLL :
Le choix de l'un ou l'autre ne change pas grand-chose en fait. Gardez juste en tête que vous êtes dans le processus de Notepad++ et que lui aussi a des tâches à exécuter.
Il peut donc être judicieux, une fois que la tâche à accomplir est faite, de terminer le processus Notepad++.
L'idée est simple, elle doit :
CREATE_SUSPENDED
(qui correspond à la valeur 0x00000004
).À ce stade, nous avons donc un processus explorer.exe qui a chargé notre DLL et qui exécute donc notre code.
Bienvenue dans explorer.exe, faites comme chez vous. 👌
Pour commencer, contrairement au chapitre précédent, je vais vous donner directement tout le code de cette DLL.
Bon, déjà, le code en lui-même est explicite.
On utilise MiniHook pour remplacer la fonction "SystemParametersInfoW" par notre propre fonction.
On initialise MiniHook, on indique quelle fonction on cible, et on garde un pointeur sur la fonction originale pour pouvoir lui passer les appels que nous ne souhaitons pas filtrer.
Pour rappel, nous voulons juste filtrer les appels qui changent le fond d'écran. Nous ne savons pas si explorer.exe utilise cette fonction pour faire autre chose, donc dans le doute, on laisse le reste passer, ce qui nous évite de créer des instabilités.
Notre fonction hookée est super simple : on regarde si explorer.exe passe le paramètre "SPI_SETDESKWALLPAPER" (0x0014). Si c'est le cas, on renvoie juste "true" et on ne fait rien.
(En plus, c'est ultra léger, ça réduit le nombre d'instructions exécutées 😂)
Quand explorer.exe appelle cette API, c'est nous qui répondons.
Et voilà, nous avons vu comment modifier un processus en mémoire sur Windows.
Ah, et... vous voulez voir ce que ça donne ?
La partie sur la DLL chargée par un exécutable signé est volontairement très théorique, sans code, car je ne souhaite pas que cela soit utilisé à des fins malveillantes.
D'ailleurs, je ne répondrai pas aux questions (généralement par e-mail) à ce sujet 😊.
Passez une très bonne journée et à la prochaine ! 😁