Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
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
ShellcodeFluctuation — Une technique avancée d'évasion en mémoire qui fait fluctuer la protection mémoire du shellcode entre RW/NoAccess et RX, puis chiffre/déchiffre son contenu. | Kitploit
Outils/GitHubGitHub/mgeeky/shellcodefluctuation
ShellcodePost-ExploitationRed TeamingDéveloppement de Charges UtilesAttaque Adversariale
GitHubmgeeky/shellcodefluctuation

ShellcodeFluctuation

Une technique avancée d'évasion en mémoire qui fait fluctuer la protection mémoire du shellcode entre RW/NoAccess et RX, puis chiffre/déchiffre son contenu.

Voir le dépôt
1.1k163il 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

Shellcode Fluctuation PoC

Une implémentation PoC pour une autre technique d'évasion en mémoire qui chiffre et déchiffre cycliquement le contenu du shellcode pour le faire fluctuer entre les protections mémoire RW (ou NoAccess) et RX. Lorsque notre shellcode réside dans des pages mémoire RW ou NoAccess, des scanners tels que Moneta ou pe-sieve seront incapables de le localiser et de le dump pour une analyse plus approfondie.

Intro

Après avoir publié ThreadStackSpoofer, j'ai reçu quelques questions à propos du point suivant du README :

Changez la protection des pages mémoire de votre Beacon en RW (depuis RX/RWX) et chiffrez leur contenu avant l'endormissement (cela pourrait contourner des scanners tels que Moneta ou pe-sieve)

Avant cela, j'étais assez convaincu que la communauté savait déjà comment chiffrer/déchiffrer ses payloads et modifier ses protections mémoire pour simplement contourner les scanners mémoire à la recherche de régions exécutables anormales. Les questions ont prouvé le contraire, j'ai donc décidé de publier ce PoC non armé pour documenter une autre stratégie d'évasion et proposer une implémentation d'exemple à la communauté.

Ce PoC est une démonstration d'une technique plutôt simple, déjà connue de la communauté offensive (donc je n'apporte rien de vraiment nouveau ici), dans l'espoir de lever le voile sur la magie démontrée par certains frameworks commerciaux qui exhibent leurs capacités d'évasion ciblant les deux scanners mémoire susmentionnés.

Voici une comparaison lors de la fluctuation vers RW (une autre option consiste à fluctuer vers PAGE_NOACCESS — décrite ci-dessous) :

  1. Beacon non chiffré
  2. Beacon chiffré (fluctuant)

comparison

Cette implémentation, accompagnée de mon ThreadStackSpoofer, apporte à la communauté Offensive Security des implémentations d'exemple pour rattraper l'offre des produits C2 commerciaux, afin que nous ne fassions pas moins bien dans nos outils Red Team. 💪


Comment ça marche ?

Ce programme effectue une auto-injection de shellcode (grossièrement via le classique VirtualAlloc + memcpy + CreateThread). Lorsque le shellcode s'exécute (cette implémentation cible spécifiquement les implants Cobalt Strike Beacon), une fonction Windows sera hookée pour intercepter le moment où le Beacon s'endort : kernel32!Sleep. Chaque fois que la fonction hookée MySleep est appelée, elle localise les limites de son allocation mémoire, bascule leur protection en RW et applique un xor32 sur tous les octets qui y sont stockés. Après avoir attendu le délai prévu, lorsque le shellcode revient dans notre handler MySleep, nous déchiffrons les données du shellcode et rebasculons la protection en RX.

Fluctuation vers PAGE_READWRITE — déroulement

  1. Lire le contenu du shellcode depuis un fichier.
  2. Hooker kernel32!Sleep en le faisant pointer vers notre callback.
  3. Injecter et lancer le shellcode via VirtualAlloc + memcpy + CreateThread. Contrairement à ce que nous avions dans ThreadStackSpoofer, nous ne hookons ici rien dans ntdll pour lancer notre shellcode, mais nous y sautons depuis notre propre fonction. Cela tente d'éviter de laisser de simples IOC en mémoire pointant vers une mémoire ntdll modifiée.
  4. Dès que le Beacon tente de s'endormir, notre callback MySleep est invoqué.
  5. L'allocation mémoire du Beacon est chiffrée et sa protection basculée en RW
  6. Nous déhookons ensuite le kernel32!Sleep d'origine pour éviter de laisser un simple IOC en mémoire indiquant que Sleep a été trampoliné (hooké en ligne).
  7. Un appel au ::Sleep d'origine est effectué pour laisser le Beacon dormir en attendant de nouvelles communications.
  8. Une fois le Sleep terminé, nous déchiffrons les données de notre shellcode, rebasculons ses protections mémoire en RX puis re-hookons pour garantir l'interception des endormissements suivants.

