Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
Tools/GitHubGitHub/dovughs/mora-hwbp
DefensivwerkzeugeIDS/IPS-UmgehungDebuggerLernen & BildungRed TeamingAdversarial-Angriff
GitHubdovughs/mora-hwbp

mora-hwbp

Auf Hardware-Breakpoints (DR0-DR7) basierende, patch-lose User-Mode-Hooking- und Telemetrie-Instrumentierungs-Engine (AMSI, WLDP & ETW-PoC).

Repository anzeigen
10vor 1 TagNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

Mora-HWBP — AMSI / WLDP / ETW Telemetrie-Hooking über Hardware-Breakpoints

Ein Proof-of-Concept (POC) aus der Sicherheitsforschung, das auf Hardware-Breakpoints (CPU-Debug-Register) basierendes Funktions-Hooking als Alternative zum herkömmlichen In-Memory-Code-Patching demonstriert.

Zweck & Umfang

Dieses Repository wird ausschließlich für defensive Sicherheitsforschung, Red-/Purple-Team-Ausbildung, Detection Engineering und akademische Studien der Windows-Interna veröffentlicht. Es zeigt, wie ein Angreifer Prozessor-Debug-Register missbrauchen könnte, um benutzermodusseitige Sicherheitstelemetrie zu neutralisieren – und, ebenso wichtig, was Verteidiger überwachen sollten, um solche Techniken zu erkennen. Der Autor ist nicht für jeglichen Missbrauch dieses Codes verantwortlich. Die Verwendung dieser Technik gegen Systeme ohne ausdrückliche Genehmigung ist illegal und verstößt in den meisten Rechtsräumen gegen die einschlägigen Computerbetrugs- und Missbrauchsgesetze. Setzen Sie dies nicht in einer Umgebung ein, die Sie nicht besitzen oder für die Sie keine ausdrückliche schriftliche Genehmigung zum Testen haben.


Inhaltsverzeichnis

  1. Überblick
  2. Hintergrund — Warum Hardware-Breakpoints?
  3. Zielkomponenten der Sicherheit
  4. Architektur
  5. Technischer Tiefgang
    • 5.1 Hardware-Breakpoints unter x64
    • 5.2 Aufbau der Debug-Register (DR0–DR7)
    • 5.3 Der Vectored Exception Handler (VEH)
    • 5.4 Abfanglogik pro Komponente
    • 5.5 Thread-Verwaltung & Hook-Persistenz
  6. Exportierte API
  7. Build-Anleitung
  8. Injektion & Anwendungsbeispiel
  9. Erkennung & Maßnahmen (Blue Team)
  10. Bekannte Einschränkungen
  11. Referenzen

Überblick

mora_hwbp.c implementiert eine DLL, die nach dem Laden/Injizieren in einen Zielprozess (z. B. einen PowerShell-Host) vier Benutzermodus-Funktionen ausschließlich über CPU-Hardware-Breakpoints hookt, die in den architektonischen Debug-Registern (DR0–DR7) jedes Threads im Prozess gespeichert sind:

Ein prozessweiter Vectored Exception Handler (VEH) empfängt die von den Debug-Registern ausgelösten EXCEPTION_SINGLE_STEP-Fehler (0x80000004), simuliert den erfolgreichen Rückgabepfad der ursprünglichen Funktion, indem er den Ausnahmekontext umschreibt, und setzt die Ausführung fort – alles ohne ein einziges Byte ausführbaren Speichers zu verändern.

Das macht die Technik sowohl aus offensiver als auch aus defensiver Sicht besonders interessant:

  • Offensiv umgeht es die Integritätsprüfungen von EDR/HIPS, die nach modifizierten .text-Abschnitten suchen (klassisches Inline-Hooking, EAT/IAT-Patching oder Etwp*-Stubbing).
  • Defensiv hinterlassen Hardware-Breakpoints äußerst charakteristische forensische Artefakte (Inhalte der Debug-Register, Dichte von Single-Step-Ausnahmen, VEH-Registrierung, GetThreadContext/SetThreadContext-Syscall-Muster), die zur Erkennung genutzt werden können.

Hintergrund — Warum Hardware-Breakpoints?

