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
EDRSandblast-GodFault — EDRSandblast-GodFault | Kitploit
Tools/GitHubGitHub/gabriellandau/edrsandblast-godfault
DefensivwerkzeugePrivilege EscalationSpeicherforensikExploitationPost-ExploitationRed TeamingPayload-EntwicklungArchived
GitHubgabriellandau/edrsandblast-godfault

EDRSandblast-GodFault

EDRSandblast-GodFault

Repository anzeigen
27350vor 2 JahrenVon Kitploit geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

EDRSandblast-GodFault

Von Gabriel Landau bei Elastic Security. Modifikation von EDRSandblast - siehe ursprüngliche README unten.

Integriert GodFault in EDR Sandblast, um das gleiche Ergebnis ohne die Verwendung verwundbarer Treiber zu erzielen.

Beispielausgabe```

C:\Users\user\Desktop\Offsets>EDRSandblast.exe --kernelmode cmd


| | __ | __ \ / | | | | | | | | | | | | | | |) | ( __ _ _ __ | | | | | __ _ | | | | | | | | _ / _ \ / | '_ \ / _ | ' | |/ ` / __| __| | || || | | \ \ ) | (| | | | | (| | |) | | (| _ | | ||_____/|| _|/ _,|| ||_,|_./||_,|__/__|

D3FC0N 30 Edition | Thomas DIOT (@_Qazeer) & Maxime MEIGNAN (@th3m4ks)

[!] If kernel mode bypass is enabled, it is recommended to enable usermode bypass as well (e.g. to unhook the NtLoadDriver API call)

[===== KERNEL MODE =====]

[+] Setting up prerequisites for the kernel read/write primitives... [+] Loading kernel related offsets from the CSV file [*] System's ntoskrnl.exe file version is: ntoskrnl_22621-1702.exe [+] Offsets are available for this version of ntoskrnl.exe (ntoskrnl_22621-1702.exe)! [+] Checking if any EDR kernel notify rountines are set for image loading, process and thread creations... [+] [NotifyRountines] Enumerating process creation callbacks [+] Running command: GodFault.exe -t 2684 [?] Server does not appear to be running. Attempting to install it... [+] CSRSS PID is 748 [+] Testing initial ability to acquire PROCESS_ALL_ACCESS to System: Failure [+] Ready. Spawning WinTcb. [+] SpawnPPL: Waiting for child process to finish. [+] Thread 2684 (KTHREAD FFFF910961E4C080) has been blessed by GodFault [+] [NotifyRountines] fffff8034df25500 [cng.sys + 0x5500] [+] [NotifyRountines] fffff8034e9efdc0 [WdFilter.sys + 0x4fdc0] [+] [NotifyRountines] Found callback belonging to EDR driver WdFilter.sys [+] [NotifyRountines] fffff803487bc460 [ksecdd.sys + 0x1c460] [+] [NotifyRountines] fffff8034eff3fd0 [tcpip.sys + 0x13fd0] [+] [NotifyRountines] fffff8034f5ed980 [iorate.sys + 0xd980] [+] [NotifyRountines] fffff8034dea8890 [CI.dll + 0x88890] [+] [NotifyRountines] fffff803525079f0 [dxgkrnl.sys + 0x179f0] [+] [NotifyRountines] fffff80352be0a70 [vm3dmp.sys + 0x10a70] [+] [NotifyRountines] fffff8036ebccd00 [peauth.sys + 0x3cd00] [+] [NotifyRountines] fffff8036eda1550 [wtd.sys + 0x1550] [+] [NotifyRountines] Found a total of 1 EDR / security products driver(s) [+] [NotifyRountines] Enumerating thread creation callbacks [+] [NotifyRountines] fffff8034e9f15c0 [WdFilter.sys + 0x515c0] [+] [NotifyRountines] Found callback belonging to EDR driver WdFilter.sys [+] [NotifyRountines] fffff8034e9f1350 [WdFilter.sys + 0x51350] [+] [NotifyRountines] Found callback belonging to EDR driver WdFilter.sys [+] [NotifyRountines] fffff8036eb71010 [mmcss.sys + 0x1010] [+] [NotifyRountines] Found a total of 2 EDR / security products driver(s) [+] [NotifyRountines] Enumerating image loading callbacks [+] [NotifyRountines] fffff8034e9f0820 [WdFilter.sys + 0x50820] [+] [NotifyRountines] Found callback belonging to EDR driver WdFilter.sys [+] [NotifyRountines] fffff80352ab5710 [ahcache.sys + 0x25710] [+] [NotifyRountines] Found a total of 1 EDR / security products driver(s)

[+] Checking if EDR callbacks are registered on processes and threads handle creation/duplication... [+] [ObjectCallblacks] Enumerating Process object callbacks : [+] [ObjectCallblacks] Callback at FFFF800C5E2F2940 for handle creations & duplications: [+] [ObjectCallblacks] Status: Enabled [+] [ObjectCallblacks] Preoperation at 0xfffff8034e9eda30 [WdFilter.sys + 0x4da30] [+] [ObjectCallblacks] Callback belongs to an EDR and is enabled! [+] [ObjectCallblacks] Enumerating Thread object callbacks : [+] [ObjectCallblacks] Object callbacks are present !

[+] [ETWTI] Checking the ETW Threat Intelligence Provider state... [+] [ETWTI] ETW Threat Intelligence Provider is ENABLED!

[+] Process is NOT "safe" to launch our payload, removing monitoring and starting another process...

[+] [ETWTI] Disabling the ETW Threat Intel provider by patching ProviderEnableInfo at 0xffff91095ce8c430 with 0x00. [+] [ETWTI] The ETW Threat Intel provider was successfully disabled!

[+] Removing kernel callbacks registered by EDR for process creation, thread creation and image loading... [+] [NotifyRountines] Removing process creation callbacks [+] [NotifyRountines] Removing callback of EDR driver "WdFilter.sys" [callback addr: 0xfffff8034970c2a8 | callback struct: 0xffff91095dbf3a5f | callback function: 0xfffff8034e9efdc0] [+] [NotifyRountines] Removing thread creation callbacks [+] [NotifyRountines] Removing callback of EDR driver "WdFilter.sys" [callback addr: 0xfffff8034970c4a0 | callback struct: 0xffff91095dbf3b1f | callback function: 0xfffff8034e9f15c0] [+] [NotifyRountines] Removing callback of EDR driver "WdFilter.sys" [callback addr: 0xfffff8034970c4a8 | callback struct: 0xffff91095dbf3b4f | callback function: 0xfffff8034e9f1350] [+] [NotifyRountines] Removing image loading callbacks [+] [NotifyRountines] Removing callback of EDR driver "WdFilter.sys" [callback addr: 0xfffff8034970c6a0 | callback struct: 0xffff91095dbf3e4f | callback function: 0xfffff8034e9f0820]

[+] Disabling kernel callbacks registered by EDR for process and thread opening or handle duplication... [+] [ObjectCallblacks] Disabling WdFilter.sys callback...

[+] All EDR drivers were successfully removed from Kernel callbacks!

================================================== Starting a new unmonitored process...

[!] If kernel mode bypass is enabled, it is recommended to enable usermode bypass as well (e.g. to unhook the NtLoadDriver API call)

[===== KERNEL MODE =====]

[+] Setting up prerequisites for the kernel read/write primitives... [+] Loading kernel related offsets from the CSV file [*] System's ntoskrnl.exe file version is: ntoskrnl_22621-1702.exe [+] Offsets are available for this version of ntoskrnl.exe (ntoskrnl_22621-1702.exe)! [+] Checking if any EDR kernel notify rountines are set for image loading, process and thread creations... [+] [NotifyRountines] Enumerating process creation callbacks [+] Running command: GodFault.exe -t 8344 [+] Thread 8344 (KTHREAD FFFF91096169F080) has been blessed by GodFault [+] Initial blessing successful [+] [NotifyRountines] fffff8034df25500 [cng.sys + 0x5500] [+] [NotifyRountines] fffff803487bc460 [ksecdd.sys + 0x1c460] [+] [NotifyRountines] fffff8034eff3fd0 [tcpip.sys + 0x13fd0] [+] [NotifyRountines] fffff8034f5ed980 [iorate.sys + 0xd980] [+] [NotifyRountines] fffff8034dea8890 [CI.dll + 0x88890] [+] [NotifyRountines] fffff803525079f0 [dxgkrnl.sys + 0x179f0] [+] [NotifyRountines] fffff80352be0a70 [vm3dmp.sys + 0x10a70] [+] [NotifyRountines] fffff8036ebccd00 [peauth.sys + 0x3cd00] [+] [NotifyRountines] fffff8036eda1550 [wtd.sys + 0x1550] [+] [NotifyRountines] No EDR driver(s) found! [+] [NotifyRountines] Enumerating thread creation callbacks [+] [NotifyRountines] fffff8036eb71010 [mmcss.sys + 0x1010] [+] [NotifyRountines] No EDR driver(s) found! [+] [NotifyRountines] Enumerating image loading callbacks [+] [NotifyRountines] fffff80352ab5710 [ahcache.sys + 0x25710] [+] [NotifyRountines] No EDR driver(s) found!

[+] Checking if EDR callbacks are registered on processes and threads handle creation/duplication... [+] [ObjectCallblacks] Enumerating Process object callbacks : [+] [ObjectCallblacks] Callback at FFFF800C5E2F2940 for handle creations & duplications: [+] [ObjectCallblacks] Status: Disabled [+] [ObjectCallblacks] Preoperation at 0xfffff8034e9eda30 [WdFilter.sys + 0x4da30] [+] [ObjectCallblacks] Callback belongs to an EDR but is disabled. [+] [ObjectCallblacks] Enumerating Thread object callbacks : [+] [ObjectCallblacks] Object callbacks are not found !

[+] [ETWTI] Checking the ETW Threat Intelligence Provider state... [+] [ETWTI] ETW Threat Intelligence Provider is DISABLED!

[+] Process is "safe" to launch our payload

[+] Kernel callbacks have normally been removed, starting cmd.exe WARNING: EDR kernel callbacks will be restored after exiting the cmd prompt (by typing exit) WARNING: While unlikely, the longer the callbacks are removed, the higher the chance of being detected / causing a BSoD upon restore is!

Microsoft Windows [Version 10.0.22621.1702] (c) Microsoft Corporation. All rights reserved.

C:\Users\user\Desktop\Offsets>

root@kitploit:~
# EDRSandBlast

`EDRSandBlast` ist ein in `C` geschriebenes Tool, das einen verwundbaren signierten Treiber ausnutzt, um EDR-Erkennungen (Notify Routine Callbacks, Object Callbacks und `ETW TI` Provider) sowie `LSASS`-Schutzmechanismen zu umgehen. Es werden zudem mehrere Userland-Unhooking-Techniken implementiert, um die Überwachung im Benutzermodus zu umgehen.

Zum Zeitpunkt der Veröffentlichung wurde eine Kombination aus Userland- (`--usermode`) und Kernel-Land- (`--kernelmode`) Techniken verwendet, um den `LSASS`-Speicher unter EDR-Beobachtung auszulesen, ohne blockiert zu werden oder Ereignisse im Zusammenhang mit "OS Credential Dumping" in der Produkt-(Cloud-)Konsole zu erzeugen. Die Tests wurden mit 3 verschiedenen EDR-Produkten durchgeführt und waren in jedem Fall erfolgreich.

## Beschreibung

### EDR Bypass durch Entfernung von Kernel Notify Routines

EDR-Produkte verwenden Kernel-"Notify Routines"-Callbacks unter Windows, um vom Kernel über Systemaktivitäten wie Prozess- und Thread-Erstellung sowie das Laden von Images (`exe` / `DLL`) benachrichtigt zu werden.

Diese Kernel-Callbacks werden aus dem Kernel-Modus definiert, normalerweise vom Treiber, der die Callbacks implementiert, unter Verwendung einer Reihe dokumentierter APIs (`nt!PsSetCreateProcessNotifyRoutine`, `nt!PsSetCreateThreadNotifyRoutine`, usw.). Diese APIs fügen treiberbereitgestellte Callback-Routinen zu undokumentierten Arrays von Routinen im Kernel-Space hinzu:
  - `PspCreateProcessNotifyRoutine` für Prozesserstellung
  - `PspCreateThreadNotifyRoutine` für Thread-Erstellung
  - `PspLoadImageNotifyRoutine` für Image-Laden

`EDRSandBlast` zählt die in diesen Arrays definierten Routinen auf und entfernt alle Callback-Routinen, die mit einer vordefinierten Liste von EDR-Treibern verknüpft sind (mehr als 1000 Treiber von Sicherheitsprodukten werden unterstützt, siehe den [Abschnitt zur EDR-Treibererkennung](#edr-drivers-and-processes-detection)). Die Aufzählung und Entfernung werden durch die Ausnutzung einer willkürlichen Kernel-Speicher-Lese-/Schreib-Primitive ermöglicht, die durch die Ausnutzung eines anfälligen Treibers bereitgestellt wird (siehe [Abschnitt „Verwundbare Treiber“](#vulnerable-drivers-detection)).

Die Offsets der zuvor genannten Arrays werden mit mehreren Techniken wiederhergestellt, bitte beachten Sie den [Abschnitt „Offsets“](#ntoskrnl-and-wdigest-offsets).

### EDR Bypass durch Entfernung von Object Callbacks

EDR- (und sogar EPP-)Produkte registrieren oft "Object callbacks" mithilfe der Kernel-API `nt!ObRegisterCallbacks`. Diese Callbacks ermöglichen es dem Sicherheitsprodukt, bei jeder Handle-Erstellung zu bestimmten Objekttypen (Prozess-, Thread- und Desktop-bezogene Object Callbacks werden jetzt von Windows unterstützt) benachrichtigt zu werden. Eine Handle-Erstellung kann beim Öffnen eines Objekts (Aufruf von `OpenProcess`, `OpenThread`, usw.) sowie beim Duplizieren von Handles (Aufruf von `DuplicateHandle`, usw.) erfolgen.

Indem es vom Kernel bei jeder dieser Operationen benachrichtigt wird, kann ein Sicherheitsprodukt die Legitimität der Handle-Erstellung analysieren (*z. B. ein unbekannter Prozess versucht, LSASS zu öffnen*), und sie sogar blockieren, wenn eine Bedrohung erkannt wird.

Bei jeder Callback-Registrierung mit `ObRegisterCallbacks` wird ein neues Element zur doppelt verknüpften Liste `CallbackList` im `_OBJECT_TYPE`-Objekt hinzugefügt, das den vom Callback betroffenen Objekttyp beschreibt (entweder einen Prozess, einen Thread oder einen Desktop). Leider werden diese Elemente durch eine Struktur beschrieben, die von Microsoft weder dokumentiert noch in Symboldateien veröffentlicht wird. Die Untersuchung verschiedener `ntoskrnl.exe`-Versionen scheint jedoch darauf hinzudeuten, dass sich die Struktur zwischen (mindestens) Windows 10 Builds 10240 und 22000 (von 2015 bis 2022) nicht geändert hat.

Die erwähnte Struktur, die eine Objekt-Callback-Registrierung darstellt, ist die folgende:```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;

Die oben erwähnte OB_CALLBACK-Struktur ist ebenfalls undokumentiert und wird wie folgt definiert:```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;

root@kitploit:~
Um von EDR registrierte Objekt-Callbacks zu deaktivieren, sind in `EDRSandblast` drei Techniken implementiert; derzeit ist jedoch nur eine aktiviert.

#### Verwendung des `Enabled`-Felds von `OB_CALLBACK_ENTRY`
Dies ist die standardmäßig in `EDRSandblast` aktivierte Technik. Um EDR-bezogene Objekt-Callbacks zu erkennen und zu deaktivieren, wird die Liste `CallbackList` in den `_OBJECT_TYPE`-Objekten durchsucht, die mit den Typen *Process* und *Thread* verbunden sind. Beide `_OBJECT_TYPE`s werden durch öffentliche globale Symbole im Kernel, `PsProcessType` und `PsThreadType`, referenziert.

Es wird angenommen, dass jedes Element der Liste der oben beschriebenen `OB_CALLBACK_ENTRY`-Struktur entspricht (eine Annahme, die zum Zeitpunkt der Erstellung zumindest in allen Windows 10-Builds zu gelten scheint). Funktionen, die in den Feldern `PreOperation` und `PostOperation` definiert sind, werden lokalisiert, um zu überprüfen, ob sie zu einem EDR-Treiber gehören. Wenn ja, werden die Callbacks einfach durch Umschalten des `Enabled`-Flags deaktiviert.

Obwohl dies eine ziemlich sichere Technik ist, hat sie den Nachteil, dass sie auf einer undokumentierten Struktur basiert. Um das Risiko einer unsicheren Manipulation dieser Struktur zu verringern, werden grundlegende Prüfungen durchgeführt, um zu validieren, dass einige Felder die erwarteten Werte haben:
* `Enabled` ist entweder `TRUE` oder `FALSE` (*lachen Sie nicht, ein `BOOL` ist ein `int`, also könnte es alles andere als `1` oder `0` sein*);
* `Operations` ist `OB_OPERATION_HANDLE_CREATE`,  `OB_OPERATION_HANDLE_DUPLICATE` oder beides;
* `ObjectType` zeigt auf `PsProcessType` oder `PsThreadType`.

#### Entfernen der `CallbackList` von Threads und Prozessen
Eine weitere Strategie, die nicht auf einer undokumentierten Struktur basiert (und daher theoretisch robuster gegenüber Änderungen am NT-Kernel ist), ist das Entfernen der gesamten `CallbackList` sowohl für Prozesse als auch für Threads. Das `_OBJECT_TYPE`-Objekt ist wie folgt:```C
struct _OBJECT_TYPE {
	LIST_ENTRY TypeList;
	UNICODE_STRING Name;
	[...]
	_OBJECT_TYPE_INITIALIZER TypeInfo;
	[...]
	LIST_ENTRY CallbackList;
}

Das Setzen der Flink- und Blink-Zeiger der CallbackList LIST_ENTRY auf die LIST_ENTRY selbst macht die Liste effektiv leer. Da die _OBJECT_TYPE-Struktur in den Kernel-Symbolen veröffentlicht ist, basiert die Technik nicht auf hartcodierten Offsets/Strukturen. Sie hat jedoch einige Nachteile.

Der erste Nachteil ist, dass nicht nur die Callbacks von EDR deaktiviert werden können; die Technik betrifft tatsächlich alle Objekt-Callbacks, die von „legitimer“ Software registriert worden sein könnten. Es sollte jedoch angemerkt werden, dass Objekt-Callbacks von keiner vorinstallierten Komponente unter Windows 10 (zum Zeitpunkt des Schreibens) verwendet werden, sodass deren Deaktivierung die Maschinenstabilität nicht beeinträchtigen sollte (umso mehr, wenn die Deaktivierung nur vorübergehend ist).

Der zweite Nachteil besteht darin, dass Prozess- oder Thread-Handle-Operationen im normalen Betrieb des Betriebssystems sehr häufig (fast kontinuierlich) sind. Wenn die verwendete Kernel-Schreibprimitive keinen QWORD-Schreibvorgang „atomar“ durchführen kann, besteht eine hohe Wahrscheinlichkeit, dass der _OBJECT_TYPE.CallbackList.Flink-Zeiger vom Kernel mitten in seiner Überschreibung zugegriffen wird. Beispielsweise kann der anfällige MSI-Treiber RTCore64.sys jeweils nur einen DWORD-Schreibvorgang durchführen, sodass zwei verschiedene IOCTLs benötigt werden, um den Zeiger zu überschreiben. Dazwischen besteht eine hohe Wahrscheinlichkeit, dass der Kernel ihn verwendet (was zu einem Absturz führt). Andererseits kann der anfällige DELL-Treiber DBUtil_2_3.sys Schreibvorgänge beliebiger Größe in einem IOCTL durchführen, sodass die Verwendung dieser Methode mit ihm kein Absturzrisiko birgt.

Deaktivieren von Objekt-Callbacks insgesamt

Eine letzte Technik, die wir gefunden haben, besteht darin, die Unterstützung für Objekt-Callbacks für Threads und Prozesse vollständig zu deaktivieren. Innerhalb der _OBJECT_TYPE-Struktur, die den Prozess- und Thread-Typen entspricht, befindet sich ein TypeInfo-Feld, das der dokumentierten _OBJECT_TYPE_INITIALIZER-Struktur folgt. Letztere enthält ein Bitfeld ObjectTypeFlags, dessen Flag SupportsObjectCallbacks bestimmt, ob der beschriebene Objekttyp (Prozess, Thread, Desktop, Token, Datei usw.) die Registrierung von Objekt-Callbacks unterstützt oder nicht. Wie bereits erwähnt, unterstützen nur die Objekttypen Prozess, Thread und Desktop diese Callbacks unter einer Windows-Installation zum Zeitpunkt des Schreibens.

Da das SupportsObjectCallbacks-Bit von ObpCreateHandle oder ObDuplicateObject überprüft wird, bevor überhaupt die CallbackList gelesen wird (und natürlich bevor Callbacks ausgeführt werden), deaktiviert das Umschalten des Bits zur Kernel-Laufzeit effektiv die Ausführung aller Objekt-Callbacks.

Der Hauptnachteil der Methode ist einfach, dass KPP ("PatchGuard") die Integrität einiger (aller?) _OBJECT_TYPE-Strukturen überwacht und einen 0x109 Bug Check auslöst, wobei Parameter 4 gleich 0x8 ist, was bedeutet, dass eine Objekttyp-Struktur geändert wurde.

Wenn man die Deaktivierung / Wiederaktivierung (und die „böswillige“ Aktion dazwischen) jedoch schnell genug durchführt, sollte das ausreichen, um PatchGuard zu „überholen“ (es sei denn, man hat Pech und eine periodische Überprüfung erfolgt genau im falschen Moment).

EDR-Umgehung durch Deaktivierung des ETW-Anbieters Microsoft-Windows-Threat-Intelligence

Der ETW Microsoft-Windows-Threat-Intelligence-Anbieter protokolliert Daten über die Nutzung einiger Windows-APIs, die häufig böswillig verwendet werden. Dazu gehört die nt!MiReadWriteVirtualMemory-API, die von nt!NtReadVirtualMemory aufgerufen wird (zum Auslesen des LSASS-Speichers verwendet) und von der Funktion nt!EtwTiLogReadWriteVm überwacht wird.

EDR-Produkte können die vom ETW TI-Anbieter erzeugten Protokolle über Dienste oder Prozesse verbrauchen, die als SERVICE_LAUNCH_PROTECTED_ANTIMALWARE_LIGHT bzw. PS_PROTECTED_ANTIMALWARE_LIGHT ausgeführt werden und mit einem Early Launch Anti Malware (ELAM)-Treiber verknüpft sind.

Wie von slaeryan in einem Blogbeitrag der CNO Development Labs veröffentlicht, kann der ETW TI-Anbieter vollständig deaktiviert werden, indem man im Kernel-Speicher sein ProviderEnableInfo-Attribut auf 0x0 setzt. Für weitere Informationen zur Technik sei auf den großartigen, zuvor genannten Blogbeitrag verwiesen.

Ähnlich wie bei der Entfernung von Kernel-Callbacks werden die notwendigen ntoskrnl.exe-Offsets (nt!EtwThreatIntProvRegHandleOffset, _ETW_REG_ENTRY's GuidEntry und _ETW_GUID_ENTRY's ProviderEnableInfo) in der Datei NtoskrnlOffsets.csv für eine Reihe von Windows-Kernel-Versionen berechnet.

EDR-Umgehung durch Umgehung von Userland-Hooking

Wie Userland-Hooking funktioniert

Um Aktionen, die von Prozessen durchgeführt werden, einfach zu überwachen, setzen EDR-Produkte häufig einen Mechanismus namens Userland-Hooking ein. Zunächst registrieren EDR-Produkte einen Kernel-Callback (normalerweise Image Loading oder Process Creation-Callbacks, siehe oben), der es ihnen ermöglicht, bei jedem Prozessstart benachrichtigt zu werden.

Wenn ein Prozess von Windows geladen wird und bevor er tatsächlich startet, kann das EDR eine benutzerdefinierte DLL in den Adressraum des Prozesses injizieren, die seine Überwachungslogik enthält. Während des Ladens injiziert diese DLL "Hooks" am Anfang jeder Funktion, die vom EDR überwacht werden soll. Zur Laufzeit, wenn die überwachten Funktionen von dem überwachten Prozess aufgerufen werden, leiten diese Hooks den Kontrollfluss zu einem Überwachungscode um, der in der EDR-DLL vorhanden ist, und ermöglichen es, Argumente und Rückgabewerte dieser Aufrufe zu inspizieren.

Meistens handelt es sich bei den überwachten Funktionen um Systemaufrufe (wie NtReadVirtualMemory, NtOpenProcess usw.), deren Implementierungen in ntdll.dll liegen. Das Abfangen von Aufrufen von Nt*-Funktionen ermöglicht es Produkten, so nah wie möglich an der Benutzermodus/Kernel-Modus-Grenze zu sein (während sie im Benutzermodus bleiben), aber auch Funktionen aus einigen DLLs höherer Ebene können überwacht werden.

Unten sind Beispiele derselben Funktion, vor und nach dem Hooking durch das EDR-Produkt:```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

root@kitploit:~
EINGABE:```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			

Hook-Erkennung

Userland-Hooks haben die "Schwäche", sich im Userspace-Speicher zu befinden, was bedeutet, dass sie vom untersuchten Prozess direkt beobachtet und modifiziert werden können. Um Hooks im Adressraum des Prozesses automatisch zu erkennen, besteht die Grundidee darin, die Unterschiede zwischen der ursprünglichen DLL auf der Festplatte und der im Speicher befindlichen Bibliothek zu vergleichen, die möglicherweise von einem EDR verändert wurde. Um diesen Vergleich durchzuführen, führt EDRSandblast die folgenden Schritte aus:

  • Die Liste aller geladenen DLLs wird mithilfe der InLoadOrderModuleList im PEB aufgezählt (um den Aufruf einer API zu vermeiden, die überwacht und verdächtig sein könnte)
  • Für jede geladene DLL wird ihr Inhalt auf der Festplatte gelesen und ihre Header werden geparst. Die entsprechende Bibliothek, die sich im Speicher befindet, wird ebenfalls geparst, um Abschnitte, Exporte usw. zu identifizieren.
  • Die Relocation-Einträge der DLL werden unter Berücksichtigung der Basisadresse der entsprechenden geladenen Bibliothek geparst und angewendet. Dadurch haben der Inhalt der Bibliothek im Speicher und der ursprünglichen DLL von der Festplatte auf den Abschnitten, auf die Relocation angewendet werden, exakt den gleichen Inhalt, was den Vergleich zuverlässig macht.
  • Exportierte Funktionen werden aufgezählt und die ersten Bytes der "im Speicher" und "auf der Festplatte" befindlichen Versionen werden verglichen. Jeder Unterschied weist auf eine Änderung hin, die nach dem Laden der DLL vorgenommen wurde, und handelt es sich daher sehr wahrscheinlich um einen EDR-Hook.

Hinweis: Der Vorgang kann verallgemeinert werden, um Unterschiede überall in nicht beschreibbaren Abschnitten zu finden, nicht nur am Anfang exportierter Funktionen, falls EDR-Produkte beispielsweise damit beginnen, Hooks in der Mitte einer Funktion anzubringen :) Daher wird dieser vom Tool nicht verwendet, wurde aber in findDiffsInNonWritableSections implementiert.

Um die von diesen Hooks durchgeführte Überwachung zu umgehen, sind mehrere Techniken möglich, und jede hat Vor- und Nachteile.

Hook-Umgehung durch ... Unhooking

Die intuitivste Methode, um die hook-basierte Überwachung zu umgehen, besteht darin, die Hooks zu entfernen. Da sich die Hooks im Speicher befinden, der vom Prozess selbst erreichbar ist, kann der Prozess zum Entfernen eines Hooks einfach:

  • Die Berechtigungen der Seite ändern, auf der sich der Hook befindet (RX -> RWX oder RW)
  • Die ursprünglichen Bytes schreiben, die dank des Inhalts der DLL auf der Festplatte bekannt sind
  • Die Berechtigungen wieder auf RX ändern

Dieser Ansatz ist recht einfach und kann verwendet werden, um alle erkannten Hooks auf einmal zu entfernen. Wenn er von einem Offensive-Tool zu Beginn ausgeführt wird, ermöglicht dies dem restlichen Code, den Hooking-Mechanismus völlig zu ignorieren und normal zu funktionieren, ohne überwacht zu werden.

Sie hat jedoch zwei Hauptnachteile. Der EDR überwacht wahrscheinlich die Verwendung von NtProtectVirtualMemory, daher ist es (zumindest konzeptionell) eine schlechte Idee, es zu verwenden, um die Berechtigungen der Seite zu ändern, auf der die Hooks installiert wurden. Wenn außerdem ein Thread vom EDR ausgeführt wird und periodisch die Integrität der Hooks überprüft, könnte dies ebenfalls eine Erkennung auslösen.

Implementierungsdetails finden Sie im Codepfad der Funktion unhook(), wenn unhook_method den Wert UNHOOK_WITH_NTPROTECTVIRTUALMEMORY hat.

Wichtiger Hinweis: Der Einfachheit halber ist diese Technik in EDRSandblast als Basistechnik implementiert, die verwendet wird, um die anderen Umgehungstechniken zu demonstrieren; jede von ihnen zeigt, wie man eine unüberwachte Version von NtProtectVirtualMemory erhält, führt aber danach die gleiche Operation aus (Entfernen eines bestimmten Hooks).

Hook-Umgehung mittels eines benutzerdefinierten Trampolins

Um einen bestimmten Hook zu umgehen, ist es möglich, einfach "darüber zu springen" und den Rest der Funktion wie gehabt auszuführen. Zuerst müssen die ursprünglichen Bytes der überwachten Funktion, die vom EDR zum Installieren des Hooks überschrieben wurden, aus der DLL-Datei wiederhergestellt werden. In unserem vorherigen Codebeispiel wären dies die Bytes, die den folgenden Anweisungen entsprechen:```assembly mov r10, rcx mov eax, 50h

root@kitploit:~
Das Identifizieren dieser Bytes ist eine einfache Aufgabe, da wir einen sauberen *Diff* zwischen der Speicher- und der Festplattenversion der Bibliothek durchführen können, wie zuvor beschrieben. Dann setzen wir eine Sprunganweisung zusammen, die den Kontrollfluss sofort auf den Code nach dem Hook an der Adresse `NtProtectVirtualMemory + sizeof(overwritten_instructions)` umleitet.```assembly
jmp NtProtectVirtualMemory+8

Schließlich verketten wir diese Opcodes, speichern sie im (neu) ausführbaren Speicher und behalten einen Zeiger darauf. Dieses Objekt wird als "Trampolin" bezeichnet und kann dann als Funktionszeiger verwendet werden, der streng äquivalent zur ursprünglichen NtProtectVirtualMemory-Funktion ist.

Der Hauptvorteil dieser Technik, wie bei allen nachfolgenden Techniken, ist, dass der Hook nie gelöscht wird, sodass alle Integritätsprüfungen, die vom EDR an den Hooks durchgeführt werden, bestehen sollten. Allerdings erfordert es, zuerst beschreibbaren und dann ausführbaren Speicher zu allozieren, was typisch für eine Shellcode-Allokation ist und somit die Aufmerksamkeit des EDR auf sich zieht.

Einzelheiten zur Implementierung finden Sie im Codepfad der Funktion unhook(), wenn unhook_method auf UNHOOK_WITH_INHOUSE_NTPROTECTVIRTUALMEMORY_TRAMPOLINE gesetzt ist. Bitte beachten Sie, dass die Technik nur in unserer Implementierung gezeigt wird und letztendlich dazu dient, Hooks aus dem Speicher zu entfernen, wie jede nachfolgende Technik.

Hook-Umgehung mit dem eigenen EDR-Trampolin

Das EDR-Produkt muss, damit sein Hook funktioniert, irgendwo im Speicher die Opcodes speichern, die es entfernt hat. Schlimmstenfalls (oder „besser“, aus Sicht des Angreifers) hat das EDR sich selbst wahrscheinlich ein Trampolin irgendwo alloziert, um die ursprüngliche Funktion auszuführen, nachdem es den Aufruf abgefangen hat.

Dieses Trampolin kann gesucht und als Ersatz für die gehookedte Funktion verwendet werden, ohne dass ausführbarer Speicher allokiert oder eine andere API außer VirtualQuery aufgerufen werden muss, die höchstwahrscheinlich nicht überwacht wird, da sie eine harmlose Funktion ist.

Um das Trampolin im Speicher zu finden, durchsuchen wir den gesamten Adressraum mit VirtualQuery nach committetem und ausführbarem Speicher. Für jede solche Speicherregion scannen wir sie nach einer Sprunganweisung, die auf die Adresse nach den überschriebenen Anweisungen abzielt (NtProtectVirtualMemory+8 in unserem vorherigen Beispiel). Das Trampolin kann dann verwendet werden, um die gehookedte Funktion aufzurufen, ohne den Hook auszulösen.

Diese Technik funktioniert überraschend gut, da sie nahezu alle Trampoline auf getesteten EDRs wiederherstellt. Einzelheiten zur Implementierung finden Sie im Codepfad der Funktion unhook(), wenn unhook_method auf UNHOOK_WITH_EDR_NTPROTECTVIRTUALMEMORY_TRAMPOLINE gesetzt ist.

Hook-Umgehung mit duplizierter DLL

Eine weitere einfache Methode, um Zugriff auf eine nicht überwachte Version der NtProtectVirtualMemory-Funktion zu erhalten, besteht darin, eine duplizierte Version der Bibliothek ntdll.dll in den Prozessadressraum zu laden. Da zwei identische DLLs im selben Prozess geladen werden können, sofern sie unterschiedliche Namen haben, können wir einfach die legitime ntdll.dll-Datei an einen anderen Ort kopieren, sie mit LoadLibrary laden (oder den Ladevorgang neu implementieren) und die Funktion beispielsweise mit GetProcAddress aufrufen.

Diese Technik ist sehr einfach zu verstehen und zu implementieren und hat eine anständige Erfolgschance, da die meisten EDR-Produkte keine Hooks auf neu geladene DLLs erneut installieren, sobald der Prozess läuft. Der größte Nachteil ist jedoch, dass das Kopieren von Microsoft-signierten Binärdateien unter einem anderen Namen oft als verdächtig angesehen wird, und zwar von EDR-Produkten selbst.

Diese Technik ist dennoch in EDRSandblast implementiert. Einzelheiten zur Implementierung finden Sie im Codepfad der Funktion unhook(), wenn unhook_method auf UNHOOK_WITH_DUPLICATE_NTPROTECTVIRTUALMEMORY gesetzt ist.

Hook-Umgehung mit direkten Syscalls

Um systemaufruffbezogene Funktionen zu nutzen, kann ein Programm Syscalls (in Assembler) neu implementieren, um die entsprechenden Betriebssystemfunktionen aufzurufen, ohne den Code in ntdll.dll zu berühren, der vom EDR überwacht werden könnte. Dies umgeht vollständig jegliches Userland-Hooking, das bei Syscall-Funktionen in ntdll.dll durchgeführt wurde.

Dies hat dennoch einige Nachteile. Erstens setzt dies voraus, dass man die Liste der Syscall-Nummern der benötigten Funktionen kennt, die sich mit jeder Windows-Version ändert. Dies wird jedoch durch die Implementierung mehrerer Heuristiken abgemildert, die bekanntermaßen in allen vergangenen Windows NT-Versionen funktionieren (Sortieren der Zw*-Exporte von ntdll, Suchen nach der mov rax, #syscall_number-Anweisung in der zugehörigen ntdll-Funktion usw.) und Überprüfen, ob alle das gleiche Ergebnis liefern (siehe Syscalls.c für weitere Details).

Auch Funktionen, die technisch gesehen keine Syscalls sind (z. B. LoadLibraryX/LdrLoadDLL), könnten ebenfalls überwacht werden und können nicht einfach mit einem Syscall neu implementiert werden.

Die direkte Syscalls-Technik ist in EDRSandblast implementiert. Wie bereits erwähnt, wird sie nur verwendet, um NtProtectVirtualMemory sicher auszuführen und alle erkannten Hooks zu entfernen.

Einzelheiten zur Implementierung finden Sie im Codepfad der Funktion unhook(), wenn unhook_method auf UNHOOK_WITH_DIRECT_SYSCALL gesetzt ist.

Exploitierung anfälliger Treiber

Wie bereits erwähnt, basiert jede Aktion, die einen Kernel-Speicher-Lese- oder Schreibzugriff erfordert, auf einem anfälligen Treiber, um diese Primitive bereitzustellen. In EDRSandblast kann die Unterstützung für einen neuen Treiber, der die Lese-/Schreibprimitive bereitstellt, „einfach“ hinzugefügt werden; es müssen nur drei Funktionen implementiert werden:

  • Eine Funktion ReadMemoryPrimitive_DRIVERNAME(SIZE_T Size, DWORD64 Address, PVOID Buffer), die Size Bytes von der Kernel-Adresse Address in den Userland-Puffer Buffer kopiert;
  • Eine Funktion WriteMemoryPrimitive_DRIVERNAME(SIZE_T Size, DWORD64 Address, PVOID Buffer), die Size Bytes vom Userland-Puffer Buffer zur Kernel-Adresse Address kopiert;
  • Eine Funktion CloseDriverHandle_DRIVERNAME(), die sicherstellt, dass alle Handles zum Treiber geschlossen sind (erforderlich vor der Deinstallationsoperation, die derzeit treiberunabhängig ist).

Als Beispiel werden derzeit zwei Treiber von EDRSandblast unterstützt: RTCore64.sys (SHA256: 01AA278B07B58DC46C84BD0B1B5C8E9EE4E62EA0BF7A695862444AF32E87F1FD) und DBUtils_2_3.sys (SHA256: 0296e2ce999e67c76352613a718e11516fe1b0efc3ffdb8918fc999dd76a73a5). Der folgende Code in KernelMemoryPrimitives.h muss aktualisiert werden, wenn der verwendete anfällige Treiber geändert oder ein neuer implementiert wird.```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

root@kitploit:~
### Erkennung von EDR-Treibern und -Prozessen
Derzeit werden mehrere Techniken verwendet, um festzustellen, ob ein bestimmter Treiber oder Prozess zu einem EDR-Produkt gehört oder nicht.

Zunächst kann einfach der Name des Treibers zu diesem Zweck verwendet werden. Tatsächlich vergibt Microsoft spezifische Nummern, sogenannte "Altitudes", für alle Treiber, die Callbacks im Kernel registrieren müssen. Dadurch wird eine deterministische Reihenfolge bei der Ausführung von Callbacks ermöglicht, unabhängig von der Registrierungsreihenfolge, sondern nur basierend auf der Treibernutzung. Eine Liste der (Anbieter von) Treibern, die eine bestimmte *altitude* reserviert haben, findet sich [auf MSDN](https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/allocated-altitudes). Infolgedessen wird von Microsoft eine nahezu vollständige Liste von Sicherheitstreibernamen, die mit Sicherheitsprodukten verbunden sind, bereitgestellt, hauptsächlich in den Listen "FSFilter Anti-Virus" und "FSFilter Activity Monitor". Diese Listen von Treibernamen sind in EDRSandblast sowie zusätzliche Beiträge eingebettet.

Darüber hinaus sind EDR-Executables und DLLs mehr als oft digital mit dem Signaturzertifikat des Anbieters signiert. Daher kann die Überprüfung des Signierers eines einer zugehörigen ausführbaren Datei oder DLL eines Prozesses eine schnelle Identifizierung von EDR-Produkten ermöglichen.

Außerdem müssen Treiber direkt von Microsoft signiert sein, um im Kernelspace geladen werden zu dürfen. Während der Treiberanbieter nicht direkt der Signierer des Treibers selbst ist, scheint es, dass der Name des Anbieters dennoch in einem Attribut der Signatur enthalten ist; diese Erkennungstechnik muss jedoch noch untersucht und implementiert werden.

Schließlich, wenn man einem EDR gegenübersteht, der EDRSandblast unbekannt ist, ist der beste Ansatz, das Tool im "Audit"-Modus auszuführen und die Liste der Treiber zu überprüfen, die Kernel-Callbacks registriert haben; dann kann der Treibername zur Liste hinzugefügt, das Tool neu kompiliert und erneut ausgeführt werden.

### RunAsPPL-Bypass

Der `Local Security Authority (LSA) Protection`-Mechanismus, der erstmals in Windows 8.1 und Windows Server 2012 R2 eingeführt wurde, nutzt die `Protected Process Light (PPL)`-Technologie, um den Zugriff auf den `LSASS`-Prozess einzuschränken. Der `PPL`-Schutz reguliert und beschränkt Operationen wie Speicherinjektion oder Speicher-Dumping von geschützten Prozessen, selbst von einem Prozess, der das `SeDebugPrivilege`-Privileg besitzt. Unter dem Prozessschutzmodell können nur Prozesse mit höheren Schutzstufen Operationen an geschützten Prozessen durchführen.

Die `_EPROCESS`-Struktur, die vom Windows-Kernel verwendet wird, um einen Prozess im Kernel-Speicher darzustellen, enthält ein `_PS_PROTECTION`-Feld, das die Schutzstufe eines Prozesses durch seine Attribute `Type` (`_PS_PROTECTED_TYPE`) und `Signer` (`_PS_PROTECTED_SIGNER`) definiert.

Durch Schreiben in den Kernel-Speicher kann der EDRSandblast-Prozess seine eigene Schutzstufe auf `PsProtectedSignerWinTcb-Light` erhöhen. Diese Stufe reicht aus, um den Speicher des `LSASS`-Prozesses zu dumpen, da sie über `PsProtectedSignerLsa-Light` "dominiert", der Schutzstufe des `LSASS`-Prozesses, der mit dem `RunAsPPL`-Mechanismus läuft.

`EDRSandBlast` implementiert den Selbstschutz wie folgt:
  - Öffnen eines Handles auf den aktuellen Prozess
  - Leaken aller System-Handles mithilfe von `NtQuerySystemInformation`, um das geöffnete Handle auf den aktuellen Prozess sowie die Adresse der `EPROCESS`-Struktur des aktuellen Prozesses im Kernel-Speicher zu finden.
  - Nutzung der beliebigen Lese-/Schreib-Schwachstelle des `Micro-Star MSI Afterburner`-Treibers, um das `_PS_PROTECTION`-Feld des aktuellen Prozesses im Kernel-Speicher zu überschreiben. Die Offsets des `_PS_PROTECTION`-Feldes relativ zur `EPROCESS`-Struktur (definiert durch die verwendete `ntoskrnl`-Version) werden in der `NtoskrnlOffsets.csv`-Datei berechnet.

### Credential Guard-Bypass

Microsoft `Credential Guard` ist eine virtualisierungsbasierte Isolationstechnologie, die in Microsofts `Windows 10 (Enterprise Edition)` eingeführt wurde und den direkten Zugriff auf die im `LSASS`-Prozess gespeicherten Anmeldeinformationen verhindert.

Wenn `Credentials Guard` aktiviert ist, wird ein `LSAIso`-Prozess (*LSA Isolated*) im `Virtual Secure Mode` erstellt, einer Funktion, die die Virtualisierungserweiterungen der CPU nutzt, um zusätzliche Sicherheit der Daten im Speicher zu bieten. Der Zugriff auf den `LSAIso`-Prozess ist selbst für einen Zugriff mit dem Sicherheitskontext `NT AUTHORITY\SYSTEM` eingeschränkt. Bei der Verarbeitung eines Hashes führt der `LSA`-Prozess einen `RPC`-Aufruf an den `LSAIso`-Prozess durch und wartet auf das Ergebnis des `LSAIso`-Prozesses, um fortzufahren. Daher enthält der `LSASS`-Prozess keine Geheimnisse und speichert stattdessen `LSA Isolated Data`.

Wie in der ursprünglichen Forschung von `N4kedTurtle` festgestellt: "`Wdigest` kann auf einem System mit Credential Guard aktiviert werden, indem die Werte von `g_fParameter_useLogonCredential` und `g_IsCredGuardEnabled` im Speicher gepatcht werden". Die Aktivierung von `Wdigest` führt dazu, dass Klartext-Anmeldeinformationen für alle neuen interaktiven Anmeldungen im `LSASS`-Speicher gespeichert werden (ohne dass ein Neustart des Systems erforderlich ist). Weitere Einzelheiten zu dieser Technik finden Sie im [ursprünglichen Forschungsblogbeitrag](https://teamhydra.blog/2020/08/25/bypassing-credential-guard/).

`EDRSandBlast` macht den ursprünglichen PoC einfach etwas opsec-freundlicher und bietet Unterstützung für eine Reihe von `wdigest.dll`-Versionen (durch berechnete Offsets für `g_fParameter_useLogonCredential` und `g_IsCredGuardEnabled`).

### Offsets abrufen
Um zuverlässig Kernel-Überwachungs-Bypass-Operationen durchführen zu können, muss EDRSandblast genau wissen, wo im Kernel-Speicher gelesen und geschrieben werden muss. Dies erfolgt mithilfe von Offsets globaler Variablen innerhalb des Zielimages (ntoskrnl.exe, wdigest.dll) sowie Offsets spezifischer Felder in Strukturen, deren Definitionen von Microsoft in Symboldateien veröffentlicht werden. Diese Offsets sind für jeden Build der Zielimages spezifisch und müssen mindestens einmal für eine bestimmte Plattformversion erfasst werden.

Die Entscheidung, "hartcodierte" Offsets anstelle von Mustersuchen zu verwenden, um die von EDRSandblast verwendeten Strukturen und Variablen zu lokalisieren, ist dadurch gerechtfertigt, dass die undokumentierten APIs, die für das Hinzufügen/Entfernen von Kernel-Callbacks verantwortlich sind, Änderungen unterliegen und jeder Versuch, Kernel-Speicher an der falschen Adresse zu lesen oder zu schreiben, zu einem `Bug Check` (`Blue Screen of Death`) führen kann (und oft führen wird). Ein Maschinenabsturz ist sowohl in Red-Teaming- als auch in normalen Penetrationstestszenarien nicht akzeptabel, da eine abstürzende Maschine für Verteidiger sehr sichtbar ist und alle Anmeldeinformationen verliert, die zum Zeitpunkt des Angriffs noch im Speicher waren.

Um Offsets für jede spezifische Windows-Version abzurufen, werden zwei Ansätze implementiert.

#### Manuelles Abrufen von Offsets
Die erforderlichen Offsets von `ntoskrnl.exe` und `wdigest.dll` können mit dem bereitgestellten Python-Skript `ExtractOffsets.py` extrahiert werden, das auf `radare2` und `r2pipe` zurückgreift, um Symbole aus PDB-Dateien herunterzuladen und zu parsen, und die benötigten Offsets daraus extrahiert. Die Offsets werden dann in CSV-Dateien für die spätere Verwendung durch EDRSandblast gespeichert.

Um eine breite Palette von Windows-Builds sofort zu unterstützen, werden viele Versionen der Binärdateien `ntoskrnl.exe` und `wdigest.dll` von [Winbindex](https://winbindex.m417z.com/) referenziert und können automatisch heruntergeladen (und ihre Offsets extrahiert) werden vom `ExtractOffsets.py`. Dies ermöglicht die Extraktion von Offsets aus nahezu allen Dateien, die jemals in Windows-Update-Paketen veröffentlicht wurden (bisher sind 450+ `ntoskrnl.exe`- und 30+ `wdigest.dll`-Versionen verfügbar und vorberechnet).

#### Automatisches Abrufen und Aktualisieren von Offsets
Eine zusätzliche Option wurde in `EDRSandBlast` implementiert, die es dem Programm ermöglicht, die benötigten `.pdb`-Dateien selbst vom Microsoft-Symbolserver herunterzuladen, die erforderlichen Offsets zu extrahieren und sogar die entsprechenden `.csv`-Dateien zu aktualisieren, falls vorhanden.

Die Verwendung der Option `--internet` macht die Ausführung des Tools viel einfacher, führt jedoch ein zusätzliches OpSec-Risiko ein, da während des Vorgangs eine `.pdb`-Datei heruntergeladen und auf die Festplatte geschrieben wird. Dies ist erforderlich für die `dbghelp.dll`-Funktionen, die zum Parsen der Symboldatenbank verwendet werden; es könnte jedoch in Zukunft eine vollständige PDB-Analyse im Speicher implementiert werden, um diese Anforderung aufzuheben und den Footprint des Tools zu reduzieren.

## Verwendung

Der anfällige Treiber `RTCore64.sys` kann abgerufen werden unter:```
http://download-eu2.guru3d.com/afterburner/%5BGuru3D.com%5D-MSIAfterburnerSetup462Beta2.zip

Kurzanleitung```

Usage: EDRSandblast.exe [-h | --help] [-v | --verbose] <audit | dump | cmd | credguard> [--usermode [--unhook-method ]] [--kernelmode] [--dont-unload-driver] [--dont-restore-callbacks] [--driver <RTCore64.sys>] [--service <SERVICE_NAME>] [--nt-offsets <NtoskrnlOffsets.csv>] [--wdigest-offsets <WdigestOffsets.csv>] [--add-dll ]* [-o | --dump-output <DUMP_FILE>]

root@kitploit:~
### Optionen```
-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 LSASS process, by default as 'lsass' 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.

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

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

        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

Other options:

--dont-unload-driver                    Keep the vulnerable driver installed on the host
                                        Default to automatically unsinstall the driver.
--dont-restore-callbacks                Do not restore the EDR drivers' Kernel Callbacks that were removed.
                                        Default to restore the callbacks.

--driver <RTCore64.sys>                 Path to the vulnerable driver file.
                                        Default to 'RTCore64.sys' in the current directory.
--service <SERVICE_NAME>                Name of the vulnerable service to intall / start.

--nt-offsets <NtoskrnlOffsets.csv>      Path to the CSV file containing the required ntoskrnl.exe's offsets.
                                        Default to 'NtoskrnlOffsets.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.

--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...

-o | --output <DUMP_FILE>               Output path to the dump file that will be generated by the 'dump' mode.
                                        Default to 'lsass' 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 ntoskrnl.exe and/or wdigest.dll

Erstellen

EDRSandBlast (nur x64) wurde mit Visual Studio 2019 erstellt (Windows SDK Version: 10.0.19041.0 und Plattformtoolset: Visual Studio 2019 (v142)).

Verwendung von ExtractOffsets.py

Beachten Sie, dass ExtractOffsets.py nur unter Windows getestet wurde.```

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:~
## Erkennung
Aus Sicht des Verteidigers (EDR-Anbieter, Microsoft, SOC-Analysten, die die EDR-Telemetrie untersuchen, ...) können mehrere Indikatoren verwendet werden, um diese Art von Techniken zu erkennen oder zu verhindern.

### Treiber-Whitelisting
Da jede Aktion, die das Tool im Kernel-Mode-Speicher ausführt, auf einen anfälligen Treiber angewiesen ist, um beliebige Inhalte zu lesen/schreiben, sollten Treiberladeereignisse von EDR-Produkten (oder SOC-Analysten) gründlich geprüft werden und bei jedem ungewöhnlichen Treiberladen einen Alarm auslösen oder sogar bekannte anfällige Treiber blockieren. Letzterer Ansatz wird sogar [von Microsoft selbst empfohlen](https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-defender-application-control/microsoft-recommended-driver-block-rules): Jedes HVCI (*Hypervisor-geschützte Codeintegrität*) aktivierte Windows-Gerät enthält eine Treiber-Blockliste, und dies wird schrittweise zum Standardverhalten unter Windows werden (unter Windows 11 ist es bereits Standard).

### Integritätsprüfungen des Kernel-Speichers
Da ein Angreifer immer noch einen unbekannten anfälligen Treiber verwenden könnte, um dieselben Aktionen im Speicher auszuführen, könnte der EDR-Treiber regelmäßig überprüfen, ob seine Kernel-Callbacks noch registriert sind, entweder direkt durch Inspektion des Kernel-Speichers (wie dieses Tool es tut) oder einfach durch Auslösen von Ereignissen (Prozesserstellung, Threaderstellung, Image-Laden usw.) und Prüfen, ob die Callback-Funktionen tatsächlich vom Executive-Kernel aufgerufen werden.

Als Randbemerkung: Diese Art von Datenstruktur könnte über den kürzlich eingeführten [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/) Mechanismus geschützt werden, der auf Virtual Based Security basiert, um das Kernel-Callbacks-Array ohne Aufruf der richtigen APIs nicht beschreibbar zu machen.

Die gleiche Logik könnte auf sensible ETW-Variablen wie `ProviderEnableInfo` angewendet werden, die von diesem Tool missbraucht werden, um die Generierung von ETW Threat Intelligence-Ereignissen zu deaktivieren.

### Benutzermodus-Erkennung
Der erste Hinweis darauf, dass ein Prozess aktiv versucht, User-Land-Hooking zu umgehen, sind die Dateizugriffe auf jede DLL, die geladenen Modulen entspricht; bei einer normalen Ausführung muss ein Userland-Prozess selten DLL-Dateien außerhalb eines `LoadLibrary`-Aufrufs lesen, insbesondere `ntdll.dll`.

Um zu verhindern, dass API-Hooking umgangen wird, könnten EDR-Produkte regelmäßig überprüfen, ob Hooks im Speicher innerhalb jedes überwachten Prozesses nicht verändert wurden.

Schließlich könnten EDR-Produkte, um Hooking-Umgehungen (Missbrauch eines Trampolins, Verwendung direkter Syscalls usw.) zu erkennen, die nicht das Entfernen von Hooks implizieren, potenziell auf Kernel-Callbacks zurückgreifen, die mit den missbrauchten Syscalls verbunden sind (z.B. `PsCreateProcessNotifyRoutine` für den `NtCreateProcess`-Syscall, `ObRegisterCallbacks` für den `NtOpenProcess`-Syscall usw.), und eine User-Mode-Call-Stack-Analyse durchführen, um festzustellen, ob der Syscall von einem normalen Pfad (`kernel32.dll` -> `ntdll.dll` -> Syscall) oder einem abnormalen (z.B. `program.exe` -> direkter Syscall) ausgelöst wurde.


## Danksagungen

- Aufzählung und Entfernung von Kernel-Callbacks:
  https://github.com/br-sn/CheekyBlinder

- Kernel-Speicher-Lese-/Schreib-Primitive durch den anfälligen
  `Micro-Star MSI Afterburner`-Treiber:
  https://github.com/Barakat/CVE-2019-16098/

- Deaktivierung des ETW Threat Intelligence-Anbieters:
  https://public.cnotools.studio/bring-your-own-vulnerable-kernel-driver-byovkd/exploits/data-only-attack-neutralizing-etwti-provider

- Treiberinstallation / -deinstallation: https://github.com/gentilkiwi/mimikatz

- Erste Liste von EDR-Treibernamen:
  https://github.com/SadProcessor/SomeStuff/blob/master/Invoke-EDRCheck.ps1

- Credential Guard-Umgehung durch erneutes Aktivieren von `Wdigest` mittels `LSASS`-Speicher-Patching:
  https://teamhydra.blog/2020/08/25/bypassing-credential-guard/


## Autoren

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

## Lizenz

CC BY 4.0 Lizenz - https://creativecommons.org/licenses/by/4.0/
Tool herunterladen