Fluctuation vers PAGE_NOACCESS — déroulement

  1. Lire le contenu du shellcode depuis un fichier.
  2. Hooker kernel32!Sleep en le faisant pointer vers notre callback.
  3. Injecter et lancer le shellcode via VirtualAlloc + memcpy + CreateThread ...
  4. Initialiser un Vectored Exception Handler (VEH) pour mettre en place notre propre handler qui attrapera les exceptions Access Violation.
  5. Dès que le Beacon tente de s'endormir, notre callback MySleep est invoqué.
  6. L'allocation mémoire du Beacon est chiffrée et sa protection basculée en PAGE_NOACCESS
  7. Nous déhookons ensuite le kernel32!Sleep d'origine pour éviter de laisser un simple IOC en mémoire indiquant que Sleep a été trampoliné (hooké en ligne).
  8. Un appel au ::Sleep d'origine est effectué pour laisser le Beacon dormir en attendant de nouvelles communications.
  9. Une fois le Sleep terminé, nous re-hookons kernel32!Sleep pour garantir l'interception des endormissements suivants.
  10. Le shellcode tente ensuite de reprendre son exécution, ce qui provoque une Access Violation puisque ses pages sont marquées NoAccess.

Ce n'est pas une technique nouvelle

La technique n'est pas récente, et ce n'est rien que j'ai inventé moi-même. C'est simplement une implémentation montrant le concept et son utilisation pratique pour permettre à notre communauté Offensive Security de rattraper l'offre des frameworks C2 commerciaux.

En réalité, j'ai été introduit à l'idée de basculer la protection mémoire du shellcode il y a quelques années grâce au travail de Josh Lospinoso dans son incroyable Gargoyle.

Voici davantage de contexte :

  • gargoyle, a memory scanning evasion technique
  • Bypassing Memory Scanners with Cobalt Strike and Gargoyle

Gargoyle pousse le concept du shellcode auto-conscient et auto-fluctuant encore plus loin, en exploitant une séquence ROP appelant VirtualProtect. Cependant, si la technique est impressionnante, elle est tout aussi difficile à exploiter avec le Beacon de Cobalt Strike sans avoir à tuer son thread et à réinitialiser continuellement le Beacon en mémoire.

Ce n'est pas parfait, mais puisque nous opérons déjà depuis le terrain de notre propre processus loader à auto-injection, nous pouvons faire ce que nous voulons de l'environnement dans lequel le shellcode évolue et le cacher comme bon nous semble. Cette technique (ainsi que la précédente, ThreadStackSpoofer) montre les avantages d'exécuter nos shellcodes de cette manière.

L'implémentation de la fluctuation vers PAGE_NOACCESS est inspirée du travail d'ORCA666 présenté dans son injecteur https://github.com/ORCA666/0x41. Il a démontré que :

  1. nous pouvons initialiser un vectored exception handler (VEH),
  2. basculer les pages du shellcode en no-access
  3. puis attraper les exceptions Access Violation qui se produiront dès que le shellcode voudra reprendre son exécution, et déchiffrer + rebasculer ses pages mémoire en Read+Execute.

Cette implémentation contient cette idée, disponible avec l'option 2 dans <fluctuate>. Assurez-vous également de consulter ses autres projets.


Demo

L'outil ShellcodeFluctuation accepte trois paramètres : le premier étant le chemin vers le shellcode et le second un modificateur de notre fonctionnalité.``` Usage: ShellcodeFluctuation.exe : -1 - Read shellcode but dont inject it. Run in an infinite loop. 0 - Inject the shellcode but don't hook kernel32!Sleep and don't encrypt anything 1 - Inject shellcode and start fluctuating its memory with standard PAGE_READWRITE. 2 - Inject shellcode and start fluctuating its memory with ORCA666's PAGE_NOACCESS.

root@kitploit:~
### Moneta (apparemment) faux positif```
C:\> ShellcodeFluctuation.exe beacon64.bin -1

So, voyons d'abord ce que le scanner Moneta64 pense d'un processus qui ne fait rien de suspect et se contente d'exécuter une boucle infinie :

faux positif moneta

