# Les EDR, mode d’emploi

Le but de cet article est d’exposer l’ensemble des sources de détection employées aujourd’hui par les solutions existantes d’EDR ainsi que leurs limitations, et, dans un second temps, de mettre en comparaison ces éléments avec les détections pouvant survenir lors d’un test d’intrusion typique, ainsi que de mettre en contraste avec les techniques fréquemment observées chez des acteurs malveillants, typiquement lors d’une intrusion précédent le déploiement d’un *ransomware.*

L’article va se concentrer sur les détections sur un environnement Windows, de fichiers compilés malveillants. Cela n’inclut donc pas des sujets comme la détection de scripts PowerShell ou Python malveillants, par exemple.

Enfin, cela ne concerne que partiellement les applications en code managé (.NET), car ces applications ne sont pas directement compilées en code natif, seulement en code intermédiaire (en général).

## **L’analyse statique**

La fonctionnalité d’analyse statique est la fonctionnalité de détection la plus connue des solutions d’antivirus et d’EDR. Il s’agit de la reconnaissance de *patterns* connus comme appartenant à du code malveillant, suite à une analyse manuelle. Ces *patterns* sont principalement de deux types différents, soit des chaînes de caractères ou des données bien spécifiques. Par exemple, le motif présent au sein de mimikatz dispose de nombreuses signatures :

```bash
.#####. mimikatz 2.0
.## ^ ##.
## / \ ## /* * *
## \ / ## Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
'## v ##' https://blog.gentilkiwi.com/mimikatz (oe.eo)
'#####' with 13 modules * * */
```

L’autre type de *patterns* est une suite d’instructions assembleur bien spécifique à ce programme malveillant.

Un format universel permettant de se partager ce genre de règle des détection a été créé pour cela : le format Yara.

```bash
rule XorExample2
{
    strings:
        $xor_string_00 = "This program cannot"
        $xor_string_01 = "Uihr!qsnfs`l!b`oonu"
        $xor_string_02 = "Vjkq\"rpmepco\"acllmv"
        // Repeat for every single byte XOR
    condition:
        any of them
}
```

La principale limitation de cette analyse statique, est qu’elle est contournée par des *reflective loaders*. Ce sont de petits programmes, dont le rôle est d’exécuter en mémoire un plus gros programme malveillant pour lequel il existe des signatures connues. Comme c’est le *reflective loader* qui charge le programme final, il est possible de chiffrer ou d’encoder au préalable le programme malveillant final, cassant ainsi les signatures et rendant les règles de détection inefficaces, le *reflective loader* se chargeant de déchiffrer ou décoder le programme final juste avant son exécution.

