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
mora-hwbp — Moteur de hooking en mode utilisateur sans patch et d'instrumentation de télémétrie basé sur les points d'arrêt matériels (DR0-DR7) (PoC AMSI, WLDP et ETW). | Kitploit
Outils/GitHubGitHub/dovughs/mora-hwbp
Outils DéfensifsÉvasion IDS/IPSDébogueursApprentissage et ÉducationRed TeamingAttaque Adversariale
GitHubdovughs/mora-hwbp

mora-hwbp

Moteur de hooking en mode utilisateur sans patch et d'instrumentation de télémétrie basé sur les points d'arrêt matériels (DR0-DR7) (PoC AMSI, WLDP et ETW).

Voir le dépôt
10il y a 1 jourPas encore vérifié

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

Mora-HWBP — Hooking de télémétrie AMSI / WLDP / ETW via des points d'arrêt matériels

Un Proof-of-Concept (POC) de recherche en sécurité démontrant le hooking de fonctions basé sur les points d'arrêt matériels (registres de débogage du CPU) comme alternative au patch de code en mémoire traditionnel.

Objectif et portée

Ce dépôt est publié strictement pour la recherche en sécurité défensive, l'éducation red-team / purple-team, l'ingénierie de détection et l'étude académique des mécanismes internes de Windows. Il démontre comment un attaquant pourrait abuser des registres de débogage du processeur pour neutraliser la télémétrie de sécurité en mode utilisateur — et, tout aussi important, ce que les défenseurs doivent surveiller afin de détecter de telles techniques. L'auteur n'est pas responsable de toute utilisation abusive de ce code. L'utilisation de cette technique contre des systèmes sans autorisation explicite est illégale et viole les lois relatives à la fraude informatique et aux abus dans la plupart des juridictions. Ne déployez pas ceci dans un environnement que vous ne possédez pas ou pour lequel vous n'avez pas d'autorisation écrite explicite de test.


Table des matières

  1. Aperçu
  2. Contexte — Pourquoi des points d'arrêt matériels ?
  3. Composants de sécurité ciblés
  4. Architecture
  5. Plongée technique approfondie
    • 5.1 Points d'arrêt matériels sur x64
    • 5.2 Disposition des registres de débogage (DR0–DR7)
    • 5.3 Le gestionnaire d'exceptions vectorisées (VEH)
    • 5.4 Logique d'interception par composant
    • 5.5 Gestion des threads et persistance du hook
  6. API exportée
  7. Instructions de compilation
  8. Exemple d'injection et d'utilisation
  9. Détection et atténuation (Blue Team)
  10. Limites connues
  11. Références

Aperçu

mora_hwbp.c implémente une DLL qui, une fois chargée/injectée dans un processus cible (par exemple, un hôte PowerShell), hooke quatre fonctions en mode utilisateur exclusivement via des points d'arrêt matériels du CPU stockés dans les registres de débogage architecturaux (DR0–DR7) de chaque thread du processus :

Un gestionnaire d'exceptions vectorisées (VEH) par processus reçoit les défauts EXCEPTION_SINGLE_STEP (0x80000004) déclenchés par les registres de débogage, simule le chemin de retour réussi de la fonction d'origine en réécrivant le contexte d'exception, puis reprend l'exécution — le tout sans modifier un seul octet de mémoire exécutable.

Cela rend la technique particulièrement intéressante d'un point de vue offensif comme défensif :

  • Offensivement, elle contourne les vérifications d'intégrité EDR/HIPS qui recherchent des sections .text modifiées (hooking inline classique, patch EAT/IAT, ou stub Etwp*).
  • Défensivement, les points d'arrêt matériels laissent des artefacts forensiques très distinctifs (contenu des registres de débogage, densité d'exceptions single-step, enregistrement du VEH, motifs d'appels système GetThreadContext/SetThreadContext) qui peuvent être utilisés pour la détection.

Contexte — Pourquoi des points d'arrêt matériels ?

Les approches traditionnelles de hooking en mode utilisateur — detours inline (écrasements de 5 à 14 octets), hooking de la table d'adresses d'importation (IAT) et hooking de la table d'adresses d'exportation (EAT) — partagent une faiblesse commune : elles modifient de la mémoire que les scanners d'intégrité et l'ETW peuvent observer.

