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
EDRSandblast — Arme des pilotes signés vulnérables pour contourner les rappels noyau de l'EDR, les rappels d'objets, le fournisseur ETW TI et les hooks en espace utilisateur pour le vidage mémoire de LSASS et l'extraction d'identifiants. | Kitploit
Outils/GitHubGitHub/wavestone-cdt/edrsandblast
Outils DéfensifsEscalade de PrivilègesExploitationTests d'IntrusionRed Teaming
GitHubwavestone-cdt/edrsandblast

EDRSandblast

Arme des pilotes signés vulnérables pour contourner les rappels noyau de l'EDR, les rappels d'objets, le fournisseur ETW TI et les hooks en espace utilisateur pour le vidage mémoire de LSASS et l'extraction d'identifiants.

Voir le dépôt
1.8k320il y a 2 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

EDRSandBlast

EDRSandBlast est un outil écrit en C qui exploite un pilote signé vulnérable pour contourner les détections EDR (callbacks de routines de notification, callbacks d'objets et fournisseur ETW TI) et les protections LSASS. De multiples techniques de désaccrochage (unhooking) en mode utilisateur sont également implémentées pour échapper à la surveillance en mode utilisateur.

À la date de publication, la combinaison de techniques en mode utilisateur (--usermode) et en mode noyau (--kernelmode) a été utilisée pour vider la mémoire de LSASS sous la surveillance d'EDR, sans être bloquée ni générer d'événements liés au « Credential Dumping » dans la console (cloud) du produit. Les tests ont été effectués sur 3 produits EDR distincts et ont été couronnés de succès dans chaque cas.

Description

Contournement d'EDR par suppression des routines de notification du noyau

Les produits EDR utilisent les callbacks « Notify Routines » du noyau sous Windows pour être informés par le noyau de l'activité du système, comme la création de processus et de threads, et le chargement d'images (exe / DLL).

Ces callbacks du noyau sont définis depuis l'espace noyau, généralement par le pilote implémentant les callbacks, à l'aide d'un certain nombre d'API documentées (nt!PsSetCreateProcessNotifyRoutine, nt!PsSetCreateThreadNotifyRoutine, etc.). Ces API ajoutent des routines de callback fournies par le pilote à des tableaux non documentés de routines dans l'espace noyau :

  • PspCreateProcessNotifyRoutine pour la création de processus
  • PspCreateThreadNotifyRoutine pour la création de threads
  • PspLoadImageNotifyRoutine pour le chargement d'images

EDRSandBlast énumère les routines définies dans ces tableaux et supprime toute routine de callback liée à une liste prédéfinie de pilotes EDR (plus de 1000 pilotes de produits de sécurité pris en charge, voir la section sur la détection des pilotes EDR). L'énumération et la suppression sont possibles grâce à l'exploitation d'une primitive arbitraire de lecture/écriture en mémoire du noyau fournie par l'exploitation d'un pilote vulnérable (voir la section sur les pilotes vulnérables).

Les décalages des tableaux mentionnés ci-dessus sont récupérés à l'aide de plusieurs techniques, veuillez vous référer à la section sur les décalages.

Contournement d'EDR par suppression des callbacks d'objets

Les produits EDR (et même EPP) enregistrent souvent des « callbacks d'objets » via l'API noyau nt!ObRegisterCallbacks. Ces callbacks permettent au produit de sécurité d'être notifié à chaque création de handle sur des types d'objets spécifiques (les callbacks d'objets liés aux processus, threads et bureaux sont désormais pris en charge par Windows). Une création de handle peut se produire lors de l'ouverture d'un objet (appel à OpenProcess, OpenThread, etc.) ainsi que lors de la duplication de handle (appel à DuplicateHandle, etc.).

En étant notifié par le noyau pour chacune de ces opérations, un produit de sécurité peut analyser la légitimité de la création du handle (par exemple, un processus inconnu tente d'ouvrir LSASS), et même la bloquer si une menace est détectée.

Lors de chaque enregistrement de callback utilisant ObRegisterCallbacks, un nouvel élément est ajouté à la liste doublement chaînée CallbackList présente dans l'objet _OBJECT_TYPE décrivant le type d'objet affecté par le callback (processus, thread ou bureau). Malheureusement, ces éléments sont décrits par une structure qui n'est ni documentée ni publiée dans les fichiers de symboles par Microsoft. Cependant, son étude à partir de différentes versions de ntoskrnl.exe semble indiquer que la structure n'a pas changé entre (au moins) les builds Windows 10 10240 et 22000 (de 2015 à 2022).

La structure mentionnée, représentant un enregistrement de callback d'objet, est la suivante :```C typedef struct OB_CALLBACK_ENTRY_t { LIST_ENTRY CallbackList; // linked element tied to _OBJECT_TYPE.CallbackList OB_OPERATION Operations; // bitfield : 1 for Creations, 2 for Duplications BOOL Enabled; // self-explanatory OB_CALLBACK* Entry; // points to the structure in which it is included POBJECT_TYPE ObjectType; // points to the object type affected by the callback POB_PRE_OPERATION_CALLBACK PreOperation; // callback function called before each handle operation POB_POST_OPERATION_CALLBACK PostOperation; // callback function called after each handle operation KSPIN_LOCK Lock; // lock object used for synchronization } OB_CALLBACK_ENTRY;

root@kitploit:~
La structure `OB_CALLBACK` mentionnée ci-dessus est également non documentée, et est définie
par :```C
typedef struct OB_CALLBACK_t {
    USHORT Version;                           // usually 0x100
    USHORT OperationRegistrationCount;        // number of registered callbacks
    PVOID RegistrationContext;                // arbitrary data passed at registration time
    UNICODE_STRING AltitudeString;            // used to determine callbacks order
    struct OB_CALLBACK_ENTRY_t EntryItems[1]; // array of OperationRegistrationCount items
    WCHAR AltitudeBuffer[1];                  // is AltitudeString.MaximumLength bytes long, and pointed by AltitudeString.Buffer
} OB_CALLBACK;

Afin de désactiver les callbacks d'objets enregistrés par l'EDR, trois techniques sont implémentées dans EDRSandblast ; cependant une seule est activée pour le moment.

Utilisation du champ Enabled de OB_CALLBACK_ENTRY

C'est la technique activée par défaut dans EDRSandblast. Afin de détecter et désactiver les callbacks d'objets liés à l'EDR, la liste CallbackList située dans les objets _OBJECT_TYPE associés aux types Process et Thread est parcourue. Les deux _OBJECT_TYPEs sont pointés par des symboles globaux publics dans le noyau, PsProcessType et PsThreadType.

Chaque élément de la liste est supposé correspondre à la structure OB_CALLBACK_ENTRY décrite ci-dessus (hypothèse qui semble être vérifiée au moins dans toutes les builds de Windows 10 au moment de la rédaction). Les fonctions définies dans les champs PreOperation et PostOperation sont localisées pour vérifier si elles appartiennent à un pilote EDR, et si c'est le cas, les callbacks sont simplement désactivés en basculant le drapeau Enabled.

Bien qu'il s'agisse d'une technique assez sûre, elle a l'inconvénient de reposer sur une structure non documentée ; pour réduire le risque de manipulation non sécurisée de cette structure, des vérifications de base sont effectuées pour valider que certains champs ont les valeurs attendues :

  • Enabled est soit TRUE soit FALSE (ne riez pas, un BOOL est un int, donc il pourrait valoir autre chose que 1 ou 0);
  • Operations est OB_OPERATION_HANDLE_CREATE, OB_OPERATION_HANDLE_DUPLICATE ou les deux ;
  • ObjectType pointe sur PsProcessType ou PsThreadType.

Dissocier la CallbackList des threads et des processus

Une autre stratégie qui ne repose pas sur une structure non documentée (et est donc théoriquement plus robuste face aux changements du noyau NT) consiste à dissocier la totalité de la CallbackList pour les processus et les threads. L'objet _OBJECT_TYPE est le suivant :```C struct _OBJECT_TYPE { LIST_ENTRY TypeList; UNICODE_STRING Name; [...] _OBJECT_TYPE_INITIALIZER TypeInfo; [...] LIST_ENTRY CallbackList; }

root@kitploit:~
Faire pointer les pointeurs `Flink` et `Blink` de la `LIST_ENTRY` de `CallbackList` vers
la `LIST_ENTRY` elle-même rend effectivement la liste vide. Comme la structure `_OBJECT_TYPE`
est publiée dans les symboles du noyau, la technique ne repose pas sur des décalages/structures
codés en dur. Cependant, elle présente quelques inconvénients.

Le premier est de ne pas pouvoir désactiver uniquement les callbacks de l'EDR ; en effet, la technique
affecte tous les callbacks d'objets qui auraient pu être enregistrés par un logiciel « légitime ».
Il convient néanmoins de noter que les callbacks d'objets ne sont utilisés par aucun composant
préinstallé sur Windows 10 (au moment de la rédaction), donc leur désactivation ne devrait pas affecter
la stabilité de la machine (encore moins si la désactivation n'est que temporaire).

Le second inconvénient est que les opérations sur les handles de processus ou de threads sont vraiment
fréquentes (presque continues) dans le fonctionnement normal du système d'exploitation. Ainsi, si la
primitive d'écriture dans le noyau utilisée ne peut pas effectuer une écriture `QWORD` « de manière
atomique », il y a de fortes chances que le pointeur `_OBJECT_TYPE.CallbackList.Flink` soit accédé
par le noyau au milieu de sa réécriture. Par exemple, le pilote vulnérable MSI `RTCore64.sys` ne peut
effectuer qu'une écriture `DWORD` à la fois, donc 2 IOCTL distincts seront nécessaires pour écraser
le pointeur, entre lesquels le noyau a une forte probabilité de l'utiliser (provoquant un crash).
En revanche, le pilote vulnérable DELL `DBUtil_2_3.sys` peut effectuer des écritures de tailles
arbitraires en un seul IOCTL, donc utiliser cette méthode avec lui ne risque pas de provoquer un
crash.

#### Désactiver complètement les callbacks d'objets
Une dernière technique que nous avons trouvée consiste à désactiver entièrement le support des
callbacks d'objets pour les threads et les processus. À l'intérieur de la structure `_OBJECT_TYPE`
correspondant aux types processus et thread se trouve un champ `TypeInfo`, suivant la structure
documentée `_OBJECT_TYPE_INITIALIZER`. Ce dernier contient un champ de bits `ObjectTypeFlags`,
dont le drapeau `SupportsObjectCallbacks` détermine si le type d'objet décrit (Processus, Thread,
Bureau, Jeton, Fichier, etc.) supporte ou non l'enregistrement de callbacks d'objets. Comme indiqué
précédemment, seuls les types d'objets Processus, Thread et Bureau supportent ces callbacks sur une
installation Windows au moment de la rédaction.

Puisque le bit `SupportsObjectCallbacks` est vérifié par `ObpCreateHandle` ou `ObDuplicateObject`
avant même de lire la `CallbackList` (et avant d'exécuter les callbacks, bien sûr), inverser ce bit
à l'exécution dans le noyau désactive effectivement toute exécution de callbacks d'objets.

Le principal inconvénient de cette méthode est simplement que *KPP* (« *PatchGuard* ») surveille
l'intégrité de certaines (toutes ?) structures `_OBJECT_TYPE`, et déclenche un
[`0x109 Bug Check`](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/bug-check-0x109---critical-structure-corruption)
avec le paramètre 4 égal à `0x8`, ce qui signifie qu'une structure de type d'objet a été modifiée.

Cependant, effectuer la désactivation / réactivation (et l'action « malveillante » entre les deux)
assez rapidement devrait suffire à « distancer » *PatchGuard* (sauf si vous êtes malchanceux et
qu'une vérification périodique est effectuée au mauvais moment).

### Contournement de l'EDR via le déliement des callbacks des minifiltres
Le système Windows Filter Manager permet à un EDR de charger un pilote « minifilter » et
d'enregistrer des callbacks afin d'être notifié des opérations d'E/S, telles que l'ouverture de
fichiers, la lecture, l'écriture, etc.

Voici un bref résumé des différentes structures internes utilisées par le gestionnaire de filtres :
- Le gestionnaire de filtres établit un « frame » (`_FLTP_FRAME`) comme structure racine ;
- Une structure « volume » (`_FLT_VOLUME`) est instanciée pour chaque « disque » géré par le
gestionnaire de filtres (peut être des partitions, des clichés instantanés, ou des volumes spéciaux
correspondant aux pipes nommés ou aux systèmes de fichiers distants) ;
- À chaque pilote minifilter enregistré correspond une structure « filtre » (`_FLT_FILTER`),
décrivant diverses propriétés telles que ses opérations supportées ;
- Ces minifiltres ne sont pas tous attachés à chaque volume ; une structure « instance »
(`_FLT_INSTANCE`) est créée pour marquer chaque association
filtre<->volume ;
- Les minifiltres enregistrent des fonctions de callback qui doivent être exécutées avant et/ou après
des opérations spécifiques (ouverture de fichier, écriture, lecture, etc.). Ces callbacks sont
décrits dans des structures `_CALLBACK_NODE`, et peuvent être accédés de différentes manières :
  - Un tableau de tous les `_CALLBACK_NODE` implémentés par une instance d'un minifilter
    peut être trouvé dans la structure `_FLT_INSTANCE` ; le tableau est indexé par le code
    « fonction majeure » IRP, une constante représentant les opérations gérées par les
    callbacks (`IRP_MJ_CREATE`, `IRP_MJ_READ`, etc.).
  - De plus, tous les `_CALLBACK_NODE` implémentés par les instances liées à un volume spécifique
  sont regroupés dans des listes chaînées, stockées dans le tableau
  `_FLT_VOLUME.Callbacks.OperationLists` indexé par les codes de fonction majeure IRP.

Ces différentes structures sont parcourues par `EDRSandblast` pour détecter les filtres qui sont
associés à des pilotes liés à l'EDR, et les nœuds de callback contenant des fonctions de
surveillance sont énumérés. Pour désactiver leur effet, les nœuds sont déliés de leurs listes,
les rendant temporairement invisibles pour le gestionnaire de filtres.

Ainsi, pendant une période spécifiée, l'EDR peut être complètement inconscient de toute opération
sur les fichiers. Un exemple simple serait la création d'un fichier de dump mémoire lsass sur le
disque, qui ne déclencherait aucune analyse de la part de l'EDR, et donc aucune détection basée
sur le fichier lui-même.

### Contournement de l'EDR via la désactivation du fournisseur ETW Microsoft-Windows-Threat-Intelligence

Le fournisseur `ETW Microsoft-Windows-Threat-Intelligence` enregistre des données sur les
utilisations de certaines API Windows couramment utilisées de manière malveillante. Cela inclut
l'API `nt!MiReadWriteVirtualMemory`, appelée par `nt!NtReadVirtualMemory` (qui est
utilisée pour dumper la mémoire de `LSASS`) et surveillée par la fonction
`nt!EtwTiLogReadWriteVm`.

Les produits EDR peuvent consommer les journaux produits par le fournisseur `ETW TI` via
des services ou des processus s'exécutant respectivement sous les droits
`SERVICE_LAUNCH_PROTECTED_ANTIMALWARE_LIGHT` ou
`PS_PROTECTED_ANTIMALWARE_LIGHT`, et associés à un pilote
`Early Launch Anti Malware (ELAM)`.

Comme publié par
[`slaeryan` dans un article de blog `CNO Development Labs`](https://public.cnotools.studio/bring-your-own-vulnerable-kernel-driver-byovkd/exploits/data-only-attack-neutralizing-etwti-provider),
le fournisseur `ETW TI` peut être désactivé complètement en patchant, dans la mémoire du noyau,
son attribut `ProviderEnableInfo` à `0x0`. Référez-vous à l'excellent article de blog susmentionné
pour plus d'informations sur la technique.

De manière similaire à la suppression des callbacks du noyau, les décalages nécessaires de
`ntoskrnl.exe` (`nt!EtwThreatIntProvRegHandleOffset`, `GuidEntry` de `_ETW_REG_ENTRY`, et
`ProviderEnableInfo` de `_ETW_GUID_ENTRY`) sont calculés dans le fichier
`NtoskrnlOffsets.csv` pour un certain nombre de versions du noyau Windows.

### Contournement de l'EDR via le contournement du hooking en espace utilisateur
#### Comment fonctionne le hooking en espace utilisateur
Afin de surveiller facilement les actions effectuées par les processus, les produits EDR déploient
souvent un mécanisme appelé *hooking en espace utilisateur*. Tout d'abord, les produits EDR
enregistrent un callback du noyau (généralement des callbacks de *chargement d'image* ou de
*création de processus*, voir ci-dessus) qui leur permet d'être notifiés à chaque démarrage de
processus.

Lorsqu'un processus est chargé par Windows, et avant qu'il ne démarre réellement, l'EDR est capable
d'injecter une DLL personnalisée dans l'espace d'adressage du processus, qui contient sa logique
de surveillance. Pendant le chargement, cette DLL injecte des « hooks » au début de chaque fonction
qui doit être surveillée par l'EDR. À l'exécution, lorsque les fonctions surveillées sont appelées
par le processus sous surveillance, ces hooks redirigent le flux de contrôle vers un code de
supervision présent dans la DLL de l'EDR, ce qui lui permet d'inspecter les arguments et les
valeurs de retour de ces appels.

La plupart du temps, les fonctions surveillées sont des appels système (tels que
`NtReadVirtualMemory`, `NtOpenProcess`, etc.), dont les implémentations résident dans `ntdll.dll`.
Intercepter les appels aux fonctions `Nt*` permet aux produits d'être aussi proches que possible
de la frontière espace utilisateur / espace noyau (tout en restant en espace utilisateur), mais
les fonctions de certaines DLL de plus haut niveau peuvent également être surveillées.

Voici des exemples de la même fonction, avant et après avoir été hookée par le produit EDR :```assembly
NtProtectVirtualMemory   proc near
	mov r10, rcx
	mov eax, 50h
	test byte ptr ds:7FFE0308h, 1
	jnz short loc_18009D1E5
	syscall
	retn
loc_18009D1E5:
	int 2Eh
	retn
NtProtectVirtualMemory   endp			

Please provide the Markdown content to translate.```assembly NtProtectVirtualMemory proc near jmp sub_7FFC74490298 ; --> "hook", jump to EDR analysis function int 3 ; overwritten instructions int 3 ; overwritten instructions int 3 ; overwritten instructions test byte_7FFE0308, 1 ; <-- execution resumes here after analysis jnz short loc_7FFCB44AD1E5 syscall retn loc_7FFCB44AD1E5: int 2Eh retn NtProtectVirtualMemory endp

root@kitploit:~
#### Détection des hooks
Les hooks en espace utilisateur ont la « faiblesse » de se trouver dans la mémoire utilisateur, ce qui signifie qu'ils sont
directement observables et modifiables par le processus surveillé. Pour détecter automatiquement
les hooks dans l'espace d'adressage du processus, l'idée principale est de comparer les différences entre
la DLL originale sur disque et la bibliothèque résidant en mémoire, qui a été potentiellement
modifiée par un EDR. Pour effectuer cette comparaison, EDRSandblast suit les étapes suivantes :
* La liste de toutes les DLL chargées est énumérée grâce à la `InLoadOrderModuleList` située
  dans le `PEB` (pour éviter d'appeler une API qui pourrait être surveillée et suspecte)
* Pour chaque DLL chargée, son contenu sur disque est lu et ses en-têtes analysés. La
  bibliothèque correspondante, résidant en mémoire, est également analysée pour identifier les sections, les exports,
  etc.
* Les relocalisations de la DLL sont analysées et appliquées, en tenant compte de l'adresse de base de la
  bibliothèque chargée correspondante. Cela permet au contenu de la bibliothèque en mémoire et de la DLL
  provenant du disque d'avoir exactement le même contenu (sur les sections où les relocalisations sont appliquées),
  rendant ainsi la comparaison fiable.
* Les fonctions exportées sont énumérées et les premiers octets des versions « en mémoire » et « sur disque »
  sont comparés. Toute différence indique une altération effectuée après
  le chargement de la DLL, et est donc très probablement un hook d'EDR.

Remarque : Le processus peut être généralisé pour trouver des différences n'importe où dans les sections non inscriptibles
et pas seulement au début des fonctions exportées, par exemple si les produits EDR commencent à
appliquer des hooks au milieu d'une fonction :) Ainsi, non utilisé par l'outil, cela a été
implémenté dans `findDiffsInNonWritableSections`.

Afin de contourner la surveillance effectuée par ces hooks, plusieurs techniques sont
possibles, chacune ayant ses avantages et inconvénients.

#### Contournement de hook par ... dé-hooking
La méthode la plus intuitive pour contourner la surveillance basée sur les hooks est de supprimer les
hooks. Puisque les hooks sont présents dans une mémoire accessible par le processus lui-même, pour
supprimer un hook, le processus peut simplement :
* Modifier les permissions de la page où se trouve le hook (RX -> RWX ou RW)
* Écrire les octets d'origine connus grâce au contenu de la DLL sur disque
* Rétablir les permissions à RX

Cette approche est assez simple et peut être utilisée pour supprimer tous les hooks détectés d'un seul
coup. Effectuée par un outil offensif au début de son exécution, elle permet au reste du code
d'être complètement ignorant du mécanisme de hooking et de fonctionner normalement sans être
surveillé.

Cependant, elle présente deux inconvénients majeurs. L'EDR surveille probablement l'utilisation de
`NtProtectVirtualMemory`, donc l'utiliser pour modifier les permissions de la page où les
hooks ont été installés est (au moins conceptuellement) une mauvaise idée. Aussi, si un thread est
exécuté par l'EDR et vérifie périodiquement l'intégrité des hooks, cela pourrait également
déclencher une détection.

Pour les détails d'implémentation, consultez le chemin de code de la fonction `unhook()` lorsque `unhook_method` est
`UNHOOK_WITH_NTPROTECTVIRTUALMEMORY`.

**Remarque importante : par souci de simplicité, cette technique est implémentée dans EDRSandblast comme la
technique de base utilisée pour *démontrer* les autres techniques de contournement ; chacune d'elles montre
comment obtenir une version non surveillée de `NtProtectVirtualMemory`, mais effectue la même opération ensuite (dé-hooking d'un hook spécifique).**

#### Contournement de hook par un trampoline personnalisé
Pour contourner un hook spécifique, il est possible de simplement « sauter par‑dessus » et d'exécuter le reste de
la fonction tel quel. D'abord, les octets d'origine de la fonction surveillée, qui ont été
écrasés par l'EDR pour installer le hook, doivent être récupérés à partir du fichier DLL. Dans notre
exemple de code précédent, cela correspondrait aux octets correspondant aux instructions suivantes :```assembly
mov r10, rcx
mov eax, 50h

Identifier ces octets est une tâche simple puisque nous sommes capables d'effectuer un diff propre des versions mémoire et disque de la bibliothèque, comme décrit précédemment. Ensuite, nous assemblons une instruction de saut qui est construite pour rediriger le flux de contrôle vers le code suivant immédiatement le hook, à l'adresse `NtProtectVirtualMemory + sizeof(overwritten_instructions)````assembly jmp NtProtectVirtualMemory+8

root@kitploit:~
Enfin, nous concaténons ces opcodes, les stockons dans une mémoire (nouvellement) exécutable et conservons un pointeur vers eux. Cet objet est appelé un "*trampoline*" et peut ensuite être utilisé comme un pointeur de fonction, strictement équivalent à la fonction originale `NtProtectVirtualMemory`.

Le principal avantage de cette technique, comme pour toutes les techniques ci-dessous, est que le hook n'est jamais effacé, donc toute vérification d'intégrité effectuée sur les hooks par l'EDR devrait réussir. Cependant, elle nécessite d'allouer de la mémoire d'abord accessible en écriture puis exécutable, ce qui est typique d'une allocation de shellcode, attirant ainsi l'attention de l'EDR.

Pour les détails d'implémentation, consultez le chemin de code de la fonction `unhook()` lorsque `unhook_method` est `UNHOOK_WITH_INHOUSE_NTPROTECTVIRTUALMEMORY_TRAMPOLINE`. Veuillez noter que la technique n'est démontrée que dans notre implémentation et est, en fin de compte, utilisée pour **supprimer** les hooks de la mémoire, comme toutes les techniques ci-dessous.

#### Contournement de hook en utilisant le trampoline de l'EDR lui-même
Le produit EDR, pour que son hook fonctionne, doit sauvegarder quelque part en mémoire les opcodes qu'il a supprimés. Pire (*ou "mieux", du point de vue de l'attaquant*), pour utiliser efficacement les instructions originales, l'EDR s'est probablement alloué un *trampoline* quelque part pour exécuter la fonction originale après avoir intercepté l'appel.

Ce trampoline peut être recherché et utilisé comme remplacement de la fonction hookée, sans avoir besoin d'allouer de la mémoire exécutable, ni d'appeler une API autre que `VirtualQuery`, qui n'est très probablement pas surveillée étant une fonction anodine.

Pour trouver le trampoline en mémoire, nous parcourons tout l'espace d'adressage en utilisant `VirtualQuery` à la recherche de mémoire validée et exécutable. Pour chaque région de mémoire de ce type, nous la scannons pour trouver une instruction de saut qui cible l'adresse suivant les instructions écrasées (`NtProtectVirtualMemory+8` dans notre exemple précédent). Le trampoline peut alors être utilisé pour appeler la fonction hookée sans déclencher le hook.

Cette technique fonctionne étonnamment bien car elle récupère presque tous les trampolines sur les EDR testés. Pour les détails d'implémentation, consultez le chemin de code de la fonction `unhook()` lorsque `unhook_method` est `UNHOOK_WITH_EDR_NTPROTECTVIRTUALMEMORY_TRAMPOLINE`.

#### Contournement de hook en utilisant une DLL en double
Une autre méthode simple pour accéder à une version non surveillée de la fonction `NtProtectVirtualMemory` consiste à charger une copie en double de la bibliothèque `ntdll.dll` dans l'espace d'adressage du processus. Étant donné que deux DLL identiques peuvent être chargées dans le même processus, à condition qu'elles aient des noms différents, nous pouvons simplement copier le fichier légitime `ntdll.dll` vers un autre emplacement, le charger en utilisant `LoadLibrary` (ou réimplémenter le processus de chargement), et accéder à la fonction en utilisant `GetProcAddress` par exemple.

Cette technique est très simple à comprendre et à implémenter, et a de bonnes chances de succès, car la plupart des produits EDR ne réinstallent pas de hooks sur les DLL nouvellement chargées une fois le processus en cours d'exécution. Cependant, le principal inconvénient est que copier des binaires signés par Microsoft sous un nom différent est souvent considéré comme suspect par les produits EDR eux-mêmes.

Cette technique est néanmoins implémentée dans `EDRSandblast`. Pour les détails d'implémentation, consultez le chemin de code de la fonction `unhook()` lorsque `unhook_method` est `UNHOOK_WITH_DUPLICATE_NTPROTECTVIRTUALMEMORY`.

#### Contournement de hook en utilisant des appels système directs
Afin d'utiliser des fonctions liées aux appels système, un programme peut réimplémenter les appels système (en assembleur) pour appeler les fonctionnalités correspondantes du système d'exploitation sans toucher au code dans `ntdll.dll`, qui pourrait être surveillé par l'EDR. Cela contourne complètement tout hook en espace utilisateur effectué sur les fonctions d'appel système dans `ntdll.dll`.

Cela a néanmoins quelques inconvénients. Premièrement, cela implique de pouvoir connaître la liste des numéros d'appel système des fonctions dont le programme a besoin, qui changent pour chaque version de Windows. Cela est néanmoins atténué en implémentant plusieurs heuristiques connues pour fonctionner sur toutes les versions passées de Windows NT (tri des exports `Zw*` de `ntdll`, recherche de l'instruction `mov rax, #syscall_number` dans la fonction `ntdll` associée, etc.), et en vérifiant qu'elles renvoient toutes le même résultat (voir `Syscalls.c` pour plus de détails).

De plus, les fonctions qui ne sont techniquement pas des appels système (par exemple `LoadLibraryX`/`LdrLoadDLL`) pourraient également être surveillées, et ne peuvent pas simplement être réimplémentées en utilisant un appel système.

La technique des appels système directs est implémentée dans EDRSandblast. Comme indiqué précédemment, elle est uniquement utilisée pour exécuter `NtProtectVirtualMemory` en toute sécurité, et supprimer tous les hooks détectés.

Pour les détails d'implémentation, consultez le chemin de code de la fonction `unhook()` lorsque `unhook_method` est `UNHOOK_WITH_DIRECT_SYSCALL`.

### Exploitation de drivers vulnérables
Comme indiqué précédemment, toute action nécessitant une lecture ou écriture en mémoire noyau repose sur un driver vulnérable pour fournir cette primitive. Dans EDRSandblast, ajouter le support d'un nouveau driver fournissant la primitive de lecture/écriture peut être fait "facilement", seules trois fonctions doivent être implémentées :

* Une fonction `ReadMemoryPrimitive_DRIVERNAME(SIZE_T Size, DWORD64 Address, PVOID Buffer)`, qui copie `Size` octets de l'adresse noyau `Address` vers le tampon espace utilisateur `Buffer` ;
* Une fonction `WriteMemoryPrimitive_DRIVERNAME(SIZE_T Size, DWORD64 Address, PVOID Buffer)`, qui copie `Size` octets du tampon espace utilisateur `Buffer` vers l'adresse noyau `Address` ;
* Une fonction `CloseDriverHandle_DRIVERNAME()` qui garantit que tous les handles du driver sont fermés (nécessaire avant l'opération de désinstallation qui est indépendante du driver, pour le moment).

À titre d'exemple, deux drivers sont actuellement supportés par EDRSandblast, `RTCore64.sys` (SHA256: `01AA278B07B58DC46C84BD0B1B5C8E9EE4E62EA0BF7A695862444AF32E87F1FD`) et `DBUtils_2_3.sys` (SHA256: `0296e2ce999e67c76352613a718e11516fe1b0efc3ffdb8918fc999dd76a73a5`). Le code suivant dans `KernelMemoryPrimitives.h` doit être mis à jour si le driver vulnérable utilisé doit être changé, ou si un nouveau est implémenté.```C
#define RTCore 0
#define DBUtil 1
// Select the driver to use with the following #define
#define VULN_DRIVER RTCore

#if VULN_DRIVER == RTCore
#define DEFAULT_DRIVER_FILE TEXT("RTCore64.sys")
#define CloseDriverHandle CloseDriverHandle_RTCore
#define ReadMemoryPrimitive ReadMemoryPrimitive_RTCore
#define WriteMemoryPrimitive WriteMemoryPrimitive_RTCore
#elif VULN_DRIVER == DBUtil
#define DEFAULT_DRIVER_FILE TEXT("DBUtil_2_3.sys")
#define CloseDriverHandle CloseDriverHandle_DBUtil
#define ReadMemoryPrimitive ReadMemoryPrimitive_DBUtil
#define WriteMemoryPrimitive WriteMemoryPrimitive_DBUtil
#endif

Détection des pilotes et processus EDR

Plusieurs techniques sont actuellement utilisées pour déterminer si un pilote ou un processus spécifique appartient ou non à un produit EDR.

Premièrement, le nom du pilote peut simplement être utilisé à cette fin. En effet, Microsoft alloue des numéros spécifiques appelés « Altitudes » pour tous les pilotes qui doivent insérer des rappels dans le noyau. Cela permet un ordre déterministe dans l'exécution des rappels, indépendant de l'ordre d'enregistrement, mais basé uniquement sur l'utilisation du pilote. Une liste de (fournisseurs de) pilotes ayant réservé une altitude spécifique peut être trouvée sur MSDN. En conséquence, une liste quasi exhaustive des noms de pilotes de sécurité liés aux produits de sécurité est fournie par Microsoft, principalement dans les listes « FSFilter Anti-Virus » et « FSFilter Activity Monitor ». Ces listes de noms de pilotes sont intégrées dans EDRSandblast, ainsi que des contributions supplémentaires.

De plus, les exécutables et DLL EDR sont très souvent signés numériquement à l'aide du certificat de signature du fournisseur. Ainsi, vérifier le signataire d'un exécutable ou d'une DLL associé à un processus peut permettre d'identifier rapidement les produits EDR.

De plus, les pilotes doivent être directement signés par Microsoft pour être autorisés à être chargés dans l'espace noyau. Bien que le fournisseur du pilote ne soit pas directement le signataire du pilote lui-même, il semble que le nom du fournisseur soit toujours inclus dans un attribut de la signature ; cette technique de détection reste néanmoins à étudier et à implémenter.

Enfin, lorsqu'on fait face à un EDR inconnu d'EDRSandblast, la meilleure approche est d'exécuter l'outil en mode « audit », et de vérifier la liste des pilotes ayant enregistré des rappels noyau ; ensuite, le nom du pilote peut être ajouté à la liste, l'outil recompilé et réexécuté.

Contournement de RunAsPPL

Le mécanisme de Protection de l'autorité de sécurité locale (LSA), introduit pour la première fois dans Windows 8.1 et Windows Server 2012 R2, utilise la technologie Protected Process Light (PPL) pour restreindre l'accès au processus LSASS. La protection PPL régule et restreint les opérations, telles que l'injection mémoire ou le dump mémoire des processus protégés, même de la part d'un processus détenant le privilège SeDebugPrivilege. Dans le modèle de protection des processus, seuls les processus s'exécutant avec des niveaux de protection plus élevés peuvent effectuer des opérations sur les processus protégés.

La structure _EPROCESS, utilisée par le noyau Windows pour représenter un processus dans la mémoire du noyau, inclut un champ _PS_PROTECTION définissant le niveau de protection d'un processus via ses attributs Type (_PS_PROTECTED_TYPE) et Signer (_PS_PROTECTED_SIGNER).

En écrivant dans la mémoire du noyau, le processus EDRSandblast peut élever son propre niveau de protection à PsProtectedSignerWinTcb-Light. Ce niveau est suffisant pour dumper la mémoire du processus LSASS, car il « domine » PsProtectedSignerLsa-Light, le niveau de protection du processus LSASS s'exécutant avec le mécanisme RunAsPPL.

EDRSandBlast implémente l'auto-protection comme suit :

  • ouvrir un handle sur le processus courant
  • fuiter tous les handles système via NtQuerySystemInformation pour trouver le handle ouvert sur le processus courant, et l'adresse de la structure EPROCESS du processus courant dans la mémoire du noyau.
  • utiliser la vulnérabilité de lecture/écriture arbitraire du pilote vulnérable pour écraser le champ _PS_PROTECTION du processus courant dans la mémoire du noyau. Les offsets du champ _PS_PROTECTION par rapport à la structure EPROCESS (définis par la version de ntoskrnl utilisée) sont calculés dans le fichier NtoskrnlOffsets.csv.

Contournement de Credential Guard

Microsoft Credential Guard est une technologie d'isolation basée sur la virtualisation, introduite dans Microsoft Windows 10 (édition Entreprise) qui empêche l'accès direct aux informations d'identification stockées dans le processus LSASS.

Lorsque Credential Guard est activé, un processus LSAIso (LSA Isolated) est créé dans Virtual Secure Mode, une fonctionnalité qui utilise les extensions de virtualisation du CPU pour fournir une sécurité accrue des données en mémoire. L'accès au processus LSAIso est restreint même pour un accès avec le contexte de sécurité NT AUTHORITY\SYSTEM. Lors du traitement d'un hash, le processus LSA effectue un appel RPC au processus LSAIso, et attend le résultat de LSAIso pour continuer. Ainsi, le processus LSASS ne contiendra aucun secret et stockera à la place des Données isolées LSA.

Comme indiqué dans la recherche originale menée par N4kedTurtle : « Wdigest peut être activé sur un système avec Credential Guard en patchant les valeurs de g_fParameter_useLogonCredential et g_IsCredGuardEnabled en mémoire ». L'activation de Wdigest entraînera le stockage en clair des informations d'identification dans la mémoire LSASS pour toute nouvelle connexion interactive (sans nécessiter un redémarrage du système). Reportez-vous au billet de blog de la recherche originale pour plus de détails sur cette technique.

EDRSandBlast rend simplement le PoC original un peu plus compatible avec l'opsec et prend en charge un certain nombre de versions de wdigest.dll (via des offsets calculés pour g_fParameter_useLogonCredential et g_IsCredGuardEnabled).

Récupération des offsets

Afin d'effectuer de manière fiable les opérations de contournement de la surveillance du noyau, EDRSandblast doit savoir exactement où lire et écrire dans la mémoire du noyau. Cela se fait en utilisant des offsets de variables globales dans l'image ciblée (ntoskrnl.exe, wdigest.dll), ainsi que l'offset de champs spécifiques dans des structures dont les définitions sont publiées par Microsoft dans les fichiers de symboles. Ces offsets sont spécifiques à chaque build des images ciblées, et doivent être collectés au moins une fois pour une version de plateforme spécifique.

Le choix d'utiliser des offsets « codés en dur » plutôt que des recherches de motifs pour localiser les structures et variables utilisées par EDRSandblast est justifié par le fait que les API non documentées responsables de l'ajout/suppression des rappels noyau sont sujettes à changement et que toute tentative de lire ou écrire la mémoire du noyau à une mauvaise adresse peut (et souvent entraînera) un Bug Check (écran bleu de la mort). Un crash de la machine n'est pas acceptable dans les scénarios de red-teaming ni de tests de pénétration normaux, car une machine qui crash est très visible par les défenseurs, et perdra toutes les informations d'identification encore en mémoire au moment de l'attaque.

Pour récupérer les offsets pour chaque version spécifique de Windows, deux approches sont implémentées.

Récupération manuelle des offsets

Les offsets nécessaires de ntoskrnl.exe et wdigest.dll peuvent être extraits à l'aide du script Python fourni ExtractOffsets.py, qui s'appuie sur radare2 et r2pipe pour télécharger et analyser les symboles à partir des fichiers PDB, et en extraire les offsets nécessaires. Les offsets sont ensuite stockés dans des fichiers CSV pour une utilisation ultérieure par EDRSandblast.

Afin de prendre en charge immédiatement un large éventail de builds Windows, de nombreuses versions des binaires ntoskrnl.exe et wdigest.dll sont référencées par Winbindex, et peuvent être automatiquement téléchargées (et leurs offsets extraits) par ExtractOffsets.py. Cela permet d'extraire les offsets de presque tous les fichiers jamais publiés dans les paquets de mise à jour Windows (à ce jour, plus de 450 versions de ntoskrnl.exe et plus de 30 versions de wdigest.dll sont disponibles et pré-calculées).

Récupération et mise à jour automatiques des offsets

Une option supplémentaire a été implémentée dans EDRSandBlast pour permettre au programme de télécharger lui-même les fichiers .pdb nécessaires depuis le serveur de symboles Microsoft, d'extraire les offsets requis, et même de mettre à jour les fichiers .csv correspondants s'ils sont présents.

L'utilisation de l'option --internet rend l'exécution de l'outil beaucoup plus simple, tout en introduisant un risque OpSec supplémentaire, puisqu'un fichier .pdb est téléchargé et déposé sur le disque pendant le processus. Cela est requis par les fonctions de dbghelp.dll utilisées pour analyser la base de données de symboles ; cependant, l'analyse entièrement en mémoire des PDB pourrait être implémentée à l'avenir pour lever cette exigence et réduire l'empreinte de l'outil.

Utilisation

Pilotes vulnérables

EDRSandblast implémente publiquement le support d'au moins 3 pilotes vulnérables, gdrv.sys (par défaut), RTCore64.sys et DBUtil_2_3.sys. Le pilote effectivement utilisé est décidé avant la compilation de l'outil (voir #define VULN_DRIVER <nom du pilote> dans includes/KernelMemoryPrimitive.h). Une copie du pilote vulnérable doit être téléchargée et fournie à EDRSandblast pour que son opération noyau fonctionne.

Les hachages des pilotes testés sont mentionnés au début de chaque fichier Driver<name>.c qui implémente les primitives de lecture et d'écriture mémoire noyau utilisées par EDRSandblast. En utilisant ces hachages, des échantillons de pilotes peuvent être facilement trouvés sur Internet, notamment sur https://www.loldrivers.io.

Voici la liste des pilotes vulnérables supportés ainsi que les liens de téléchargement :

Utilisation rapide```

Usage: EDRSandblast.exe [-h | --help] [-v | --verbose] <audit | dump | cmd | credguard | firewall | load_unsigned_driver> [--usermode] [--unhook-method ] [--direct-syscalls] [--add-dll ]* [--kernelmode] [--dont-unload-driver] [--no-restore] [--nt-offsets <NtoskrnlOffsets.csv>] [--fltmgr-offsets <FltmgrOffsets.csv>] [--wdigest-offsets <WdigestOffsets.csv>] [--ci-offsets <CiOffsets.csv>] [--internet] [--vuln-driver <RTCore64.sys>] [--vuln-service <SERVICE_NAME>] [--unsigned-driver <evil.sys>] [--unsigned-service <SERVICE_NAME>] [--no-kdp] [-o | --dump-output <DUMP_FILE>]

root@kitploit:~
### Options```
-h | --help             Show this help message and exit.
-v | --verbose          Enable a more verbose output.

Actions mode:

        audit                     Display the user-land hooks and / or Kernel callbacks without taking actions.
        dump                      Dump the process specified by --process-name (LSASS process by default), as '<process_name>' in the current directory or at the
                                  specified file using -o | --output <DUMP_FILE>.
        cmd                       Open a cmd.exe prompt.
        credguard                 Patch the LSASS process' memory to enable Wdigest cleartext passwords caching even if
                                  Credential Guard is enabled on the host. No kernel-land actions required.
        firewall                  Add Windows firewall rules to block network access for the EDR processes / services.
        load_unsigned_driver      Load the specified unsigned driver, bypassing Driver Signature Enforcement (DSE).
                                  WARNING: currently an experimental feature, only works if KDP is not present and enabled.

--usermode              Perform user-land operations (DLL unhooking).
--kernelmode            Perform kernel-land operations (Kernel callbacks removal and ETW TI disabling).


Hooking-related options:

--add-dll <dll name or path>            Loads arbitrary libraries into the process' address space, before starting
                                        anything.This can be useful to audit userland hooking for DLL that are not
                                        loaded by default by this program. Use this option multiple times to load
                                        multiple DLLs all at once.
                                        Example of interesting DLLs to look at: user32.dll, ole32.dll, crypt32.dll,
                                        samcli.dll, winhttp.dll, urlmon.dll, secur32.dll, shell32.dll...

--unhook-method <N>                     Choose the userland un-hooking technique, from the following:

        0                               Do not perform any unhooking (used for direct syscalls operations).
        1 (Default)                     Uses the (probably monitored) NtProtectVirtualMemory function in ntdll to remove all
                                        present userland hooks.
        2                               Constructs a 'unhooked' (i.e. unmonitored) version of NtProtectVirtualMemory, by                                        allocating an executable trampoline jumping over the hook, and remove all present
                                        userland hooks.
        3                               Searches for an existing trampoline allocated by the EDR itself, to get an 'unhooked'
                                        (i.e. unmonitored) version of NtProtectVirtualMemory, and remove all present userland
                                        hooks.
        4                               Loads an additional version of ntdll library into memory, and use the (hopefully                                        unmonitored) version of NtProtectVirtualMemory present in this library to remove all
                                        present userland hooks.
        5                               Allocates a shellcode that uses a direct syscall to call NtProtectVirtualMemory,                                        and uses it to remove all detected hooks

--direct-syscalls       Use direct syscalls to dump the selected process memory without unhooking unserland hooks.


BYOVD options:

--dont-unload-driver                    Keep the vulnerable driver installed on the host
                                        Default to automatically unsinstall the driver.
--no-restore                            Do not restore the EDR drivers' Kernel Callbacks that were removed.
                                        Default to restore the callbacks.
--vuln-driver <gdrv.sys>                Path to the vulnerable driver file.
                                        Default to 'gdrv.sys' in the current directory.
--vuln-service <SERVICE_NAME>           Name of the vulnerable service to intall / start.


Driver sideloading options:

--unsigned-driver <evil.sys>            Path to the unsigned driver file.
                                        Default to 'evil.sys' in the current directory.
--unsigned-service <SERVICE_NAME>       Name of the unsigned driver's service to intall / start.
--no-kdp                                Switch to g_CiOptions patching method for disabling DSE (default is callback swapping).


Offset-related options:

--nt-offsets <NtoskrnlOffsets.csv>      Path to the CSV file containing the required ntoskrnl.exe's offsets.
                                        Default to 'NtoskrnlOffsets.csv' in the current directory.
--fltmgr-offsets <FltmgrOffsets.csv>    Path to the CSV file containing the required fltmgr.sys's offsets
                                        Default to 'FltmgrOffsets.csv' in the current directory.
--wdigest-offsets <WdigestOffsets.csv>  Path to the CSV file containing the required wdigest.dll's offsets
                                        (only for the 'credguard' mode).
                                        Default to 'WdigestOffsets.csv' in the current directory.
--ci-offsets <CiOffsets.csv>            Path to the CSV file containing the required ci.dll's offsets
                                        (only for the 'load_unsigned_driver' mode).
                                        Default to 'WdigestOffsets.csv' in the current directory.
-i | --internet                         Enables automatic symbols download from Microsoft Symbol Server
                                        If a corresponding *Offsets.csv file exists, appends the downloaded offsets to the file for later use
                                        OpSec warning: downloads and drops on disk a PDB file for the corresponding image

Dump options:

-o | --dump-output <DUMP_FILE>          Output path to the dump file that will be generated by the 'dump' mode.
                                        Default to 'process_name' in the current directory.
--process-name <NAME>                   File name of the process to dump (defaults to 'lsass.exe')

Construction

EDRSandBlast (x64 uniquement) a été construit sur Visual Studio 2019 (Windows SDK Version : 10.0.19041.0 et Plateforme Toolset : Visual Studio 2019 (v142)).

Utilisation de ExtractOffsets.py

Notez que ExtractOffsets.py n'a été testé que sur Windows.```

Installation of Python dependencies

pip.exe install -m .\requirements.txt

Script usage

ExtractOffsets.py [-h] -i INPUT [-o OUTPUT] [-d] mode

positional arguments: mode ntoskrnl or wdigest. Mode to download and extract offsets for either ntoskrnl or wdigest

optional arguments: -h, --help show this help message and exit -i INPUT, --input INPUT Single file or directory containing ntoskrnl.exe / wdigest.dll to extract offsets from. If in download mode, the PE downloaded from MS symbols servers will be placed in this folder. -o OUTPUT, --output OUTPUT CSV file to write offsets to. If the specified file already exists, only new ntoskrnl versions will be downloaded / analyzed. Defaults to NtoskrnlOffsets.csv / WdigestOffsets.csv in the current folder. -d, --download Flag to download the PE from Microsoft servers using list of versions from winbindex.m417z.com.

root@kitploit:~
## Détection
Du point de vue du défenseur (éditeur d'EDR, Microsoft, analystes SOC examinant la télémétrie de l'EDR, ...), plusieurs indicateurs peuvent être utilisés pour détecter ou prévenir ce type de techniques.

### Liste blanche de pilotes
Étant donné que chaque action effectuée par l'outil en mémoire en mode noyau repose sur un pilote vulnérable pour lire/écrire du contenu arbitraire, les événements de chargement de pilotes devraient être lourdement scrutés par le produit EDR (ou les analystes SOC), et déclencher une alerte pour tout chargement de pilote inhabituel, voire bloquer les pilotes vulnérables connus. Cette dernière approche est même [recommandée par Microsoft eux-mêmes](https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-defender-application-control/microsoft-recommended-driver-block-rules) : tout appareil Windows avec HVCI (*Hypervisor-protected code integrity*) activé intègre une liste de blocage de pilotes, et cela deviendra progressivement un comportement par défaut sur Windows (c'est déjà le cas sur Windows 11).

### Vérifications d'intégrité de la mémoire du noyau
Puisqu'un attaquant pourrait quand même utiliser un pilote vulnérable inconnu pour effectuer les mêmes actions en mémoire, le pilote de l'EDR pourrait vérifier périodiquement que ses callbacks du noyau sont toujours enregistrés, directement en inspectant la mémoire du noyau (comme le fait cet outil), ou simplement en déclenchant des événements (création de processus, création de thread, chargement d'image, etc.) et en vérifiant que les fonctions de callback sont bien appelées par le noyau exécutif.

En remarque, ce type de structure de données pourrait être protégé via le récent mécanisme [Kernel Data Protection (KDP)](https://www.microsoft.com/security/blog/2020/07/08/introducing-kernel-data-protection-a-new-platform-security-technology-for-preventing-data-corruption/), qui repose sur la sécurité basée sur la virtualisation, afin de rendre le tableau de callbacks du noyau non inscriptible sans appeler les bonnes API.

La même logique pourrait s'appliquer à des variables ETW sensibles telles que `ProviderEnableInfo`, abusée par cet outil pour désactiver la génération d'événements ETW Threat Intelligence.

### Détection en mode utilisateur
Le premier indicateur qu'un processus tente activement de contourner le hooking en mode utilisateur est l'accès aux fichiers pour chaque DLL correspondant aux modules chargés ; dans une exécution normale, un processus en mode utilisateur a rarement besoin de lire des fichiers DLL en dehors d'un appel `LoadLibrary`, en particulier `ntdll.dll`.

Afin de protéger le hooking des API contre un contournement, les produits EDR pourraient vérifier périodiquement que les hooks ne sont pas modifiés en mémoire, à l'intérieur de chaque processus surveillé.

Enfin, pour détecter un contournement de hooking (abus d'une trampoline, utilisation d'appels système directs, etc.) qui n'implique pas la suppression des hooks, les produits EDR pourraient potentiellement s'appuyer sur les callbacks du noyau associés aux appels système abusés (ex. `PsCreateProcessNotifyRoutine` pour l'appel système `NtCreateProcess`, `ObRegisterCallbacks` pour l'appel système `NtOpenProcess`, etc.), et effectuer une analyse de la pile d'appels en mode utilisateur afin de déterminer si l'appel système a été déclenché depuis un chemin normal (`kernel32.dll` -> `ntdll.dll` -> syscall) ou anormal (ex. `program.exe` -> syscall direct).


## Remerciements

- Énumération et suppression des callbacks du noyau :
  https://github.com/br-sn/CheekyBlinder

- Primitives de lecture / écriture en mémoire du noyau via le pilote vulnérable
  `Micro-Star MSI Afterburner` :
  https://github.com/Barakat/CVE-2019-16098/

- Désactivation du fournisseur ETW Threat Intelligence :
  https://public.cnotools.studio/bring-your-own-vulnerable-kernel-driver-byovkd/exploits/data-only-attack-neutralizing-etwti-provider

- Installation / désinstallation de pilote : https://github.com/gentilkiwi/mimikatz

- Liste initiale des noms de pilotes EDR :
  https://github.com/SadProcessor/SomeStuff/blob/master/Invoke-EDRCheck.ps1

- Contournement de Credential Guard en réactivant `Wdigest` via le patching
  mémoire de `LSASS` : https://teamhydra.blog/2020/08/25/bypassing-credential-guard/


## Auteurs

[Thomas DIOT (Qazeer)](https://github.com/Qazeer/)
[Maxime MEIGNAN (themaks)](https://github.com/themaks)

## Remerciements aux contributeurs
- [v1k1ngfr](https://github.com/v1k1ngfr) : pour le contournement de la vérification de signature des pilotes (via le patching de `g_CiOptions`) et le support du pilote GDRV.sys
- [Windy Bug](https://github.com/0mWindyBug) : pour un contournement de la vérification de signature des pilotes compatible KDP (via l'échange de callbacks) et leur contribution majeure sur la fonctionnalité de contournement du minifiltre


## Licence

Licence CC BY 4.0 - https://creativecommons.org/licenses/by/4.0/
Télécharger l’outil
Pilote supportéLien de téléchargementSHA256
GDRV.sysLien LOLDrivers31f4cfb4c71da44120752721103a16512444c13c2ac2d857a7e6f13cb679b427
RTCore64.sysLien LOLDrivers01aa278b07b58dc46c84bd0b1b5c8e9ee4e62ea0bf7a695862444af32e87f1fd
DBUtil_2_3.sysLien LOLDrivers0296e2ce999e67c76352613a718e11516fe1b0efc3ffdb8918fc999dd76a73a5