Comme on peut le voir, il y a un faux positif (du moins, c'est ainsi que je le considère) censé détecter Mismatching PEB module / Phantom image. Les limites mémoire pointent vers le module ShellcodeFluctuate.exe lui-même et pourraient indiquer que ce module, bien qu'étant de type MEM_IMAGE, n'est pas lié dans la PEB du processus - ce qui est inhabituel et semble plutôt étrange. La raison de cet IOC m'est inconnue et je n'ai pas tenté de la comprendre davantage, mais ce n'est pas vraiment quelque chose qui devrait nous inquiéter.

Si quelqu'un sait quelle est la raison de cette détection, je serais très curieux de l'entendre ! N'hésitez pas à me contacter.

Beacon non chiffré```

C:> ShellcodeFluctuation.exe beacon64.bin 0

root@kitploit:~
Le deuxième cas d'usage présente des IOC mémoire d'un Beacon opérant dans notre processus, qui n'utilise aucune sorte d'`Artifact Kits` personnalisés, ni de `User-Defined Reflective Loaders` (comme mon [`ElusiveMice`](https://github.com/mgeeky/ElusiveMice)), ni aucune action initiale qui pourrait fausser nos résultats.

![moneta non chiffré](https://assets.kitploit.com/production/public/readmes/50718/6a4e3a230a362c25da6f4aa6955b822d2a83215848c1bc09566a27ea9db653c9/dd2e0560a688886c0fe06debe92f153e129daa6654cb17c2976edee8661e3bd3-display-v1.webp)

On peut voir que `Moneta64` reconnaît correctement `Abnormal private executable memory` pointant vers l'emplacement où réside notre shellcode. 
C'est un IOC mémoire très fort qui expose notre shellcode, le faisant potentiellement dumper et analyser par des scanners automatisés. Pas cool.

### Beacon chiffré avec protections RW```
C:\> ShellcodeFluctuation.exe beacon64.bin 1

Maintenant le troisième cas d'utilisation, le plus intéressant du point de vue de cette implémentation, étant le Beacon fluctuant.

moneta encrypted

Outre le premier IOC, considéré comme plutôt faux positif, on en voit un nouveau indiquant que la mémoire de kernel32.dll a été modifiée. Cependant, aucun IOC Abnormal private executable memory cette fois. Notre fluctuation (chiffrement/déchiffrement répété et basculement des protections mémoire) est active.

Et pour mémoire, pe-sieve détecte également les PE implantés lorsqu'il est utilisé avec l'option /data 3 (à moins que cette option ne soit fournie, aucune détection ne sera effectuée) :

pe-sieve

Mon hypothèse actuelle est que PE-Sieve détecte les mêmes caractéristiques que Moneta (décrites ci-dessous dans Modified code in kernel32.dll) - le fait qu'un module PE mappé possède un Working set non vide, ce qui est une preuve évidente d'une forme d'injection de code. Cela est étiqueté comme Implanted PE / Implanted. Si c'est le cas, la conclusion est similaire à l'observation de Moneta. Je ne pense pas que nous devrions accorder trop d'importance à cet IOC du point de vue de la détection.

Actuellement, je n'ai pas trouvé de meilleure option pour intercepter l'exécution du shellcode en plein milieu (parlant maintenant de Cobalt Strike), que de hooker kernel32!Sleep. Ainsi, nous sommes obligés de laisser ce genre d'IOCs.

Mais bon, aucun octet ne diffère toujours par rapport à ce qui se trouve sur le système de fichiers (C:\Windows\System32\kernel32.dll) et aucune fonction n'est hookée, alors que se passe-t-il ? 😉

Beacon chiffré avec protections PAGE_NOACCESS```

C:> ShellcodeFluctuation.exe beacon64.bin 2

root@kitploit:~
![no-access](https://assets.kitploit.com/production/public/readmes/50718/03f80df765f37efb3242dce12c613091ab79896e584fbfc2a309a1295c4544c6/327fe5cc3e3ebe6db8277bd091361f7ae42ee4925e21aa87cfa9287b404a1ab5-display-v1.webp)

Cela fera effectivement osciller le shellcode entre des pages `RX` et `NA`.

Pour l'instant, je ne suis pas certain des avantages de basculer vers `PAGE_NOACCESS` plutôt que `PAGE_READWRITE`. 


### Code modifié dans kernel32.dll

Alors, qu'en est-il de cet IOC `kernel32` modifié ?

Maintenant, essayons d'aller au fond de cet IOC et de voir ce qui se passe exactement.

Tout d'abord, nous allons dumper la région mémoire mentionnée - à savoir la section `.text` (code) de `kernel32.dll`. Utilisons `ProcessHacker` à cette fin, afin de recourir à un outil public, connu et stable :

![dump-kernel](https://assets.kitploit.com/production/public/readmes/50718/0b1a4700514b15ec5199ead8f09ccd7c4e5fefc2302a9a9eee0d4e6d77ea48b4/bae9be0ce4bdcede99f235f42431b159bbbf35539f36fe58906fe991e4aacdb4-display-v1.webp)

Nous dumpons la section code de ce kernel32 prétendument modifié, puis nous faisons de même pour le kernel32 s'exécutant dans un processus qui n'a pas modifié cette zone.

Une fois ces deux dumps obtenus, nous pouvons les comparer octet par octet (à l'aide de mon [expdevBadChars](https://github.com/mgeeky/expdevBadChars)) pour rechercher d'éventuelles incohérences :

![bindiff](https://assets.kitploit.com/production/public/readmes/50718/4df33e426c7d23554953e2117e3706ee9af1b53b3dd4a60f7b05bcabb988bc85/3db05a8375ded834d576d29083dab9b646cbd83b791a591717fbe0e56ca9a64e-display-v1.webp)

Pour simplement constater qu'ils correspondent l'un à l'autre. De toute évidence, pas un seul octet n'est modifié dans `kernel32.dll`, et la raison en est que nous retirons le hook de `kernel32!Sleep` avant de l'appeler :

`main.cpp:31:````
    HookTrampolineBuffers buffers = { 0 };
    buffers.originalBytes = g_hookedSleep.sleepStub;
    buffers.originalBytesSize = sizeof(g_hookedSleep.sleepStub);

    //
    // Unhook kernel32!Sleep to evade hooked Sleep IOC. 
    // We leverage the fact that the return address left on the stack will make the thread
    // get back to our handler anyway.
    //
    fastTrampoline(false, (BYTE*)::Sleep, &MySleep, &buffers);

    // Perform sleep emulating originally hooked functionality.
    ::Sleep(dwMilliseconds);

Alors, qu'est-ce qui déclenche l'IOC ? Inspectons Moneta de plus près :

moneta

En nous introduisant dans le Ioc.cpp de Moneta, juste autour de la ligne 104 où il signale l'IOC MODIFIED_CODE, nous pouvons modifier un peu le code pour mieux exposer le moment exact où il analyse le pool de kernel32. Maintenant :

  1. La vérification est faite pour s'assurer que la région de kernel32 est exécutable. Nous voyons qu'en fait cette région est exécutable a = true
  2. La quantité de mémoire privée de ce module est obtenue. Ici nous voyons que kernel32 a b = 0x1000 octets privés. Comment cela se fait-il ? Il devrait y en avoir 0.
  3. Si l'allocation exécutable a plus de 0 octets de mémoire privée (a && b), l'IOC est signalé
  4. Et c'est la preuve que nous examinions kernel32 à ce moment-là.

Lorsque le chargeur d'images Windows mappe un module DLL dans l'espace mémoire du processus, les pages mémoire sous-jacentes seront étiquetées comme MEM_MAPPED ou MEM_IMAGE selon le scénario. Chaque fois que nous modifions ne serait-ce qu'un seul octet de l'allocation MEM_MAPPED/MEM_IMAGE, le système séparera une seule page mémoire (en supposant que nous avons modifié moins de PAGE_SIZE octets et que nous n'avons pas franchi la limite de page) pour indiquer un fragment qui ne correspond plus à l'image d'origine.

Cette observation est ensuite utilisée comme IOC - une image ne devrait pas avoir d'allocations MEM_PRIVATE dans sa région mémoire (à l'intérieur de celle-ci), car cela indiquerait que certains octets ont été modifiés dans cette région. Moneta détecte correctement la modification de code, même si les octets correspondaient aux octets du module d'origine au moment de la comparaison.

Pour une explication complète du fonctionnement interne de Moneta, de l'implémentation de l'injection de processus et des IOCs associés, lisez les articles de haute qualité suivants de Forrest Orr :

  1. Masking Malicious Memory Artifacts – Part I: Phantom DLL Hollowing
  2. Masking Malicious Memory Artifacts – Part II: Blending in with False Positives
  3. Masking Malicious Memory Artifacts – Part III: Bypassing Defensive Scanners

C'est une recherche et une documentation vraiment exceptionnelles de la part de Forrest, excellent travail mon ami !

Le deuxième article en particulier expose la justification de cette détection, comme nous lisons ce que Forrest nous enseigne :

Dans le cas où le module aurait été légitimement chargé et ajouté au PEB, l'implant shellcode aurait quand même été détecté en raison des 0x1000 octets (1 page) de mémoire mappés en privé dans l'espace d'adressage et récupérés par Moneta en interrogeant son working set - résultant en un IOC de code modifié comme vu ci-dessus.

Pour résumer, nous laissons un IOC derrière nous, mais devrions-nous nous inquiéter de cela ? Même s'il y a un IOC, aucun octet volé n'est visible, donc aucune référence immédiate ne pointe vers notre shellcode ni ne distingue la technique de notre shellcode des autres.

En bref - nous ne devrions pas vraiment nous inquiéter de cet IOC. :-)