Les produits AV/EDR modernes implémentent :

  • Analyse mémoire / scans AMSI des tampons PowerShell et .NET CLR ;
  • Télémétrie basée sur ETW (Microsoft-Windows-PowerShell, .NET ETW, fournisseurs de renseignements sur les menaces) ;
  • Callbacks noyau et vérifications d'intégrité en mode utilisateur qui détectent les astuces pageguard/guard-page, les transitions VirtualProtect vers PAGE_EXECUTE_READWRITE, et les incohérences de hachage de section.

Les points d'arrêt matériels contournent tout cela :

  1. Ce sont des registres CPU, pas de la mémoire — il n'y a rien à analyser dans .text.
  2. Ils sont définis par thread via l'API Windows SetThreadContext, ce qui ne déclenche pas les signaux classiques de « mémoire modifiée » utilisés par les scanners d'intégrité.
  3. Le point d'interception est entièrement géré par le dispatch d'exceptions du processeur, qui passe par la chaîne VEH du processus avant que toute fonction cible en mode utilisateur ne s'exécute.

Ce POC explore l'efficacité et la détectabilité de cette technique contre AMSI (Antimalware Scan Interface), WLDP (Windows Lockdown Policy) et ETW (Event Tracing for Windows) — les trois primitives de sécurité en mode utilisateur les plus utilisées dans la pile de sécurité Windows moderne.


Composants de sécurité ciblés

AMSI — Interface d'analyse antimalware

AMSI est le point d'intégration de la plateforme Windows qui permet aux applications (PowerShell, Office, VBScript, hôtes .NET, etc.) de demander l'analyse de contenu aux fournisseurs antimalware enregistrés. Deux points d'entrée présentent un intérêt majeur :

  • AmsiScanBuffer(HANDLE hamsiContext, PVOID buffer, ULONG length, LPCWSTR contentName, HANDLE hamsiSession, AMSI_RESULT *pResult)
  • AmsiScanString(HANDLE hamsiContext, LPCWSTR string, LPCWSTR contentName, HANDLE hamsiSession, AMSI_RESULT *pResult)

En forçant le AMSI_RESULT retourné à AMSI_RESULT_CLEAN (0), le moteur de script croit que le contenu a été inspecté et jugé bénin, l'exécution se poursuit donc sans interruption.

WLDP — Windows Lockdown Policy

WLDP implémente l'évaluation des politiques pour Windows Defender Application Control (WDAC / Device Guard). WldpIsClassInApprovedList répond si une classe COM donnée (identifiée par GUID) est autorisée par la politique actuelle. AMSI consulte en interne WLDP pour décider si certaines classes de scripts/contenus sont « de confiance » (dans la liste approuvée). Si la fonction signale la classe comme approuvée, AMSI peut éviter un examen supplémentaire pour ce type de contenu.

La DLL définit le paramètre de sortie isApproved (RDX) à TRUE et retourne S_OK, ce qui fait apparaître la classe évaluée comme digne de confiance.

ETW — Event Tracing for Windows

EtwEventWrite dans ntdll.dll est le puits (sink) central en mode utilisateur pour pratiquement toute émission d'événements ETW sur le système. Le supprimer a des effets secondaires importants pour la surveillance de sécurité :

  • Les événements de journalisation du pipeline PowerShell et des blocs de script
  • Les événements de chargement d'assemblys .NET (Microsoft-Windows-DotNETRuntime)
  • La télémétrie des résultats d'analyse AMSI
  • Les événements des fournisseurs de renseignements sur les menaces consommés par les agents EDR

La DLL retourne simplement ERROR_SUCCESS (0) sans exécuter la fonction réelle.