Traditionelle Hooking-Ansätze im Benutzermodus – Inline-Detours (Überschreibungen von 5–14 Bytes), Import Address Table (IAT)-Hooking und Export Address Table (EAT)-Hooking – haben eine gemeinsame Schwäche: Sie verändern Speicher, den Integritätsscanner und ETW beobachten können.

Moderne AV/EDR-Produkte implementieren:

  • Speicherscans / AMSI-Scans von PowerShell- und .NET-CLR-Puffern;
  • ETW-basierte Telemetrie (Microsoft-Windows-PowerShell, .NET-ETW, Threat-Intelligence-Anbieter);
  • Kernel-Callbacks und Benutzermodus-Integritätsprüfungen, die pageguard/guard-page-Tricks, VirtualProtect-Übergänge zu PAGE_EXECUTE_READWRITE und Abschnitts-Hash-Abweichungen erkennen.

Hardware-Breakpoints umgehen all dies:

  1. Sie sind CPU-Register, kein Speicher – es gibt nichts in .text zu scannen.
  2. Sie werden pro Thread über die Windows-API SetThreadContext gesetzt, was die klassischen „Speicher geändert“-Signale, die Integritätsscanner verwenden, nicht auslöst.
  3. Der Abfangpunkt wird vollständig von der Ausnahmezustellung des Prozessors übernommen, die über die VEH-Kette des Prozesses läuft, bevor eine Benutzermodus-Zielfunktion ausgeführt wird.

Dieses POC untersucht die Wirksamkeit und Erkennbarkeit dieser Technik gegen AMSI (Antimalware Scan Interface), WLDP (Windows Lockdown Policy) und ETW (Event Tracing for Windows) – die drei am weitesten verbreiteten Sicherheitsprimitiven im Benutzermodus des modernen Windows-Sicherheitsstapels.


Zielkomponenten der Sicherheit

AMSI — Antimalware Scan Interface

AMSI ist der Integrationspunkt der Windows-Plattform, der Anwendungen (PowerShell, Office, VBScript, .NET-Hosts usw.) ermöglicht, Inhalts-Scans bei registrierten Antimalware-Anbietern anzufordern. Zwei Einstiegspunkte sind von besonderem Interesse:

  • 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)

Indem das zurückgegebene AMSI_RESULT auf AMSI_RESULT_CLEAN (0) erzwungen wird, glaubt die Skript-Engine, dass der Inhalt geprüft und als gutartig befunden wurde, sodass die Ausführung ungehindert fortgesetzt wird.

WLDP — Windows Lockdown Policy

WLDP implementiert die Richtlinienauswertung für Windows Defender Application Control (WDAC / Device Guard). WldpIsClassInApprovedList beantwortet, ob eine bestimmte COM-Klasse (identifiziert durch GUID) gemäß der aktuellen Richtlinie zulässig ist. AMSI fragt intern WLDP ab, um zu entscheiden, ob bestimmte Skript-/Inhaltsklassen „vertrauenswürdig“ sind (in der genehmigten Liste). Wenn die Funktion die Klasse als genehmigt meldet, kann AMSI auf eine zusätzliche Prüfung dieses Inhaltstyps verzichten.

Die DLL setzt den Ausgabeparameter isApproved (RDX) auf TRUE und gibt S_OK zurück, sodass die bewertete Klasse als vertrauenswürdig erscheint.

ETW — Event Tracing for Windows

EtwEventWrite in ntdll.dll ist die zentrale Senke im Benutzermodus für praktisch alle ETW-Ereignisemissionen auf dem System. Das Unterdrücken hat weitreichende Nebenwirkungen, die für die Sicherheitsüberwachung relevant sind:

  • PowerShell-Pipeline- und Script-Block-Protokollierungsereignisse
  • .NET-Assembly-Ladeereignisse (Microsoft-Windows-DotNETRuntime)
  • AMSI-Ergebnistelemetrie
  • Threat-Intelligence-Anbieterereignisse, die von EDR-Agenten konsumiert werden

Die DLL gibt einfach ERROR_SUCCESS (0) zurück, ohne die eigentliche Funktion auszuführen.


