Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
DeathSleep — Une implémentation de preuve de concept pour une technique d'évasion visant à terminer le thread actuel et à le restaurer avant de reprendre l'exécution, tout en appliquant des modifications de protection de page pendant l'absence d'exécution. | Kitploit
Outils/GitHubGitHub/janoglezcampos/deathsleep
ExploitationAnalyse de MalwareRed TeamingDéveloppement de Charges Utiles
GitHubjanoglezcampos/deathsleep

DeathSleep

Une implémentation de preuve de concept pour une technique d'évasion visant à terminer le thread actuel et à le restaurer avant de reprendre l'exécution, tout en appliquant des modifications de protection de page pendant l'absence d'exécution.

Voir le dépôt
538778il y a 4 ansVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

██████╗ ███████╗ █████╗ ████████╗██╗ ██╗███████╗██╗ ███████╗███████╗██████╗ ██╔══██╗██╔════╝██╔══██╗╚══██╔══╝██║ ██║██╔════╝██║ ██╔════╝██╔════╝██╔══██╗ ██║ ██║█████╗ ███████║ ██║ ███████║███████╗██║ █████╗ █████╗ ██████╔╝ ██║ ██║██╔══╝ ██╔══██║ ██║ ██╔══██║╚════██║██║ ██╔══╝ ██╔══╝ ██╔═══╝ ██████╔╝███████╗██║ ██║ ██║ ██║ ██║███████║███████╗███████╗███████╗██║
╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚══════╝╚═╝

Une implémentation POC d'une technique d'évasion pour terminer le thread actuel et le restaurer avant de reprendre l'exécution, tout en modifiant les protections de pages pendant l'absence d'exécution.

Introduction

Les méthodes de sommeil et d'obfuscation sont bien connues dans la communauté maldev, avec différentes implémentations, elles ont pour objectif de se cacher des scanners mémoire pendant le sommeil, en changeant généralement les protections de pages et même en ajoutant des fonctionnalités intéressantes comme le chiffrement du shellcode, mais il y a un autre point important pour cacher notre shellcode : cacher le thread d'exécution actuel. Spoofer la stack est cool, mais après y avoir réfléchi un peu, je me suis dit qu'il n'est pas nécessaire de spoof la stack… s'il n'y a pas de stack :)

L'utilité de cette technique est laissée à l'appréciation du lecteur, mais dans tous les cas, je pense que c'est une façon intéressante de revoir certains sujets et d'apprendre un peu de maldev pour ceux qui, comme moi, débutent dans ce monde.

L'implémentation principale présentée ici contient tout ce que nous devons sortir de la stack dans la section data, sous forme de variables globales, mais une implémentation déplaçant tout vers le heap sera publiée prochainement. Elle vise à montrer quelques modifications clés nécessaires pour rendre ce code pic et injectable.

Ce dépôt est dupliqué entre GitHub et GitLab.


Qu'est-ce qui se passe ?

Tout d'abord

Tout ce qui est indiqué ici provient de ma compréhension des différents sujets abordés, que ce soit par la lecture ou l'expérience lors du développement. Je suis conscient que je ne suis pas un expert et la dernière chose que je souhaite est de propager des informations erronées, donc si vous pensez que quelque chose n'est pas correct, je serais ravi que vous m'en fassiez part, vous pouvez me contacter sur twitter, ou ouvrir des issues dans ce repo. Merci beaucoup pour votre compréhension. :)

Bases

L'objectif principal de cette technique est clair : terminer le thread actuel et le restaurer avant de reprendre l'exécution, mais qu'est-ce que cela signifie exactement, et quelles nouvelles contraintes cela impose-t-il ?

Pour pouvoir restaurer l'exécution, nous devons sauvegarder deux choses avant de terminer le thread : d'abord l'état du CPU, et ensuite la stack, et les remettre en place efficacement après le lancement du nouveau thread.

