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.
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.
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) :

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. 💪
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.
PAGE_READWRITE — déroulementkernel32!Sleep en le faisant pointer vers notre callback.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.MySleep est invoqué.RWkernel32!Sleep d'origine pour éviter de laisser un simple IOC en mémoire indiquant que Sleep a été trampoliné (hooké en ligne).::Sleep d'origine est effectué pour laisser le Beacon dormir en attendant de nouvelles communications.RX puis re-hookons kernel32!Sleep pour garantir l'interception des endormissements suivants.PAGE_NOACCESS — déroulementkernel32!Sleep en le faisant pointer vers notre callback.VirtualAlloc + memcpy + CreateThread ...MySleep est invoqué.PAGE_NOACCESSkernel32!Sleep d'origine pour éviter de laisser un simple IOC en mémoire indiquant que Sleep a été trampoliné (hooké en ligne).::Sleep d'origine est effectué pour laisser le Beacon dormir en attendant de nouvelles communications.kernel32!Sleep pour garantir l'interception des endormissements suivants.RX puis le shellcode reprend son exécution.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 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 :
Cette implémentation contient cette idée, disponible avec l'option 2 dans <fluctuate>.
Assurez-vous également de consulter ses autres projets.