Architektur```

┌──────────────────────────────────────────────────────────────────────────┐ │ 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:~
**High-level flow:**

1. Die DLL wird in den Zielprozess geladen (über beliebige Injektionstechniken — siehe [Verwendung](#injection--usage-example)).
2. Bei `DLL_PROCESS_ATTACH` (oder über den exportierten `InstallHook`) werden die Ziel-Exporte mit `GetProcAddress` aufgelöst (optional wird das Laden von Modulen über `LoadLibraryW` erzwungen).
3. Ein **Vectored Exception Handler** wird als **erster** Handler im Prozess registriert (`AddVectoredExceptionHandler(1, ...)`).
4. Der **aktuelle Thread** wird sofort gehookt, danach werden **alle vorhandenen Threads** im Prozess über `CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0)` aufgezählt und gehookt.
5. Ein **Monitor-Thread** wacht alle 500 ms auf und wendet die Breakpoints auf jeden Thread erneut an — einschließlich **neu erstellter Threads** — und gewährleistet so die Persistenz der Hooks, selbst wenn ein Thread nach dem Hooken erzeugt wird oder Breakpoints extern gelöscht werden.
6. Wenn eine gehookte Funktion in einem beliebigen Thread aufgerufen wird, löst die CPU eine `#DB`-Single-Step-Ausnahme aus; Windows leitet sie an den VEH weiter, der eine harmlose Rückkehr simuliert und die Ausführung fortsetzt.

### Beispiel-Debug-Ausgabe

