
Appels système indirects propres avec falsification d'appels système.
SyscallRevenant est une nouvelle méthode pour effectuer des appels système indirects propres.
Le composant principal résout dynamiquement les System Service Numbers (SSN) et les adresses de l'instruction syscall.
Cela est réalisé en activant le trap flag pendant l'exécution.
Le composant secondaire est le tampering via le remplacement de paramètres avant un syscall.
Cette combinaison est conçue pour contourner les hooks en espace utilisateur lors de l'invocation suivante du syscall tout en substituant les paramètres initialement présentés.
Avertissement : Ce projet a uniquement un but éducatif et de test. Ne l'utilisez pas sur des machines que vous n'êtes pas autorisé à utiliser. Ne l'utilisez pas pour exploiter et communiquer avec des machines que vous n'êtes pas autorisé à utiliser.
Les appels système indirects sont une méthode d'exécution d'instructions syscall dans un espace utilisateur de confiance.
Si un utilisateur trouve une instruction syscall, il peut y sauter indirectement.
Un événement activé pendant une session de traçage peut révéler l'adresse de retour immédiatement après l'instruction.
Cela ne prend pas en compte les hooks en espace utilisateur des Endpoint Detection & Response (EDR).
Un EDR peut insérer des hooks dans ntdll.dll, rendant ainsi obsolète le processus de recherche des SSN et des instructions syscall.
Entrer dans un hook bénéficiera au thread propriétaire, sans augmenter le score de malveillance.
Observer une entrée dans une fonction et observer l'opération résultante sont deux choses différentes.
RevenantSyscalls examine cet écart.
Les sections suivantes décrivent les deux composants principaux du projet.
Le premier composant résout les adresses de fonctions à partir de ntdll.dll chargé par le processus.
Un parcours par trap peut ensuite être effectué si les informations de syscall sont nécessaires.
Le second composant effectue un saut indirect vers les informations de fonction sauvegardées.
La lecture du registre de segment permet de récupérer le Process Environment Block (PEB).
Le LoaderData est un champ du PEB qui contient les données chargées avec chaque processus.
LoaderData contient des informations sur les modules chargés avec chaque processus.
Les noms de modules et les adresses de base existent dans les entrées de module.
Les informations d'export d'une Dynamically Linked Library (DLL) décrivent les symboles qu'elle exporte. Les métadonnées d'export permettent de localiser les symboles exportés. L'index d'une fonction ne s'applique qu'aux noms et aux ordinaux de noms. Le hachage d'un nom de fonction est la meilleure approche pour les environnements à faible mémoire.
Un vectored exception handler est un mécanisme de gestion des exceptions qui intercepte les exceptions depuis n'importe où dans un processus.
L'activation du trap flag provoque une exception EXCEPTION_SINGLE_STEP sur l'instruction suivante exécutée.
Un vectored exception handler personnalisé peut inspecter le RIP et vérifier la présence d'un syscall.
En réinitialisant de manière répétée le trap flag, l'adresse du syscall sera découverte et le SSN sauvegardé.
Recherche de syscall
|
Exécution de syscall
|
Chaque syscall a sa recherche initiale d'informations de syscall ; Les hooks seront entrés pour récupérer les informations de syscall. Ensuite, un saut indirect sera effectué vers le syscall. Il y aura un spoofing de RIP associé (depuis l'entrée d'origine). Lors de la ré-entrée, les paramètres initiaux ont été altérés.
Du point de vue de l'Event Tracing for Windows (ETW), les événements éventuellement émis sont : SysEnter, SysExit, et StackWalk pour l'un ou l'autre.
Si un EDR construit des événements similaires et comparables, ceux-ci sembleront presque identiques.
Les seules différences résideront dans des horodatages Query Performance Counter (QPC) radicalement différents.
src/AsmRevenant.asm REAL_RTN: DQ 0
FAKE_RTN: DQ 0
; If a syscall information lookup is in progress, the
; initial entry return address needs to be preserved.
MOV RAX, QWORD PTR [RSP]
MOV QWORD PTR [FAKE_RTN], RAX
; Once the re-entry is made, the real return is saved,
; and the current is spoofed with initial return.
MOV RAX, QWORD PTR [RSP]
MOV QWORD PTR [REAL_RTN], RAX
MOV RAX, QWORD PTR [FAKE_RTN]
MOV QWORD PTR [RSP], RAX
src/Revenant.cLONG VectoredExceptionHandler(EXCEPTION_POINTERS *BreakPoint) {
...
// If a syscall information lookup is being made, the
// syscall instruction address is saved, the SSN is
// saved, and the return is rerouted.
if (LookupInProgress && *(USHORT*)BreakPoint->Address == 0x050F) {
SyscallInstruction = BreakPoint->Address;
SyscallSSN = BreakPoint->Context->Rax;
BreakPoint->Context->Rip = SyscallExit;
}
// When re-entered, if the previous instruction was
// a syscall, reset return address, and exit.
if (!LookupInProgress && *(USHORT*)(BreakPoint->Address - 2) == 0x050F) {
*(VOID**)BreakPoint->Context->Rsp = REAL_RTN;
BreakPoint->Context->Rip = SyscallExit;
}
...
}