Architecture```

┌──────────────────────────────────────────────────────────────────────────┐ │ Target Process (e.g. powershell.exe) │ │ │ │ ┌──────────────────────────┐ ┌──────────────────────────────────┐│ │ │ mora_hwbp.dll │ │ CPU / Windows ││ │ │ │ │ ││ │ │ DllMain / InstallHook │ │ Thread A Thread B ││ │ │ │ │ │ ┌────────┐ ┌────────┐ ││ │ │ ▼ │ │ │ DR0..3 │ │ DR0..3 │ ││ │ │ Resolve exports │ │ └────────┘ └────────┘ ││ │ │ (amsi/wldp/ntdll) │ │ ││ │ │ │ │ │ #DB (single-step) ││ │ │ ▼ │ │ exception ──► Windows Dispatch ││ │ │ AddVectoredException │ │ │ ││ │ │ Handler(VEH) │ │ ▼ ││ │ │ │ │ │ ┌─────────────────────────────┐ ││ │ │ ▼ │ │ │ VectoredHandler (ours) │ ││ │ │ SetHwbpOnThread(ALL) │ │ │ • match #DB address │ ││ │ │ │ │ │ │ • rewrite context (RIP/RSP)│ ││ │ │ ▼ │ │ │ • spoof return value (RAX) │ ││ │ │ MonitorThread ◄──┐ │ │ │ • continue execution │ ││ │ │ (re-hook every │ │ │ └─────────────────────────────┘ ││ │ │ 500ms) └──────┘ │ ││ │ └──────────────────────────┘ └──────────────────────────────────┘│ └──────────────────────────────────────────────────────────────────────────┘

root@kitploit:~
**Flux de haut niveau :**

1. La DLL est chargée dans le processus cible (via n'importe quelle technique d'injection — voir [Utilisation](#injection--usage-example)).
2. Sur `DLL_PROCESS_ATTACH` (ou via l'export `InstallHook`), les exports cibles sont résolus avec `GetProcAddress` (en forçant éventuellement le chargement de modules via `LoadLibraryW`).
3. Un **Vectored Exception Handler** est enregistré comme **premier** gestionnaire du processus (`AddVectoredExceptionHandler(1, ...)`).
4. Le **thread courant** est hooké immédiatement, puis **tous les threads existants** du processus sont énumérés via `CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0)` et hookés.
5. Un **thread de surveillance** se réveille toutes les 500 ms et réapplique les breakpoints sur chaque thread — y compris les **threads nouvellement créés** — garantissant la persistance du hook même si un thread est créé après le hooking ou si les breakpoints sont effacés de l'extérieur.
6. Lorsqu'une fonction hookée est appelée sur n'importe quel thread, le CPU lève une exception single-step `#DB` ; Windows la distribue au VEH, qui simule un retour bénin et poursuit l'exécution.

### Exemple de sortie de débogage

![Diagnostics d'état du moteur de hook HWBP capturés dans Sysinternals DebugView](https://assets.kitploit.com/production/public/readmes/50594/5cf99fadc07272ff598cbb9486ff7803a3234eb6aeaa8202684c27e97bd7e161.png)

*Figure 1 — Exemple de sortie de diagnostics capturée avec Sysinternals DebugView. Chaque ligne rapporte l'adresse cible résolue et le compteur de hits en direct pour son registre de débogage correspondant.*

---

## Plongée technique approfondie

### 5.1 Breakpoints matériels sur x64

Sur x86/x64, chaque CPU fournit **quatre registres d'adresses de débogage matériel** (`DR0`–`DR3`) et un registre de contrôle (`DR7`). Tout thread s'exécutant avec un breakpoint non nul dans `DR0`–`DR3` déclenchera une faute dès que le pointeur d'instruction atteint cette adresse (ou si l'accès aux données correspond aux conditions configurées). Le registre de statut `DR6` enregistre quel breakpoint a été déclenché.

Les breakpoints matériels sont **sensibles au contexte** : ils sont stockés dans la structure `CONTEXT` du thread et ne s'appliquent qu'au thread sur lequel ils sont définis. C'est pourquoi une implémentation robuste doit définir des breakpoints sur **chaque thread** du processus (et les réappliquer en continu pour les nouveaux threads).

### 5.2 Disposition des registres de débogage (DR0–DR7)

`DR7` est un champ de bits contrôlant l'activation et le comportement des breakpoints :

