
ShellcodeFluctuation PoC porté vers Nim
Portage Nim du dépôt d'origine : https://github.com/mgeeky/ShellcodeFluctuation Tous les commentaires ont été copiés-collés tels quels depuis le dépôt d'origine, car ils m'ont vraiment aidé à comprendre la technique. Pour plus d'informations sur la technique elle-même, je recommande vivement de parcourir le README du dépôt d'origine !
Installer les dépendances :
nimble install winim ptr_math
Je suis parfaitement conscient que cette technique de chiffrement mémoire n'est pas la meilleure en termes d'OpSec. Elle ne chiffrera exactement que les régions qui ont été définies pour elle. Ainsi, par exemple, pour une C2-Implant, toutes les adresses mémoire des modules nouvellement exécutés ne seront pas chiffrées au Sleep. Pour les détections basées sur le tas (comme celles pour la configuration Cobalt-Strike), vous devez toujours ajouter le chiffrement du tas ici.
Mais néanmoins, la technique de chiffrement mémoire peut être utilisée tout à fait correctement pour éviter les détections automatiques des scanners mémoire au Sleep for the main C2-Implant. J'ai testé avec succès le PoC avec Covenant et un payload stageless personnalisé comme celui-ci.
La clé de chiffrement/déchiffrement ainsi que l'adresse du Shellcode et d'autres valeurs comme la protection (RW) doivent être définies manuellement dans ce portage. Dans le dépôt d'origine, l'adresse de l'appelant du Shellcode était récupérée automatiquement.
Le fichier Example.nim contient tout ce dont vous avez besoin pour commencer. Bien sûr, lorsque vous utilisez du C2-Shellcode, vous n'avez pas besoin d'appeler Sleep vous-même (c'est juste pour déclencher tout pour le PoC), cela devrait être fait par votre C2 lui-même. Pour le moment, ce n'est compatible qu'avec les frameworks C2 qui utilisent la fonction Win32 Sleep, mais si vous modifiez le Hook pour une autre fonction, cela fonctionnera de la même manière.
import winim
import Fluctuation
echo "Trying to hook Sleep"
if (hookSleep()):
echo "Hooked Sleep successfully!"
type
PocArray = array[12, byte]
let names: PocArray = [byte 0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA]
g_fluctuationData.shellcodeAddr = unsafeAddr names[0]
echo "Shellcode address:"
echo repr(g_fluctuationData.shellcodeAddr)
g_fluctuationData.shellcodeSize = size_t(len(names))
echo "Shellcode Size:"
echo repr(g_fluctuationData.shellcodeSize)
when defined(amd64):
g_fluctuationData.encodeKey = 0xDEADB33f
when defined(i386):
g_fluctuationData.encodeKey = 0xDEAD
g_fluctuationData.currentlyEncrypted = false
g_fluctuationData.protect = PAGE_READWRITE
g_fluctuate = FluctuateToRW
echo "Calling Sleep"
Sleep(2500)
echo "Everything went fine and as expected"
else:
echo "Failed to hook Sleep"
quit(1)
Le test du PoC de chiffrement peut être effectué, par exemple, comme ceci :
nim c --debuginfo --linedir:on Example.nim
Démarrer avec un débogueur :
gdb Example.exe
Définir des points d'arrêt avant et après Sleep :
# Before encryption
break Example.nim:31
# After encryption
break Fluctuation.nim:98
# Original value restored
break Example.nim:33
Ensuite, vérifiez la valeur de l'adresse du Shellcode pour chaque point d'arrêt comme ceci :

La fluctuation vers NA ne fonctionne pas encore, car le Vectored Exception Handler n'a jamais été déclenché dans mon test, mais l'application a planté. Je devrai effectuer d'autres tests/dépannages à l'avenir. N'hésitez pas à tester vous-même ! :-)