Il est possible tenter de détecter statistiquement des anomalies. Par exemple, si l’exécutable contient une grande zone mémoire ayant une forte [**entropie de Shannon**](https://fr.wikipedia.org/wiki/Entropie_de_Shannon), cela pourrait indiquer la présence d’un contenu chiffré, mais il est simple de baisser cette entropie, soit en ajoutant des données redondantes (par exemple, de nombreux zéros), soit en séparant le contenu chiffré dans un fichier séparé.

## **L’analyse dynamique**

#### **Sandboxing**

![sandbox](https://cdn.prod.website-files.com/66b4f677818acbec83587b15/67507af1094dbe2a9eb2ca61_sandbox.jpeg align="left")

On met évidemment une image de bac à sable pour illustrer

Afin de contourner le problème que posent les *reflective loaders*, une première solution qui a été mise en place est de récupérer l’exécutable en question, et de l’exécuter sous un hyperviseur sur une machine tierce, généralement hébergée sur un *cloud*. Cela permet d’observer le comportement, notamment le trafic réseau peu après le lancement de l’application.

Cela a une grosse limitation : ce *sandboxing* se déroulant avant l’exécution réelle du programme, cette analyse ne peut pas être très longue. Ainsi, pour un auteur de *malware*, il est possible d’abuser de ces différences de comportements. Par exemple, il est possible de vérifier que le nom de domaine de la machine sur laquelle le code correspond bien à celui attendu, ou encore d’effectuer un *Sleep* de quelques minutes avant d’exécuter le code malveillant.

Certaines plateformes tentent de modifier l’environnement pour que les fonctions telles que *Sleep* retournent immédiatement. Cela n’est toutefois que peu efficace, car il suffit de ne pas appeler de bibliothèque tierce pour *Sleep*, et de simplement effectuer des opérations prenant du temps à s’exécuter, par exemple, un algorithme mathématique de calcul (nombre premiers, multiplications matricielles, etc.) mal optimisés.

#### **Userland hooking**

La première méthode d’analyse du comportement dynamique à être apparue est celle du *hooking*.  
Le principe est de remplacer la première instruction d’une fonction par un saut inconditionnel vers une fonction d’analyse par l’EDR, puis, si l’exécution est autorisée, un second saut qui retourne vers la fonction originale, après avoir exécuté les instructions qui ont été réécrites par le saut.  
Certaines implémentations d’EDR réécrivent la [**seconde instruction**](https://inbits-sec.com/posts/in-memory-unhooking/) plutôt que la première, ce qui est plus difficile à détecter.

Par exemple, la fonction `NtOpenProcess` pourrait initialement ressembler à ceci :

```javascript
0:000> u ntdll!NtOpenProcess
ntdll!NtOpenProcess:
00007ffc`74d6fe00 4c8bd1 mov r10,rcx
00007ffc`74d6fe03 b826000000 mov eax,26h
00007ffc`74d6fe08 f604250803fe7f01 test byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1
00007ffc`74d6fe10 7503 jne ntdll!NtOpenProcess+0x15 (00007ffc`74d6fe15)
00007ffc`74d6fe12 0f05 syscall
00007ffc`74d6fe14 c3 ret
00007ffc`74d6fe15 cd2e int 2Eh
00007ffc`74d6fe17 c3 ret
```

En comparaison, la fonction une fois *hookée* ressemble à ceci :

```javascript
0:017> u ntdll!NtOpenProcess L10
ntdll!NtOpenProcess:
00007ffc`74d6fe00 e97b339aa8 jmp [redacted.dll]+0x63180 (00007ffc`1d713180)
00007ffc`74d6fe05 0000 add byte ptr [rax],al
00007ffc`74d6fe07 00f6 add dh,dh
00007ffc`74d6fe09 0425 add al,25h
00007ffc`74d6fe0b 0803 or byte ptr [rbx],al
00007ffc`74d6fe0d fe ???
00007ffc`74d6fe0e 7f01 jg ntdll!NtOpenProcess+0x11 (00007ffc`74d6fe11)
00007ffc`74d6fe10 7503 jne ntdll!NtOpenProcess+0x15 (00007ffc`74d6fe15)
00007ffc`74d6fe12 0f05 syscall
00007ffc`74d6fe14 c3 ret
00007ffc`74d6fe15 cd2e int 2Eh
00007ffc`74d6fe17 c3 ret
```

Il faut uniquement prêter attention à la première instruction, les autres ne sont pas désassemblées correctement car le `jmp` a réécrit une partie des instructions suivantes.

Cette première instruction a été remplacée par une instruction `jmp`, un saut inconditionnel, qui permettra de journaliser l’appel qui est fait à la fonction, les arguments qui sont utilisés, le *thread* appellant, etc. Cela permet d’observer le comportement de l’application lors de son exécution.

Bien que l’on entende très fréquemment parler de *hooks* pour les appels systèmes, comme `NtOpenProcess` dans l’exemple ci-dessus, ce ne sont pas les seules fonctions à se faire *hooker*. En particulier, il est intéressant pour un EDR de *hooker* les fonctions de bibliothèques Windows dont le comportement est non-trivial à reproduire.  
On retrouve fréquemment des *hooks* sur les fonctions liées au chargement dynamique de code (`LoadLibrary`, `LdrLoadDll`, `GetProcAddress`, `LdrGetProcedureAddress`, etc), ou encore les fonctions liées aux communications HTTP (les différentes fonctions de `wininet.dll`, `winhttp.dll`)

Idéalement, les solutions EDR préfereraient pouvoir *hooker* les appels système du côté *kernel*, car un programme utilisateur standard malveillant ne pourrait pas interférer avec ces *hooks*.  
Cela n’est toutefois pas employé par la majorité des solutions, car Windows tente d’interdire aux *drivers* de faire cela (bien que ça n’empêche pas certaines solutions [**à y recourir**](https://the-deniss.github.io/posts/2022/12/08/hooking-system-calls-in-windows-11-22h2-like-avast-antivirus.html) via des contournements connus, mais instables).

Un malware tentant d’échapper à la visibilité de ces *hooks* tentera alors d’interférer ceux-ci. Il est intéressant de procéder différemment pour les *hooks* sur les *syscalls* et pour les fonctions des autres bibliothèques.

Tout d’abord, concernant les *syscalls*, il est à noter que toutes les fonctions servant à les appeler ont le même préfixe, à savoir :

```javascript
mov r10,rcx
mov eax,<numéro syscall>
test byte ptr [SharedUserData+0x308],1
jne rip+0x5
syscall
```

Une subtilité est que le numéro du *syscall* pour un *syscall* donné n’est pas constant entre les versions de Windows.

Par conséquent, un *malware* voulant éviter le *hook*, doit retrouver le numéro du *syscall* de la fonction qui l’intéresse, refaire les premières instructions, puis sauter sur l’instruction *syscall* directement.  
Il existe différentes techniques pour récupérer dynamiquement les numéros des appels système, dont certains sont recensées dans [**cet article**](https://alice.climent-pommeret.red/posts/direct-syscalls-hells-halos-syswhispers2/).

Pour que les *hooks* s’appliquent à des fonctions de bibliothèque n’étant pas des appels systèmes, le préfixe de ces fonctions n’est pas constant, il n’est donc pas aussi simple de le retrouver. Cependant, une fois qu’il est possible d’exécuter des *syscalls* sans passer par les *hooks*, il est possible d’effectuer des *syscalls* pour lire les fichiers DLL sur disque, puis de les *parser*, pour récupérer les premiers octets des fonctions, qui ont été écrasés par le `jmp`.

Certaines implémentations de *unhooking* vont ensuite réécrire le code contenant le `jmp` par les instructions originales pour enlever le *hook* placé par la solution d’EDR, mais cela peut être détecté par une vérification de l’intégrité du *hook*.

### **Memory Scanning**

Afin de tenter de pallier aux limites des détections statiques, les solutions d’EDR peuvent mettre en place des « scans mémoire » pour essayer de repérer un programme malveillant connu une fois qu’il a été chargé en mémoire par le *reflective loader*, puisque le programme malveillant ne peut pas être chiffré ou encodé lors de son exécution.

Cela peut avoir lieu soit périodiquement (par exemple, toutes les quelques heures sur l’ensemble des processus d’une machine), ou bien sur un processus spécifique, suite à des actions suspectes.  
La limitation principale est qu’effectuer ce genre de scan de mémoire sur l’ensemble de la mémoire d’un processus peut être très consommateur en performances, cela ne peut donc être fait en permanence. Les solutions d’EDR tentent de limiter la mémoire d’un processus qui est scanné, par exemple en ne ciblant que la mémoire exécutable du processus allouée dynamiquement.

Seuls les malwares de type *Command And Control* (C2) sont affectés par ce genre de détection, car ce sont les seuls à demeurer suffisamment longtemps en mémoire pour être affectés.  
Pour contourner ce vecteur de détections, puisque la majorité du temps ces programmes *sleepent* en attendant le prochain intervalle de temps afin de vérifier s’il y a des nouvelles commandes à exécuter : ils peuvent simplement se re-chiffrer en mémoire lors de leurs périodes de *sleep* puis se déchiffrer avant de reprendre leur exécution. Lorsque les scans mémoire surviendront, les EDR ne verront alors que des données chiffrées – qui ne correspondent pas à des *patterns* connus.

### **Callbacks Kernel**

#### **Process Notification Callbacks**

Puisque les *drivers* des solutions d’EDR ne sont pas en mesure de mettre en place des *hooks* côté *kernel*, Microsoft a mis en place des *callbacks*, permettant d’informer les *drivers* de certains événements. Les plus connus sont les *callbacks* liés aux processus, enregistrés via la famille des API `PsSetCreateProcessNotifyRoutine`.

Ces *callbacks* servent fréquemment à injecter au sein du processus une DLL qui sera en charge de mettre en place le *hooking userland*, comme vu précédemment, et ce avant l’exécution du début du processus.

Ces *callbacks* servent également pour des politiques que certains EDR peuvent avoir, notamment, empêcher des processus inconnus de créer des processus fils.  
Cela sert notamment à détecter le comportement de commandes de type `shell` sur la plupart des C2 existants (comme par exemple Cobalt Strike) qui sert à exécuter des commandes directement en créant un processus fils, ou bien de la post-exploitation utilisant le principe de **fork & run**, dans lequel un processus fils légitime est créé, le contenu de l’exécutable est remplacé en mémoire par un module de post exploitation, et l’exécution est reprise.

Ces *callbacks* ne sont pas contournables par un *malware*. Toutefois, la solution pour éviter ces politiques est de simplement tout exécuter au sein du même processus. En pratique, cela se traduit par le développement de *Beacon Object Files*, qui est un moyen spécifique de développer des modules de post-exploitation qui seront exécutés en mémoire au sein du même processus.

#### **Image Load Notification callback**

Ces *callbacks* sont invoqués lors de l’appel en *userland* à la fonction `NtMapViewOfSection`, qui sert à *mapper* en mémoire l’objet *Section* correspondant à la DLL qui est en train d’être chargée.

En soit, il est possible de ne pas invoquer ces *callbacks*, en réimplémentant l’ensemble du *mapping* d’une DLL en mémoire. Toutefois, cela est d’une complexité importante à mettre en place, et implique d’avoir des zones mémoires non associées à des fichiers sur disque. Il s’agit donc d’une décision à prendre pour un *malware*.

Il existe un outil tel quel [**DarkLoadLibrary**](https://github.com/bats3c/DarkLoadLibrary), qui réimplémente manuellement la mise en mémoire de la DLL, toutefois il ne s’agit que d’une implémentation partielle.  
En effet, la DLL est mise en mémoire manuellement, mais ses dépendances sont chargées via un appel à `LoadLibraryA`, qui va déclencher des appels à `NtMapViewOfSection`.

Cela peut toutefois servir pour échapper à certaines détections qui se basent sur ces éléments, comme par exemple, [**certaines règles**](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_network_module_loaded_from_suspicious_unbacked_memory.toml) de détection de post-exploitation.

#### **Object callback**

Les *Object Callback* sont des *callbacks* enregistrés auprès de l’*Object Manager* via l’API `ObRegisterCallbacks`, qui sont invoqués avant ou après une opération sur un `HANDLE` d’un type spécifié.

En particulier, les solutions d’EDR mettent souvent en place ce genre de *callback* pour les objets de type *Process* et *Thread*. Cela permet, entre autres, d’observer la demande de création d’un `HANDLE` vers le processus `lsass.exe` : si la demande contient un droit d’accès tel que `PROCESS_VM_READ`, soit tuer le processus ayant fait la demande, soit simplement retirer ce droit – afin d’empêcher les *dumps* de `lsass.exe`.

#### **Opérations IO (Filesystem, Network)**

Par ailleurs, les *drivers* de solution d’EDR comportent souvent un *driver* de type *minifilter*. Ce sont des *drivers* qui vont s’enregistrer auprès du *filter manager*, pour, lorsqu’un requête IO (création ou modification de fichiers sur disque, entre autres) est effectuée, obtenir la visibilité dessus et éventuellement prendre des actions.

Cela est utilisé pour de nombreux usages, par exemple, pour détecter qu’un nouveau fichier ayant une extension `.exe` est créé et qu’il faut donc effectuer une analyse statique. Cela peut aussi servir à bloquer un exécutable dont l’analyse a révélé qu’il était malveillant, avant que le fichier ne soit supprimé.

Enfin les *drivers* incluent des *Callout Drivers*, qui permettent d’observer le contenu du trafic réseau.  
Cela peut également permettre de détecter certains *patterns* connus au sein d’opérations réseau, par exemple, un *meterpreter* n’utilisant pas de chiffrement peut se faire détecter de cette façon, car il a un protocole bien défini et repérable.

### **ETW**

![](https://cdn.prod.website-files.com/66b4f677818acbec83587b15/67507b91131a01784a25d55e_event_viewer-1024x639.png align="left")

Source : [**wikipedia**](https://commons.wikimedia.org/wiki/File:Berkas_Log_Windows.png)

ETW, l’acronyme de *Event Tracing For Windows*, est le mécanisme de Windows permettant de collecter informations sur l’exécution de différents composants de l’OS.

Bien qu’initialement conçu plus pour pouvoir identifier la source de problèmes dans les applications Windows, son usage peut également servir à des solutions d’EDR.

ETW est architecturé avec des *providers*, qui sont différentes sources qui fournissent des types différents d’informations, par exemple, sur un type d’opérations réseau spécifique (HTTP, LDAP, etc.) ou encore sur les authentifications Windows.

Des *consumers* peuvent ensuite venir s’attacher à plusieurs *providers* dans une *Tracing Session*, qui permettra de collecter les événements générés par les différentes sources, soit en instantané, soit en différé.

Un exemple parlant de *consumer* ETW est l’application *Event Viewer* sur Windows, qui affiche dans une interface graphique les événements de certains *providers*.

Ces événements sont générés par différentes sources. Certaines sont situées en *userland*, et d’autres en *kernelland*.

Par exemple, si un processus fait des requêtes LDAP, via la bibliothèque `Wldap32.dll`, cela génèrera des événements ETW. Toutefois, ceux-ci seront générés en *userland*, via les appels système `NtTraceEvent` et `NtTraceControl`. Comme ceux-ci sont générés en *userland*, un *malware* pourrait modifier l’une de ces fonctions ou l’une des fonctions appelantes, pour ne pas faire l’appel à ces fonctions, ce qui permettrait d’occulter cette télémétrie.

Toutefois, d’autres événements sont générés au niveau du *kernelland*, qui eux ne peuvent pas être occultés par un *malware*.

En particulier, parmi ces *providers*, on peut citer `Microsoft-Windows-Threat-Intelligence`, qui fournit des événements liés à la gestion de la mémoire virtuelle et des *threads* d’un processus. Entre autres, cela inclut les modifications des permissions des pages mémoires.

Les événements sont divisés en deux catégories : ceux locaux, et ceux cross-processus. Les événements cross-processus peuvent aider à identifier les injections de processus, alors que les événements locaux peuvent aider à identifier les *reflective loader*s, entre autres.

Toutefois, la difficulté principale liée à cette télémétrie est le nombre d’événements, et le taux de faux positifs : par exemple sur Windows, toutes les applications en .NET utilisent du code dynamique, et donc des allocations de code RWX. Similairement, les injections de code sont également relativement fréquentes sur des environnements Windows.

[**Cet article**](https://web.archive.org/web/20230322093557/http://blog.redbluepurple.io/windows-security-research/kernel-tracing-injection-detection) donne le détail de ces événements, ainsi que les limitations et [**assouplissements qui sont en place du fait du nombre trop important de faux positifs**](https://web.archive.org/web/20230322083937/https://blog.redbluepurple.io/windows-security-research/bypassing-injection-detection).

### **L’analyse de la callstack**

Les événements ETW sont également intéressants, puisqu’ils contiennent les informations de la *callstack* du *thread* lorsque l’événement a été enregistré.

Par conséquent, si un *reflective loader* a été utilisé, une zone mémoire a été allouée dynamiquement pour contenir le *payload* final, celui-ci a été copié dedans, puis la zone mémoire a été rendue exécutable.

Cette zone mémoire n’est donc pas associée à un fichier sur disque, car elle a été allouée dynamiquement. Ainsi, si une telle zone mémoire apparaît dans la *callstack* d’un processus lors d’un événement ETW, cela peut être considéré comme probablement malveillant.

Il existe trois grands types de méthodes pour avoir une *callstack* ne faisant pas apparaître de zone mémoire non associée à un fichier sur disque.

La première consiste à utiliser des *threads* différents, qui ne contiennent pas de zone exécutable non associée à un fichier sur disque dans leur *callstack*. En particulier, sur Windows, il existe le *Thread Pool*, qui consiste en un ensemble de *threads* managés, qui sont présents dans l’ensemble des processus, et qui permettent d’effectuer des actions en différé. Il est donc possible de demander à ces *threads* d’effectuer des actions qui nous intéressent, par exemple des appels systèmes générant de la télémétrie ETW. Comme ce n’est pas dans ces *threads* que s’exécute le *payload* principal, la zone non associée à un fichier sur disque n’apparaît pas dans la télémetrie ETW.

Cette technique a une limitation principale : les appels systèmes ne sont pas faits dans le même *thread*. Pour un *payload* de type C2, il n’est donc pas possible de faire de cette façon l’appel système pour faire *sleep* l’agent. De plus, des opérations spécifiques à un *thread* ne peuvent pas fonctionner, notamment voler un *token* Windows.

La seconde technique est plus difficile à implémenter : elle implique de complètement modifier sa *callstack*, pour quelle fasse uniquement apparaître des modules légitimes. Fondamentalement, la *callstack* est complètement sous le contrôle du programme en mode utilisateur, la difficulté n’est pas de faire l’appel d’une fonction avec une *callstack* arbitraire, mais de récupérer le flux d’exécution une fois que la fonction retourne.

Un des [**exemples d’implémentation existant**](https://github.com/klezVirus/SilentMoonwalk) utilise des gadgets, qui sont des suites d’instructions assembleur dans des modules Windows légitimes, qui ensemble forment une *callstack* complète, mais qui, lorsqu’ils sont exécutés, vont modifier la *stack*, ce qui va désynchroniser les retours de fonctions successives, pour pouvoir récupérer le flux de l’exécution du programme.

La dernière catégorie consiste à mettre en mémoire une DLL légitime, associée à un fichier sur disque, puis de modifier le contenu en mémoire de cette DLL (*module stomping*). Toutefois, cela peut mener à des détections spécifiques, notamment des événements ETW « locaux » au processus, et cela modifie un attribut de la page mémoire spécifique lié au *copy-on-write*.

### **Des pièges en mémoire**

![It'as a trap !](https://cdn.prod.website-files.com/66b4f677818acbec83587b15/67507baf6cce6944c2507756_trap.gif align="center")

It’as a trap !

Enfin, différentes solutions emploient différentes techniques peu documentées pour tenter d’obtenir des éléments de télémétrie supplémentaires.

On peut citer différents mécanismes, tels que :

– L’utilisation des [**Intrumentation Callback**](https://github.com/ionescu007/HookingNirvana/blob/master/Esoteric%20Hooks.pdf), permettant à une solution d’EDR de récupérer le flux d’exécution d’un programme après chaque instruction `syscall`.  
– La présence de fausses entrées au sein des listes chaînées des modules dans le PEB. Si un programme [**tente d’accéder**](https://x.com/NinjaParanoid/status/1493396083644399616) à un zone mémoire associée à ces fausses entrées, une exception est levée, car la mémoire est protégée avec l’attribut `PAGE_GUARD`. L’exception est alors attrapée par l’EDR, qui pourra noter ce comportement anormal.  
– L’enregistrement de fonctions de *callback* lors du chargement dynamique de DLL via [**LdrRegisterDllNotification**](https://learn.microsoft.com/en-us/windows/win32/devnotes/ldrregisterdllnotification) du côté *userland*.  
– Des vérifications d’intégrité, pour s’assurer que certaines fonctions, comme `NtTraceEvent` n’ont pas été modifiées en mémoire.

Bien que ces mécanismes puissent générer de la télémétrie supplémentaire, ces différentes techniques ne sont que peu robustes : un *malware* étant au courant de l’existence de ces mécanismes pourra simplement les retirer avant d’exécuter son programme malveillant.

## **Par rapport à un pentest « typique »**

Aujourd’hui, il n’est plus du tout aussi trivial de s’affranchir des mécanismes de détection et de blocage des EDR.

Aussi, afin de contourner ce problème, en test d’intrusion notamment, des méthodes alternatives sont employées. Depuis un poste physiquement présent au sein du réseau (ou une Raspberry Pi, par exemple), l’auditeur va lancer la majorité de ses attaques depuis son propre poste, qui n’est pas monitoré. De plus, les actions menées vont tenter au maximum de ne pas exécuter de programme directement sur la machine cible, et utiliser uniquement des appels de procédures à distance (RPC) existants sur l’ensemble des machines Windows.

Il est difficile pour un EDR de correctement bloquer ces attaques, puisqu’il n’y a pas vraiment de processus sur la machine victime à bloquer. Au mieux il est possible de le détecter, car le processus malveillant est sur une machine distante non monitorée.

Certains EDR tentent tout de même de bloquer certains appels RPC en tuant le processus sur la machine victime, mais en général ces détections ne sont pas très robustes. Par exemple, l’utilitaire `secretsdump.py` de la suite `Impacket` permet de faire un *dump* de la base SAM à distance. Pour ce faire, les ruches de registre correspondantes sont d’abord écrites sur disque, puis récupérées via le protocole SMB. Certaines solutions d’EDR vont tenter de détecter ce *dump*, pour essayer de rapidement le supprimer, mais cela laisse une fenêtre de temps durant laquelle le fichier peut être lu.

Bien que cela puisse représenter certains scénarios de compromission (accès VPN compromis, *appliance* non patchée, application Web compromise, accès physique), cela ne couvre pas l’ensemble des scénarios existants (*phishing*, accès RDP exposé, etc)

## **Par rapport à de vrais attaquants**

Tous les attaquants n’ont pas forcément les compétences ou les moyens de contourner ces solutions. Pour arriver à leurs fins, il est très fréquent de voir l’utilisation d’utilitaires légitimes d’accès à distance (TeamViewer, AnyDesk, etc). Bien qu’il soit simple de détecter l’usage de ces utilitaires, il n’est pas possible de les bloquer par défaut, car ils sont également très fréquemment utilisés pour de l’administration système.

Cela est également vrai pour les différentes phases d’une attaque, où les attaquants vont abuser d’utilitaires légitimes pour ne pas être bloqués par des solutions EDR (par exemple, utilisation d’ADExplorer pour de la reconnaissance, de PsExec pour du mouvement latéral, etc).

Enfin, les attaquants tentent aussi de désactiver l’EDR en place. Pour ce faire, un accès administrateur est nécessaire. Avec celui-ci, les attaquants vont tenter d’altérer le *driver* de l’EDR, chargé dans le *kernel*.  
Pour pouvoir interagir avec la mémoire du *kernel*, ils vont charger un *driver* connu pour avoir une vulnérabilité, puis exploiter cette vulnérabilité pour retirer les différents *callbacks* et points de visibilité de l’EDR, qui ne sera alors plus en mesure de détecter des programmes malveillants, même connus statiquement. Il existe différents exemples open-source, comme [**EDRSandBlast**](https://github.com/wavestone-cdt/EDRSandblast).

Différents vendeurs de solution d’EDR ont déjà [**signalé avoir observé ce genre de comportement**](https://www.trendmicro.com/en_us/research/22/h/ransomware-actor-abuses-genshin-impact-anti-cheat-driver-to-kill-antivirus.html) lors de vraies intrusions.

Pour contrer cela, depuis Windows 11, une *blocklist* de *drivers* connus comme vulnérables existe, mais la liste n’est pas forcément à jour, et tous les *drivers* vulnérables ne sont pas forcément connus.