| Bits   | Champ | Signification                                    |
|--------|-------|--------------------------------------------------|
| `0`    | `L0`  | Activation locale pour le breakpoint 0 (DR0)     |
| `2`    | `L1`  | Activation locale pour le breakpoint 1 (DR1)     |
| `4`    | `L2`  | Activation locale pour le breakpoint 2 (DR2)     |
| `6`    | `L3`  | Activation locale pour le breakpoint 3 (DR3)     |
| `8`    | `LE`  | Activation locale héritée (conservée pour compatibilité) |
| `9`    | `GE`  | Activation globale héritée (conservée pour compatibilité) |
| `16–17`| `R/W0`| Type d'accès pour BP0 (`00` = exécution d'instruction) |
| `18–19`| `Len0`| Longueur pour BP0 (`00` = 1 octet)               |
| `20–21`| `R/W1`| Type d'accès pour BP1 (`00` = exécution d'instruction) |
| `22–23`| `Len1`| Longueur pour BP1 (`00` = 1 octet)               |
| `24–25`| `R/W2`| Type d'accès pour BP2 (`00` = exécution d'instruction) |
| `26–27`| `Len2`| Longueur pour BP2 (`00` = 1 octet)               |
| `28–29`| `R/W3`| Type d'accès pour BP3 (`00` = exécution d'instruction) |
| `30–31`| `Len3`| Longueur pour BP3 (`00` = 1 octet)               |

Les quatre breakpoints sont configurés pour **l'exécution (fetch d'instruction) sur un seul octet**, ce qui est la condition appropriée pour des hooks d'entrée de fonction.

### 5.3 Le Vectored Exception Handler (VEH)

Lorsqu'un breakpoint se déclenche, le processeur lève une exception `#DB`. Sur Windows x64, la routine de dispatch de `ntdll` la route à travers la **chaîne VEH** du processus avant la chaîne de Structured Exception Handler (SEH) du thread. Le gestionnaire de ce projet :

1. **Filtre** — ne gère que `EXCEPTION_SINGLE_STEP` (`0x80000004`) ; tout le reste est transmis à `EXCEPTION_CONTINUE_SEARCH`.
2. **Fait correspondre** — compare `ExceptionAddress` avec les quatre adresses de fonctions connues.
3. **Réécrit le contexte** :
   - `RIP = *(RSP)` → « retourne » à l'appelant d'origine en dépilant l'adresse de retour.
   - `RSP += 8` → simule un `ret` (déroulage à instruction unique x64).
   - `RAX = 0` → simule `S_OK` / `ERROR_SUCCESS` (code de retour de succès).
   - `DR6 &= ~0xF` → efface les bits de statut du breakpoint afin que l'instruction puisse être ré-exécutée plus tard sans état parasite.