Mais les frameworks commerciaux ne laissent aucun IOC

On pourrait dire que cette implémentation est loin d'être parfaite car elle laisse quelque chose, et qu'il y a toujours des IOCs alors que les produits commerciaux montrent qu'ils n'ont pas de traits similaires.

Lorsque cet argument est sur la table, je dois rappeler que les frameworks commerciaux ont un contrôle total sur le code source de leurs implants et de leurs chargeurs de shellcode, et peuvent ainsi intégrer parfaitement l'un avec l'autre pour éviter d'avoir à hooker et bricoler leur propre shellcode. Ici, nous devons hooker kernel32!Sleep pour intercepter l'exécution du Beacon de Cobalt Strike juste avant qu'il ne s'endorme, afin de lancer notre ménage. S'il existait un meilleur mécanisme pour intervenir sans avoir à hooker le sleep, ce serait parfait.

Cependant, il existe une notion de Sleep Mask introduite dans Cobalt Strike, et les restrictions de taille (quelques centaines d'octets) nous rendent totalement incapables d'introduire cette logique dans le masque lui-même (sinon nous pourrions également ne pas hooker Sleep, ne laissant ainsi aucun IOC, comme le font les produits commerciaux).

Un autre argument pourrait être que les frameworks commerciaux intègrent ce genre de logique dans leurs Reflective Loaders et qu'ici nous la laissons plutôt dans le harnais EXE. C'est vrai, mais la raison d'une telle décision est double :

  1. Je dois être vraiment prudent en publiant ce genre de technologie pour éviter le risque d'aider à armer les criminels du monde réel avec une implémentation qui nous reviendra comme un autre Petya. De cette manière, j'ai décidé de sauter certains détails sanglants que j'utilise dans mes outils professionnels destinés aux exercices commerciaux de simulation d'adversaire. Donner la graine, espérons-le, permettra aux professionnels de la communauté de développer le concept dans leurs propres outils, à condition qu'ils aient les compétences appropriées.

  2. Je préférerais de loin déplacer toute cette logique dans le User-Defined Reflective Loader de Cobalt Strike, offrant ainsi aux groupes de Red Team des chances accrues pour leur phase de livraison. Mais premièrement, voir le point (1), deuxièmement, cette technologie est actuellement limitée à une taille de 5KBs pour leurs RDLLs, ce qui me rend totalement incapable de l'implémenter là non plus. Pour ceux d'entre nous qui construisent des C2 et des implants personnalisés pour des engagements internes de simulation d'adversaire - ils ont désormais reçu une implémentation exemple qui les aidera sûrement à embellir leurs outils en conséquence.


Comment l'utiliser ?

Regardez le code et son implémentation, comprenez le concept et réimplémentez le concept dans vos propres chargeurs de shellcode que vous utilisez pour livrer vos engagements de Red Team. C'est une technique supplémentaire d'évasion avancée en mémoire qui augmente les chances de votre équipe de ne pas être détectée par les antivirus, EDR et analystes de malwares qui examinent vos implants.

Lors du développement de votre chargeur de shellcode avancé, vous pourriez également vouloir implémenter :

  • Chiffrement du tas du processus - inspirez-vous de cet article de blog : Hook Heaps and Live Free - qui peut vous permettre d'échapper aux extracteurs de configuration Beacon comme BeaconEye
  • Spoofez la pile d'appels de votre thread avant de dormir (cela pourrait contourner les scanners tentant d'examiner les threads du processus et leurs piles d'appels pour chasser les allocations mémoire MEM_PRIVATE référencées par ces threads)
  • Nettoyez tous les résidus du Reflective Loader pour éviter les détections par signatures en mémoire
  • Unhook tout ce que vous pourriez avoir hooké (comme AMSI, ETW, WLDP) avant de dormir, puis re-hooker ensuite.

Exemple d'exécution

Cas d'utilisation :``` Usage: ShellcodeFluctuation.exe : -1 - Read shellcode but dont inject it. Run in an infinite loop. 0 - Inject the shellcode but don't hook kernel32!Sleep and don't encrypt anything 1 - Inject shellcode and start fluctuating its memory with standard PAGE_READWRITE. 2 - Inject shellcode and start fluctuating its memory with ORCA666's PAGE_NOACCESS.

root@kitploit:~
Où :
- `<shellcode>` est un chemin vers le fichier shellcode
- `<fluctuate>` comme décrit ci-dessus, prend `-1`, `0` ou `1`


Exemple d'exécution qui usurpe la pile d'appels du thread du beacon :```
C:\> ShellcodeFluctuation.exe ..\..\tests\beacon64.bin 1

[.] Reading shellcode bytes...
[.] Hooking kernel32!Sleep...
[.] Injecting shellcode...
[+] Shellcode is now running. PID = 9456
[+] Fluctuation initialized.
    Shellcode resides at 0x000002210C091000 and occupies 176128 bytes. XOR32 key: 0x1e602f0d
[>] Flipped to RW. Encoding...

===> MySleep(5000)

[.] Decoding...
[>] Flipped to RX.
[>] Flipped to RW. Encoding...

===> MySleep(5000)

Avertissement

Si vous envisagez d'ajouter cette fonctionnalité à vos propres chargeurs de shellcode / outils, assurez-vous d'ÉVITER de décrocher kernel32.dll. Une tentative de décrochage de kernel32 restaurera la fonctionnalité d'origine de Sleep, empêchant ainsi notre callback d'être appelée. Si notre callback n'est pas appelée, le thread ne pourra pas usurper sa propre pile d'appels.

Si c'est ce que vous souhaitez, vous devrez peut-être exécuter un autre thread watchdog pour vous assurer que le thread du Beacon sera usurpé à chaque fois qu'il se met en veille.

Si vous utilisez Cobalt Strike et un BOF unhook-bof de Raphael's Mudge, assurez-vous de consulter ma Pull Request qui ajoute un paramètre optionnel au BOF pour spécifier les bibliothèques qui ne doivent pas être décrochées.

De cette façon, vous pouvez conserver vos hooks dans kernel32 :``` beacon> unhook kernel32 [*] Running unhook. Will skip these modules: wmp.dll, kernel32.dll [+] host called home, sent: 9475 bytes [+] received output: ntdll.dll <.text> Unhook is done.

root@kitploit:~
[`unhook-bof` modifié avec option pour ignorer les modules spécifiés](https://github.com/mgeeky/unhook-bof)

---

## Remarque finale

Ce PoC a été conçu pour fonctionner avec les shellcodes Beacon de Cobalt Strike. Le Beacon est connu pour appeler `kernel32!Sleep` afin d'attendre d'autres instructions de son C2. 
Ce loader exploite ce fait en hookant `Sleep` pour effectuer son ménage interne. 

Cette implémentation pourrait ne pas fonctionner avec d'autres shellcodes du marché (comme _Meterpreter_) s'ils n'utilisent pas `Sleep` pour se refroidir. 
Comme il s'agit simplement d'une _Preuve de concept_ illustrant la technique, je n'ai pas l'intention d'ajouter la prise en charge d'un autre framework C2.

Lorsque vous comprenez le concept, vous serez sûrement en mesure de le traduire selon vos besoins en shellcode et d'adapter la solution à votre avantage.

Veuillez ne pas ouvrir de problèmes GitHub liés à « ce code ne fonctionne pas avec tel shellcode XYZ », ils seront fermés immédiatement.

---

### ☕ Montrez votre soutien ☕

Ce projet et d'autres sont le fruit de nuits blanches et de **beaucoup de travail acharné**. Si vous aimez ce que je fais et que vous appréciez le fait que je redonne toujours à la communauté,
[Envisagez de m'offrir un café](https://github.com/sponsors/mgeeky) _(ou plutôt une bière)_ juste pour dire merci ! 💪 

---

## Auteur```   
   Mariusz Banach / mgeeky, 21
   <mb [at] binary-offensive.com>
   (https://github.com/mgeeky)
Télécharger l’outil
kernel32!Sleep
  • Notre VEH Handler attrape l'exception, déchiffre et rebascule les protections mémoire en RX puis le shellcode reprend son exécution.