![Diagnose des Hook-Status der HWBP-Engine, erfasst mit Sysinternals DebugView](https://assets.kitploit.com/production/public/readmes/50594/5cf99fadc07272ff598cbb9486ff7803a3234eb6aeaa8202684c27e97bd7e161.png)

*Abbildung 1 — Beispielhafte Diagnoseausgabe, erfasst mit Sysinternals DebugView. Jede Zeile meldet die aufgelöste Zieladresse und den laufenden Trefferzähler für das jeweilige Debug-Register.*

---

## Technischer Deep Dive

### 5.1 Hardware-Breakpoints auf x64

Auf x86/x64 stellt jede CPU **vier Hardware-Debug-Adressregister** (`DR0`–`DR3`) und ein Kontrollregister (`DR7`) bereit. Jeder Thread, der mit einem von Null verschiedenen Breakpoint in `DR0`–`DR3` ausgeführt wird, löst eine Ausnahme aus, sobald der Befehlszeiger diese Adresse erreicht (oder ein Datenzugriff den konfigurierten Bedingungen entspricht). Das Statusregister `DR6` zeichnet auf, welcher Breakpoint ausgelöst hat.

Hardware-Breakpoints sind **kontextsensitiv**: Sie werden in der `CONTEXT`-Struktur des Threads gespeichert und gelten nur für den Thread, auf dem sie gesetzt wurden. Aus diesem Grund muss eine robuste Implementierung die Breakpoints auf **jedem Thread** des Prozesses setzen (und sie für neue Threads kontinuierlich erneut anwenden).

### 5.2 Layout der Debug-Register (DR0–DR7)

`DR7` ist ein Bitfeld, das die Aktivierung und das Verhalten der Breakpoints steuert:

| Bits   | Feld  | Bedeutung                                             |
|--------|--------|-----------------------------------------------------|
| `0`    | `L0`   | Lokale Aktivierung für Breakpoint 0 (DR0)           |
| `2`    | `L1`   | Lokale Aktivierung für Breakpoint 1 (DR1)           |
| `4`    | `L2`   | Lokale Aktivierung für Breakpoint 2 (DR2)           |
| `6`    | `L3`   | Lokale Aktivierung für Breakpoint 3 (DR3)           |
| `8`    | `LE`   | Legacy lokale Aktivierung (aus Kompatibilitätsgründen beibehalten) |
| `9`    | `GE`   | Legacy globale Aktivierung (aus Kompatibilitätsgründen beibehalten) |
| `16–17`| `R/W0` | Zugriffstyp für BP0 (`00` = Befehlsausführung)      |
| `18–19`| `Len0` | Länge für BP0 (`00` = 1 Byte)                       |
| `20–21`| `R/W1` | Zugriffstyp für BP1 (`00` = Befehlsausführung)      |
| `22–23`| `Len1` | Länge für BP1 (`00` = 1 Byte)                       |
| `24–25`| `R/W2` | Zugriffstyp für BP2 (`00` = Befehlsausführung)      |
| `26–27`| `Len2` | Länge für BP2 (`00` = 1 Byte)                       |
| `28–29`| `R/W3` | Zugriffstyp für BP3 (`00` = Befehlsausführung)      |
| `30–31`| `Len3` | Länge für BP3 (`00` = 1 Byte)                       |

Alle vier Breakpoints sind für die **Ausführung (Befehlsabruf) auf einem einzelnen Byte** konfiguriert, was die passende Bedingung für Funktions-Einstiegshooks darstellt.

### 5.3 Der Vectored Exception Handler (VEH)

Wenn ein Breakpoint ausgelöst wird, erzeugt der Prozessor eine `#DB`-Ausnahme. Unter x64-Windows leitet die Dispatch-Routine von `ntdll` diese über die prozessweite **VEH-Kette** weiter, bevor die Structured-Exception-Handler-Kette (SEH) des Threads durchlaufen wird. Der Handler in diesem Projekt:

1. **Filtert** — behandelt nur `EXCEPTION_SINGLE_STEP` (`0x80000004`); alles andere fällt auf `EXCEPTION_CONTINUE_SEARCH` zurück.
2. **Gleicht ab** — vergleicht `ExceptionAddress` mit den vier bekannten Funktionsadressen.
3. **Schreibt den Kontext neu**:
   - `RIP = *(RSP)` → "return" zum ursprünglichen Aufrufer, indem die Rücksprungadresse vom Stack genommen wird.
   - `RSP += 8` → simuliert ein `ret` (x64-Einzelinstruktions-Unwind).
   - `RAX = 0` → täuscht `S_OK` / `ERROR_SUCCESS` vor (erfolgreicher Rückgabecode).
   - `DR6 &= ~0xF` → löscht die Breakpoint-Statusbits, sodass die Anweisung später ohne unerwünschten Zustand erneut ausgeführt werden kann.
4. **Verändert Ausgabeparameter** (siehe [5.4](#54-per-component-interception-logic)).
5. **Gibt `EXCEPTION_CONTINUE_EXECUTION` zurück**, was Windows anweist, den Thread mit dem geänderten Kontext neu zu starten — d. h. die Ausführung wird beim *Aufrufer* fortgesetzt und die eigentliche Zielfunktion **läuft nie**.

Jede Interception-Stelle ist zusätzlich mit einem SEH-`__try/__except`-Guard umschlossen, sodass ein fehlerhaftes oder unerwartetes Stack-Layout den Prozess nicht zum Absturz bringen kann — ein Robustheitsgesichtspunkt für feindliche/gehärtete Ziele.

### 5.4 Interceptionslogik pro Komponente

**DR0 — `AmsiScanBuffer`** (x64, die ersten 6 Argumente in `RCX, RDX, R8, R9, [RSP+0x28], [RSP+0x30]`):```
HRESULT AmsiScanBuffer(HANDLE, PVOID, ULONG, LPCWSTR, HANDLE, AMSI_RESULT* pResult);
                                                        [RSP+0x28]  [RSP+0x30]
  • Schreibt AMSI_RESULT_CLEAN (0) in den sechsten Parameter (pResult, bei [RSP+0x30]).
  • Gibt S_OK (0) in RAX zurück.

DR1 — AmsiScanString (x64, die ersten 5 Argumente in RCX, RDX, R8, R9, [RSP+0x28]):``` HRESULT AmsiScanString(HANDLE, LPCWSTR, LPCWSTR, HANDLE, AMSI_RESULT* pResult); [RSP+0x28]

root@kitploit:~
- Schreibt `AMSI_RESULT_CLEAN (0)` in den 5. Parameter (`pResult`, bei `[RSP+0x28]`).
- Gibt `S_OK (0)` in `RAX` zurück.

**DR2 — `WldpIsClassInApprovedList`** (die ersten 3 Argumente in `RCX, RDX, R8`):```
HRESULT WldpIsClassInApprovedList(const GUID* classId, PBOOL isApproved, DWORD evalCriteria);
                                         RCX             RDX             R8
  • Schreibt TRUE in *isApproved (über RDX).
  • Gibt S_OK (0) in RAX zurück.
  • Konsequenz: Die bewertete Inhaltsklasse wird von der Lockdown-Richtlinie als „approved“ betrachtet, und AMSI vertraut dieser Einschätzung für die Klasse.

DR3 — EtwEventWrite (erste 4 Argumente in RCX, RDX, R8, R9):``` ULONG EtwEventWrite(HANDLE RegHandle, PCEVENT_DESCRIPTOR EventDescriptor, ULONG UserDataCount, PEVENT_DATA_DESCRIPTOR UserData);

root@kitploit:~
- Gibt `ERROR_SUCCESS (0)` in `RAX` zurück, ohne einen Ausgabeparameter zu berühren.
- Konsequenz: ETW-Anbieter erhalten **keine** Ereignisse vom gehookten Prozess, wodurch die Protokollierung von Skriptausführung, Modulladungen, Prozesserstellung und AMSI-Telemetrie unterdrückt wird.

### 5.5 Thread-Verwaltung & Hook-Persistenz

Da Debug-Register pro Thread gelten, muss die Engine die Hooks kontinuierlich aufrechterhalten:

1. **Sofortiges Hooken** — `DllMain` (oder `InstallHook`) hookt den aufrufenden Thread mit `SetHwbpOnThread(GetCurrentThread())`.
2. **Durchlauf über alle Threads** — `HookAllThreads()` listet jeden Thread im Prozess über einen `TH32CS_SNAPTHREAD`-Snapshot auf, unterbricht jeden fremden Thread (`SuspendThread`), setzt die Breakpoints (`SetHwbpOnThread`), setzt ihn fort und schließt das Handle. Das Unterbrechen verhindert einen Wettlauf, bei dem der Thread mitten im Kontextwechsel zwischen `GetThreadContext` und `SetThreadContext` einen Fehler auslöst.
3. **Persistenz-Monitor** — `MonitorThreadProc` läuft in einer Schleife mit `Sleep(500)` und ruft alle 500 ms `HookAllThreads()` auf. Dadurch werden **entfernte Breakpoints wieder gesetzt** (z. B. durch einen externen `SetThreadContext`-Aufruf, ein Debugging-Tool oder das Beenden/Erzeugen von Threads) und **nach dem initialen Hook erstellte Threads abgedeckt**.
4. **Synchronisierung** — `HookAllThreads` läuft unter einem `CRITICAL_SECTION` (`g_HookLock`), sodass der Monitor-Thread und die anfängliche Hook-Routine keine Kontextwechsel überlappen.
5. **Sauberes Entfernen** — `UninstallHook` stoppt den Monitor, löscht `DR0–DR7` auf jedem Thread und hebt die VEH-Registrierung auf.

> **Antwort auf die Frage zur „Hook-Persistenz“ explizit:** ja — wenn die Breakpoints von einem Thread entfernt werden (durch einen anderen Agenten, einen Debugger oder eine EDR), **setzt der Monitor-Thread sie innerhalb von 500 ms erneut**. Darüber hinaus wird jeder nach dem Laden der DLL erstellte Thread innerhalb eines Monitorzyklus gehooked. Der einzige zuverlässige Weg, diese spezifische Engine zu überwinden, besteht darin, den Monitor-Thread zu beenden *und* die VEH zu entfernen *und* die Register im selben Fenster zu löschen — oder Anti-Debugging einzusetzen, das `SetThreadContext` von vornherein verweigert.

---

## Exportierte API

| Export            | Signature                          | Behavior                                                              |
|-------------------|------------------------------------|-----------------------------------------------------------------------|
| `InstallHook`     | `BOOL WINAPI InstallHook(void)`    | Ermittelt Zieladressen, registriert VEH, hookt alle Threads, startet den Monitor.   |
| `UninstallHook`   | `BOOL WINAPI UninstallHook(void)`  | Stoppt Monitor, löscht Breakpoints auf allen Threads, entfernt VEH.        |
| `GetStats`        | `void WINAPI GetStats(void)`       | Gibt aktuellen Hook-Status aus (über `OutputDebugStringA`) — Adresse, Trefferzähler. |

Die Trefferzähler (`g_HaveAmsiBuf`, `g_HaveAmsiStr`, `g_HaveWldp`, `g_HaveEtw`) werden mit `InterlockedIncrement` geführt und in der Debug-Ausgabe angezeigt, was nützlich ist, um zu validieren, dass die Interception in einer Laborumgebung tatsächlich stattfindet.

Beachten Sie, dass `DllMain` selbst die vollständige Hook-Sequenz bei `DLL_PROCESS_ATTACH` ausführt; die Exporte sind daher optionale Annehmlichkeiten für Szenarien, in denen die DLL zur Laufzeit geladen/entladen wird.

---

## Build-Anleitung

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

DLL kompilieren (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

Das Ergebnis ist mora_hwbp.dll, die in einen Zielprozess geladen werden kann.


Injection- und Anwendungsbeispiel

Die DLL muss in einen Prozess geladen werden, der AMSI/WLDP/ETW verwendet – ein PowerShell-Host ist das kanonische Testumfeld. Das Laden kann mit jeder gängigen DLL-Injection-Technik erfolgen. Eine minimale, eigenständige Demonstration mit Reflective/LoadLibrary-Injection kann mit einem kleinen C-Loader durchgeführt werden:```bat rem Run from an x64 developer prompt (example with a generic loader) loader.exe mora_hwbp.dll powershell.exe

root@kitploit:~
Oder injizieren Sie für einen manuellen Labortest mit Ihren bevorzugten Tools und validieren Sie dann von PowerShell aus:```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"

Nur Laborvalidierung. Beobachten Sie mit einem Debugger oder GetStats/OutputDebugString, dass alle vier Breakpoints Treffer melden, während Skriptinhalte ausgeführt werden.


Erkennung & Eindämmung (Blue Team)

Dieser POC dient einem doppelten Zweck: Genau die Eigenschaften, die ihn offensiv effektiv machen, sind das, wonach Verteidiger suchen sollten.

Indikatoren für eine Kompromittierung (IOCs)

Empfohlene Gegenmaßnahmen

  1. Watchdog-/Selbstüberwachungs-Agenten – GetThreadContext(CONTEXT_DEBUG_REGISTERS) bei Prozessen mit hohem Wert abfragen und jeden Thread mit von Null verschiedenen DR0–DR3 außerhalb genehmigter Debugger-Profile prüfen.
  2. Kernel-ETW-Überwachung – Microsoft-Windows-Kernel-Process + Thread-Ablaufverfolgung aktivieren und bei NtGetContextThread/NtSetContextThread warnen, die sicherheitsrelevante Prozesse betreffen.
  3. Integrität von EDR-Benutzermodus-Hooks – Da Hardware-Hooks Speicherprüfungen umgehen, sollte man sich auf verhaltensbasierte Erkennung verlassen (ETW-Consumer-Hooks unterhalb von EtwEventWrite, Kernel-ETW, erneute Prüfung durch AMSI-Consumer) anstatt nur auf .text-Integrität.
  4. Den Monitor schützen – In wirklich feindlichen Umgebungen sollte SetThreadContext pro Thread auf andere Prozesse als explizites Signal mit hoher Schwere behandelt werden.
  5. Endpoint-Härtung – WDAC aktivieren (das dieser POC für die Klassen-Freigabe ausdrücklich umgeht – WDAC nicht als eigenständige Verteidigung gegen In-Memory-Tools behandeln), Credential Guard und LSASS-Schutz, wo anwendbar.

Bekannte Einschränkungen

  • Nur x64 – Die Umschreibungen der Stack-Offsets setzen die x64-Aufrufkonvention voraus (Argumente RCX/RDX/R8/R9, dann [RSP+0x20…]). Eine x86-Variante bräuchte eine Parameterrekonstruktion im Stil von [EBP+…].
  • Nur vier Slots – Die x64-Architektur bietet genau vier Breakpoint-Register; mit dieser Methode allein können nicht mehr als vier Funktionen pro Thread gehookt werden.
  • Monitor-Race-Fenster – Es gibt ein (absichtlich kleines) Fenster zwischen den Sleep(500)-Iterationen; extrem schnelles Erzeugen von Threads in Kombination mit aggressivem Stripping könnte den Monitor theoretisch für ein paar hundert Millisekunden überholen.
  • Anti-Debug-Interferenz – Jede Komponente, die Debug-Register aktiv überwacht oder löscht (ein echter Debugger, einige Sandboxen, bestimmte EDRs), stört die Technik.
  • Status auf Basis von OutputDebugStringA – Die Diagnose ist auf einen Debug-Ausgabekanal angewiesen; in einer vollständig gestrippten/headless Umgebung sollten Sie einen Debugger anhängen oder die Ausgabe zur Laborbeobachtung umleiten.
  • Keine Speicher-Persistenz-Primitive – Dies ist eine reine Laufzeit-Technik innerhalb eines Prozesses. Sie bietet von sich aus keine Festplatten-/Registry-Persistenz, keine Privilegienausweitung und keine laterale Bewegung zwischen Prozessen. Ihr gesamter Zweck ist die kontrollierte Untersuchung einer Interception-Primitive.

Referenzen

  • 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)

Lizenz & Verantwortungsvolle Offenlegung

Dieses Projekt ist unter der MIT-Lizenz lizenziert – siehe LICENSE für Details.

Dieses Projekt wird ausschließlich für Bildungs- und Verteidigungsforschungszwecke veröffentlicht. Wenn Sie ein Sicherheitsanbieter, Blue Team oder Detection Engineer sind, werden Sie ermutigt, die Inhalte dieses Repositorys zu nutzen, um Ihre Erkennungsabdeckung für Evasion auf Basis von Hardware-Breakpoints zu verbessern. Wenn Sie feststellen, dass diese Technik in freier Wildbahn missbraucht wird, melden Sie dies über den Responsible-Disclosure-Prozess Ihres Unternehmens sowie über die entsprechenden Kanäle des Anbieters bzw. der Behörden.

Nutzung auf eigene Gefahr. Unautorisierte Nutzung dieser Technik kann geltendes Recht verletzen.

Tool herunterladen
RegisterGehookte FunktionModulZweck
DR0AmsiScanBufferamsi.dllAMSI-Inhaltsscans neutralisieren
DR1AmsiScanStringamsi.dllAMSI-Stringscans neutralisieren
DR2WldpIsClassInApprovedListwldp.dllWLDP-Klassenfreigabe erzwingen (Device Guard / WDAC)
DR3EtwEventWritentdll.dllETW-Ereignisablaufverfolgung unterdrücken
/O3Maximale Optimierung (Funktionscode, nicht erforderlich)
/MTStatische CRT-Verknüpfung (keine Runtime-DLL-Abhängigkeit)
/EHscC++/SEH-Ausnahmebehandlung (für __try erforderlich)
/DLLErzeugt eine DLL mit einer Exporttabelle
ArtefaktBeobachtbares Zeichen
GetThreadContext / SetThreadContext-AufrufeHochfrequente Kontextwechsel der Debug-Register bei anderen Prozessen/Threads (Kernel-ETW: Microsoft-Windows-Kernel-Process/Thread-APIs).
Von Null verschiedene DR0–DR3Jeder Thread, dessen CONTEXT_DEBUG_REGISTERS eine Benutzermodus-Adresse außerhalb bekannter Debugger-Workflows enthält.
DR7 lokale Aktivierungsbits (L0–L3) mit R/W = 00Nur-Ausführung-Breakpoints auf Threads, die nicht von einem Debugger verwaltet werden – eine starke Anomalie.
EXCEPTION_SINGLE_STEP-AufkommenHohe Raten von #DB-Ausnahmen (0x80000004), die aus dem VEH eines Prozesses stammen.
Erstchancen-VEH-RegistrierungKürzlich hinzugefügter VEH (AddVectoredExceptionHandler) kurz vor einem #DB-Sturm.
TH32CS_SNAPTHREAD + SuspendThread/ResumeThreadWiederholte Thread-Aufzählungs- und -Unterbrechungsmuster (vom 500-ms-Monitor verwendet).
Laden von wldp.dll/amsi.dll über LoadLibraryW, wenn diese nicht zuvor geladen warenAnomale Modulladungen im Zielprozess.
EtwEventWrite wird nie erreichtFehlen erwarteter ETW-Ereignisse (PowerShell-Operational-Logs bleiben stumm, während Skripte ausgeführt werden).