4. **Mute les paramètres de sortie** (voir [5.4](#54-per-component-interception-logic)).
5. **Retourne `EXCEPTION_CONTINUE_EXECUTION`**, ce qui indique à Windows de redémarrer le thread avec le contexte modifié — c'est-à-dire que l'exécution reprend chez l'*appelant*, et que la fonction cible réelle **ne s'exécute jamais**.

Chaque site d'interception est en outre enveloppé dans une protection SEH `__try/__except` afin qu'une disposition de pile inattendue ou malformée ne puisse pas faire planter le processus — une considération de robustesse pour les cibles hostiles/renforcées.

### 5.4 Logique d'interception par composant

**DR0 — `AmsiScanBuffer`** (x64, 6 premiers arguments dans `RCX, RDX, R8, R9, [RSP+0x28], [RSP+0x30]`) :```
HRESULT AmsiScanBuffer(HANDLE, PVOID, ULONG, LPCWSTR, HANDLE, AMSI_RESULT* pResult);
                                                        [RSP+0x28]  [RSP+0x30]
  • Écrit AMSI_RESULT_CLEAN (0) dans le 6e paramètre (pResult, à [RSP+0x30]).
  • Retourne S_OK (0) dans RAX.

DR1 — AmsiScanString (x64, les 5 premiers arguments dans RCX, RDX, R8, R9, [RSP+0x28]) :``` HRESULT AmsiScanString(HANDLE, LPCWSTR, LPCWSTR, HANDLE, AMSI_RESULT* pResult); [RSP+0x28]

root@kitploit:~
- Écrit `AMSI_RESULT_CLEAN (0)` dans le 5ᵉ paramètre (`pResult`, à `[RSP+0x28]`).
- Renvoie `S_OK (0)` dans `RAX`.

**DR2 — `WldpIsClassInApprovedList`** (les 3 premiers arguments dans `RCX, RDX, R8`):```
HRESULT WldpIsClassInApprovedList(const GUID* classId, PBOOL isApproved, DWORD evalCriteria);
                                         RCX             RDX             R8
  • Écrit TRUE dans *isApproved (via RDX).
  • Retourne S_OK (0) dans RAX.
  • Conséquence : la classe de contenu évaluée est considérée comme « approuvée » par la politique de verrouillage, et AMSI fait confiance à ce jugement pour la classe.

DR3 — EtwEventWrite (les 4 premiers arguments dans RCX, RDX, R8, R9) :``` ULONG EtwEventWrite(HANDLE RegHandle, PCEVENT_DESCRIPTOR EventDescriptor, ULONG UserDataCount, PEVENT_DATA_DESCRIPTOR UserData);

root@kitploit:~
- Renvoie `ERROR_SUCCESS (0)` dans `RAX` sans toucher à aucun paramètre de sortie.
- Conséquence : les fournisseurs ETW ne reçoivent **aucun** événement du processus hooké, supprimant ainsi la journalisation de l'exécution de scripts, du chargement de modules, de la création de processus et de la télémétrie AMSI.

### 5.5 Gestion des threads et persistance des hooks

Comme les registres de débogage sont propres à chaque thread, le moteur doit maintenir les hooks en continu :

1. **Hook immédiat** — `DllMain` (ou `InstallHook`) hook le thread appelant avec `SetHwbpOnThread(GetCurrentThread())`.
2. **Balayage de tous les threads** — `HookAllThreads()` énumère chaque thread du processus via un instantané `TH32CS_SNAPTHREAD`, suspend chaque thread externe (`SuspendThread`), applique les points d'arrêt (`SetHwbpOnThread`), le reprend et ferme le handle. La suspension empêche une condition de course dans laquelle le thread plante au milieu d'un changement de contexte entre `GetThreadContext` et `SetThreadContext`.
3. **Moniteur de persistance** — `MonitorThreadProc` boucle avec `Sleep(500)` et appelle `HookAllThreads()` toutes les 500 ms. Cela **réarme tous les points d'arrêt qui ont été supprimés** (par exemple, par un appel externe à `SetThreadContext`, un outil de débogage ou la destruction/création de threads) et **couvre les threads créés après le hook initial**.
4. **Synchronisation** — `HookAllThreads` s'exécute sous une `CRITICAL_SECTION` (`g_HookLock`) afin que le thread moniteur et la routine de hook initiale n'entrelacent jamais les changements de contexte.
5. **Arrêt propre** — `UninstallHook` arrête le moniteur, efface `DR0–DR7` sur chaque thread et désenregistre le VEH.

> **Réponse explicite à la question de la « persistance des hooks » :** oui — si les points d'arrêt sont retirés d'un thread (par un autre agent, un débogueur ou un EDR), le thread moniteur **les réapplique dans les 500 ms**. De plus, tout thread créé après le chargement de la DLL est hooké dans un cycle du moniteur. La seule façon fiable de vaincre ce moteur spécifique est de terminer le thread moniteur *et* d'effacer le VEH *et* de retirer les registres dans la même fenêtre — ou d'utiliser un anti-débogage qui refuse `SetThreadContext` dès le départ.

---

## API exportée

| Exportation       | Signature                          | Comportement                                                        |
|-------------------|------------------------------------|-----------------------------------------------------------------------|
| `InstallHook`     | `BOOL WINAPI InstallHook(void)`    | Résout les cibles, enregistre le VEH, hook tous les threads, démarre le moniteur. |
| `UninstallHook`   | `BOOL WINAPI UninstallHook(void)`  | Arrête le moniteur, efface les points d'arrêt sur tous les threads, supprime le VEH. |
| `GetStats`        | `void WINAPI GetStats(void)`       | Émet l'état actuel du hook (via `OutputDebugStringA`) — adresse, compteurs de hits. |

Les compteurs de hits (`g_HaveAmsiBuf`, `g_HaveAmsiStr`, `g_HaveWldp`, `g_HaveEtw`) sont maintenus avec `InterlockedIncrement` et sont exposés dans la sortie de débogage, ce qui est utile pour valider que l'interception se produit réellement dans un environnement de laboratoire.

Notez que `DllMain` exécute lui-même la séquence de hook complète sur `DLL_PROCESS_ATTACH` ; les exports sont donc des commodités facultatives pour les scénarios de chargement/déchargement à l'exécution.

---

## Instructions de compilation

**Prérequis :** Windows 10/11 x64, Visual Studio Build Tools (`icx.exe`), SDK.

Compilez la DLL (x64) :```bat
icx.exe /nologo /O3 /MT /EHsc "mora_hwbp.c" /link /DLL /out:"mora_hwbp.dll" /LIBPATH:"C:\Program Files (x86)\Intel\oneAPI\compiler\latest\lib"

Flags explained:

FlagPurpose

Le résultat est mora_hwbp.dll, qui peut être chargé dans un processus cible.


Exemple d'injection et d'utilisation

La DLL doit être chargée dans un processus qui utilise AMSI/WLDP/ETW — un hôte PowerShell est le banc d'essai canonique. Le chargement peut être effectué avec toute technique standard d'injection de DLL. Une démonstration minimale et autonome utilisant l'injection réflective/LoadLibrary peut être réalisée avec un petit chargeur C :```bat rem Run from an x64 developer prompt (example with a generic loader) loader.exe mora_hwbp.dll powershell.exe

root@kitploit:~
Ou, pour une vérification manuelle en laboratoire, injectez avec l'outil de votre choix, puis validez depuis PowerShell :```powershell
# 1. Inject mora_hwbp.dll into the PowerShell process (via external tool).
# 2. Verify that classic AMSI test vectors now return clean.
"AmsiTestSample:7e72c3ce-861b-4339-8740-0ac1484c1386"

Validation en laboratoire uniquement. Observez avec un débogueur ou GetStats/OutputDebugString que les quatre points d'arrêt signalent des hits lorsque le contenu du script est exécuté.


Détection et atténuation (équipe bleue)

Cette POC a un double objectif : les mêmes caractéristiques qui la rendent efficace offensivement sont précisément ce que les défenseurs doivent rechercher.

Indicateurs de compromission (IOCs)

Atténuations recommandées

  1. Agents de surveillance/auto-surveillance — interrogez GetThreadContext(CONTEXT_DEBUG_REGISTERS) sur les processus à haute valeur et auditez tout thread dont les DR0–DR3 sont non nuls en dehors des profils de débogueur approuvés.
  2. Audit ETW du noyau — activez le traçage Microsoft-Windows-Kernel-Process + Thread et alertez sur NtGetContextThread/NtSetThreadContext ciblant des processus critiques pour la sécurité.
  3. Intégrité des hooks en mode utilisateur de l'EDR — puisque les hooks matériels contournent les vérifications de mémoire, appuyez-vous sur la détection comportementale (hooks de consommateurs ETW sous EtwEventWrite, ETW du noyau, re-vérification du consommateur AMSI) plutôt que sur la seule intégrité .text.
  4. Protégez le moniteur — dans des environnements réellement hostiles, traitez un SetThreadContext par thread vers d'autres processus comme un signal explicite de gravité élevée.
  5. Durcissement des points de terminaison — activez WDAC (que cette POC contourne explicitement pour l'approbation de la classe — ne traitez pas WDAC comme une défense autonome contre les outils en mémoire), Credential Guard et la protection LSASS le cas échéant.

Limitations connues

  • x64 uniquement — les réécritures de décalages de pile supposent la convention d'appel x64 (arguments RCX/RDX/R8/R9 puis [RSP+0x20…]). Une variante x86 nécessiterait une reconstruction des paramètres de type [EBP+…].
  • Quatre emplacements seulement — l'architecture x64 offre exactement quatre registres de points d'arrêt ; vous ne pouvez pas hooker plus de quatre fonctions par thread avec cette seule méthode.
  • Fenêtre de course du moniteur — il existe une fenêtre (intentionnellement petite) entre les itérations de Sleep(500) ; une création de threads extrêmement rapide combinée à une suppression agressive pourrait théoriquement distancer le moniteur pendant quelques centaines de millisecondes.
  • Interférence anti-débogage — tout composant qui surveille ou efface activement les registres de débogage (un véritable débogueur, certains bacs à sable, certains EDR) interférera avec la technique.
  • Statut basé sur OutputDebugStringA — les diagnostics reposent sur un canal de sortie de débogage ; dans un environnement entièrement dépouillé/sans tête, vous devriez attacher un débogueur ou rediriger la sortie pour l'observation en laboratoire.
  • Ce n'est pas une primitive de persistance mémoire — c'est une technique exclusivement runtime, intra-processus. Elle ne fournit aucune persistance disque/registre, aucune élévation de privilèges et aucun mouvement latéral inter-processus par elle-même. Son seul but est l'étude contrôlée d'une primitive d'interception.

Références

  • Microsoft Learn — Antimalware Scan Interface (AMSI)
  • Microsoft Learn — Windows Lockdown Policy (WLDP)
  • Microsoft Learn — Event Tracing for Windows (ETW)
  • Microsoft Learn — CONTEXT structure & Debug Registers
  • Intel® 64 and IA-32 Architectures Software Developer's Manual, Vol. 3B — Debug Registers (Dr0–Dr7, #DB exception)

Licence et divulgation responsable

Ce projet est sous licence MIT - voir le fichier LICENSE pour plus de détails.

Ce projet est publié à des fins exclusivement éducatives et de recherche défensive. Si vous êtes un éditeur de sécurité, un membre d'une équipe bleue ou un ingénieur en détection, vous êtes encouragé à utiliser le contenu de ce dépôt pour améliorer votre couverture de détection de l'évasion basée sur les points d'arrêt matériels. Si vous découvrez que cette technique est utilisée abusivement dans la nature, signalez-le via le processus de divulgation responsable de votre organisation et les canaux du fournisseur ou des autorités concernés.

À utiliser à vos propres risques. Une utilisation non autorisée de cette technique peut enfreindre les lois applicables.

Télécharger l’outil
RegistreFonction hookéeModuleObjectif
DR0AmsiScanBufferamsi.dllNeutraliser l'analyse de contenu AMSI
DR1AmsiScanStringamsi.dllNeutraliser l'analyse de chaînes AMSI
DR2WldpIsClassInApprovedListwldp.dllForcer l'approbation de classe WLDP (Device Guard / WDAC)
DR3EtwEventWritentdll.dllSupprimer le traçage d'événements ETW
/O3Optimisation maximale (code de fonction, non requis)
/MTLiaison CRT statique (aucune dépendance à une DLL d'exécution)
/EHscGestion des exceptions C++/SEH (nécessaire pour __try)
/DLLProduire une DLL avec une table d'exportation
ArtefactObservable
Appels GetThreadContext / SetThreadContextChangements de contexte de registres de débogage à haute fréquence sur d'autres processus/threads (ETW du noyau : Microsoft-Windows-Kernel-Process/API Thread).
DR0–DR3 non nulsTout thread dont CONTEXT_DEBUG_REGISTERS contient une adresse en mode utilisateur en dehors des flux de travail connus du débogueur.
DR7 bits d'activation locaux (L0–L3) avec R/W = 00Points d'arrêt en exécution seule sur des threads non gérés par le débogueur — une forte anomalie.
Volume EXCEPTION_SINGLE_STEPTaux élevés de fautes #DB (0x80000004) provenant du VEH d'un processus.
Enregistrement VEH de première chanceVEH nouvellement ajouté (AddVectoredExceptionHandler) peu avant la tempête de #DB.
TH32CS_SNAPTHREAD + SuspendThread/ResumeThreadModèles répétés d'énumération de threads + de suspension (utilisés par le moniteur de 500 ms).
Chargement de wldp.dll/amsi.dll via LoadLibraryW lorsqu'ils n'étaient pas chargés auparavantChargements de modules anormaux dans le processus cible.
EtwEventWrite jamais atteintAbsence d'événements ETW attendus (journaux opérationnels PowerShell silencieux pendant l'exécution des scripts).