
Implémentation PoC d'un spoofeur de pile d'appels entièrement dynamique
Implémentation d’un preuve de concept (PoC) d’un spoofeur de pile d’appels entièrement dynamique.
SilentMoonwalk est une implémentation PoC d’un spoofeur de pile d’appels entièrement dynamique, mettant en œuvre une technique permettant de supprimer l’appelant d’origine de la pile d’appels, en utilisant une chaîne ROP pour désynchroniser le déroulement de la pile du flux de contrôle.
Ce PoC est le résultat d’une recherche conjointe sur le sujet du spoofing de pile. Les auteurs de la recherche sont :
Je tiens à souligner que ce travail aurait été impossible sans le travail de Waldo-IRC et Trickster0, qui ont tous deux contribué aux premières étapes du PoC et à la recherche qui le sous-tend.
Ce dépôt présente une implémentation PoC pour usurper la pile d’appels lors de l’appel d’API Windows arbitraires.
Cette tentative a été inspirée par ce fil Twitter et ce fil Twitter, où le sensei namazso a montré et suggéré d’étendre l’approche de déroulement de pile avec une chaîne ROP pour à la fois désynchroniser le déroulement du flux de contrôle réel et restaurer la pile d’origine par la suite.
Ce PoC tente de faire quelque chose de similaire à ce qui précède et utilise une pile de désynchronisation pour masquer complètement la pile d’appels d’origine, supprimant également l’image de base de l’EXE de celle-ci. Au retour, un gadget ROP est invoqué pour restaurer la pile d’origine. Dans le code, ce processus est répété 10 fois dans une boucle, en utilisant différentes trames à chaque itération, pour prouver la stabilité.
L’outil prend actuellement en charge 2 modes, dont l’un est en fait un correctif erroné pour un frame POP RBP non fonctionnel identifié, qui fonctionne en décalant le RSP actuel et en ajoutant deux faux frames à la pile d’appels. Comme il fonctionne avec des frames synthétiques, je me réfère à ce mode sous le nom de « SYNTHETIC ».
Lors de la sélection du frame qui se déroule en dépilant le registre RBP depuis la pile, l’outil peut sélectionner un frame inapproprié, aboutissant à une pile d’appels brusquement coupée, comme observable ci-dessous.

Une solution stupide au problème consisterait à créer deux faux frames et à les relier à la pile d’appels coupée. Cela créerait une sorte de pile d’appels apparemment légitime, même sans un frame approprié qui se déroule en appelant POP RBP, mais :
Le résultat du _spoof synthétique peut être observé dans l’image ci-dessous :

Figure 1 : Windows 10 - Pile d’appels apparemment légitime, non déroulable, où le module EXE a été complètement supprimé (appel de la fonction sans paramètre getchar)
Remarque : Ce mode de fonctionnement est désactivé par défaut. Pour l’activer, définissez CALLSTACK_TYPE sur 1
Ce mode est la bonne solution au problème ci-dessus, où le frame inapproprié est simplement remplacé par un autre approprié.

Figure 2 : Windows 10 - Pile d’appels légitime, déroulable, où le module EXE a été complètement supprimé (appel de la fonction à 4 paramètres MessageBoxA)
Dans le dépôt, vous trouverez également un petit utilitaire pour inspecter les fonctions d’exécution, qui peut être utile pour analyser les entrées de fonctions d’exécution.
UnwindInspector.exe -h
Unwind Inspector v0.100000
Mandatory args:
-m <module>: Target DLL
-f <function>: Target Function
-a <function-address>: Target Function Address
Exemple de sortie :
UnwindInspector.exe -m kernelbase -a 0x7FFAAE12182C
[*] Using function address 0x7ffaae12182c
Runtime Function (0x000000000000182C, 0x00000000000019ED)
Unwind Info Address: 0x000000000026AA88
Version: 0
Ver + Flags: 00000000
SizeOfProlog: 0x1f
CountOfCodes: 0xc
FrameRegister: 0x0
FrameOffset: 0x0
UnwindCodes:
[00h] Frame: 0x741f - 0x04 - UWOP_SAVE_NONVOL (RDI, 0x001f)
[01h] Frame: 0x0015 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0015)
[02h] Frame: 0x641f - 0x04 - UWOP_SAVE_NONVOL (RSI, 0x001f)
[03h] Frame: 0x0014 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0014)
[04h] Frame: 0x341f - 0x04 - UWOP_SAVE_NONVOL (RBX, 0x001f)
[05h] Frame: 0x0012 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0012)
[06h] Frame: 0xb21f - 0x02 - UWOP_ALLOC_SMALL (R11, 0x001f)
[07h] Frame: 0xf018 - 0x00 - UWOP_PUSH_NONVOL (R15, 0x0018)
[08h] Frame: 0xe016 - 0x00 - UWOP_PUSH_NONVOL (R14, 0x0016)
[09h] Frame: 0xd014 - 0x00 - UWOP_PUSH_NONVOL (R13, 0x0014)
[0ah] Frame: 0xc012 - 0x00 - UWOP_PUSH_NONVOL (R12, 0x0012)
[0bh] Frame: 0x5010 - 0x00 - UWOP_PUSH_NONVOL (RBP, 0x0010)
Pour construire le PoC et observer un comportement similaire à celui de l’image, assurez-vous de :
/GS-)/Od)/GL)/Os, /Ot)/Oi)Il convient de mentionner les travaux antérieurs sur ce sujet, qui ont jeté les bases de ce travail.