J'ai parlé de nouvelles contraintes qui apparaîtront dans cette technique, et il y en a deux principales : premièrement, nous devons stocker en dehors de la stack tout ce qui est nécessaire depuis le moment où le thread se termine jusqu'à ce que la stack soit restaurée, et comme vous le verrez, cela crée de nouveaux défis.

Deuxièmement, nous avons toujours besoin d'au moins un autre thread en cours d'exécution dans notre processus, car nous terminons notre thread ; s'il n'y a pas d'autres threads, le processus se terminera. Je ne pense pas que ce soit un gros problème, car la plupart des agents sont injectés dans d'autres processus, nous pouvons supposer que ce processus conservera au moins un thread en cours d'exécution.

Composants de DeathSleep :

Nous pouvons voir dans cette POC 4 fonctions principales :

  • Programme principal : C'est ici que vous écririez votre code d'agent, et c'est la partie du code qui utilisera DeathSleep
  • Fonction Awake : c'est le point d'entrée de tous nos threads, et elle est chargée de sauvegarder le point de départ de la stack que nous allons restaurer. Elle est également chargée de restaurer la stack et le contexte CPU lorsque nécessaire, ou simplement de lancer notre programme principal.
  • DeathSleep : c'est la fonction principale de cette technique, et elle est chargée de sauvegarder le contexte du thread et la stack, et aussi de tout préparer pour que la magie opère.
  • Rebirth : Une fonction simple chargée uniquement de lancer nos nouveaux threads.

Sauvegarde de la stack.

Lorsque nous sommes sur le point de sauvegarder la stack, une question se pose : quelle quantité de la stack doit être sauvegardée ?

Revoyons d'abord ce qui se trouve dans la stack après avoir appelé la fonction DeathSleep (c'est la fonction qui sauvegarde le contexte, la stack et prépare tout pour l'obfuscation et la restauration)

Comme nous pouvons le voir, chaque fonction a trois parties :

  • Shadow space : c'est un espace de 32 octets, alloué par l'appelant, mais utilisé par l'appelé. Pour autant que je sache et que j'aie pu voir, sa fonction principale est de contenir, si nécessaire, les arguments passés à la fonction appelée dans les registres, mais il peut être utilisé pour tout ce que la fonction appelée décide.
  • Adresse de retour : c'est l'adresse de la prochaine instruction à exécuter dans la fonction appelante, poussée par l'instruction CALL, de sorte que l'instruction RET dans la fonction appelée prendra simplement cette adresse et "sautera" dessus lorsqu'elle se terminera.
  • Espace stack de la fonction : c'est l'espace réservé par l'appelé pour stocker la valeur des registres qui doivent être restaurés et la valeur de ses variables locales.

La partie minimale de la stack que nous devons évidemment sauvegarder est tout ce qui se trouve à l'intérieur de notre programme principal, c'est-à-dire son shadow space, son adresse de retour et tout jusqu'à la fonction DeathSleep. Tout ce qui précède n'est pas vraiment nécessaire (sauvegarder la stack utilisée par la fonction d'entrée a ses avantages, mais nous en discuterons plus tard), car c'est la stack utilisée par les routines Windows pour lancer notre nouveau thread. En plus de cela, j'ai décidé de stocker également le shadow space de la fonction DeathSleep (pas vraiment nécessaire, mais cela facilite le calcul du Rsp au moment du réveil).

Donc au final, nous sauvegardons ceci :

Comment trouver nos adresses de stack :

Chaque fonction dans une compilation standard devrait être composée de 3 parties : le prologue, le code de la fonction, et l'épilogue.

Le Rsp (pointeur de stack) ne devrait être modifié que dans le prologue et l'épilogue de la fonction. Le prologue augmente le pointeur de stack (rappelez-vous qu'augmenter la stack signifie réduire les adresses, car elles vont dans des directions opposées), pour sauvegarder les registres, contenir toutes ses variables locales, puis contenir le shadow space, et l'épilogue fait exactement le contraire.

Télécharger l’outil