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 — Nutzt anfällige signierte Treiber aus, um EDR-Kernel-Callbacks, Objekt-Callbacks, ETW-TI-Provider und Userland-Hooks zu umgehen, für LSASS-Speicherauszug und Anmeldedatenextraktion. | Kitploit
Tools/GitHubGitHub/wavestone-cdt/edrsandblast
DefensivwerkzeugePrivilege EscalationExploitationPenetrationstestsRed Teaming
GitHubwavestone-cdt/edrsandblast

EDRSandblast

Nutzt anfällige signierte Treiber aus, um EDR-Kernel-Callbacks, Objekt-Callbacks, ETW-TI-Provider und Userland-Hooks zu umgehen, für LSASS-Speicherauszug und Anmeldedatenextraktion.

Repository anzeigen
1.8k3201vor 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

EDRSandBlast ist ein in C geschriebenes Tool, das einen verwundbaren signierten Treiber ausnutzt, um EDR-Erkennungen (Notify Routine Callbacks, Object Callbacks und den ETW TI-Provider) sowie LSASS-Schutzmechanismen zu umgehen. Es werden 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-Überwachung auszulesen, ohne blockiert zu werden oder Ereignisse im Zusammenhang mit "OS Credential Dumping" in der (Cloud-)Konsole des Produkts zu erzeugen. Die Tests wurden mit 3 verschiedenen EDR-Produkten durchgeführt und waren in jedem Fall erfolgreich.

Beschreibung

EDR-Bypass durch Entfernen von Kernel-Notify-Routinen

EDR-Produkte nutzen 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-Land heraus 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 in undokumentierte Arrays von Routinen im Kernel-Space ein:

  • PspCreateProcessNotifyRoutine für die Prozesserstellung
  • PspCreateThreadNotifyRoutine für die Thread-Erstellung
  • PspLoadImageNotifyRoutine für das Laden von Images

EDRSandBlast enumeriert die in diesen Arrays definierten Routinen 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). Die Enumeration und Entfernung wird durch die Ausnutzung einer primitiven Kernel-Speicher-Lese-/Schreibfähigkeit ermöglicht, die durch die Ausnutzung eines verwundbaren Treibers bereitgestellt wird (siehe Abschnitt zu verwundbaren Treibern).

Die Offsets der genannten Arrays werden mit verschiedenen Techniken wiederhergestellt, siehe Abschnitt zu Offsets.

EDR-Bypass durch Entfernen von Object-Callbacks

EDR- (und sogar EPP-) Produkte registrieren oft "Object-Callbacks" über die Verwendung der Kernel-API nt!ObRegisterCallbacks. Diese Callbacks erlauben es dem Sicherheitsprodukt, bei jeder Handle-Erstellung für bestimmte Objekttypen (Prozesse, Threads und Desktop-bezogene Objekt-Callbacks werden von Windows unterstützt) benachrichtigt zu werden. Eine Handle-Erstellung kann beim Öffnen eines Objekts (Aufruf von OpenProcess, OpenThread usw.) sowie bei der Handle-Duplizierung (Aufruf von DuplicateHandle usw.) auftreten.

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

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

Die genannte 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;

root@kitploit:~
Die `OB_CALLBACK`-Struktur, die oben erwähnt wurde, 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;

Um EDR-registrierte Objekt-Callbacks zu deaktivieren, werden in EDRSandblast drei Techniken implementiert; allerdings ist derzeit nur eine aktiviert.

Verwendung des Enabled-Felds von OB_CALLBACK_ENTRY

Dies ist die Standardtechnik, die in EDRSandblast aktiviert ist. Um EDR-bezogene Objekt-Callbacks zu erkennen und zu deaktivieren, wird die CallbackList-Liste in den _OBJECT_TYPE-Objekten, die an die Process- und Thread-Typen gebunden sind, durchsucht. Beide _OBJECT_TYPEs werden von öffentlichen globalen Symbolen im Kernel referenziert, PsProcessType und PsThreadType.

Jedes Element der Liste wird als zur oben beschriebenen OB_CALLBACK_ENTRY-Struktur passend angenommen (eine Annahme, die zum Zeitpunkt der Erstellung dieses Textes zumindest in allen Windows 10-Builds zu gelten scheint). Funktionen, die in den PreOperation- und PostOperation-Feldern definiert sind, werden lokalisiert, um zu prüfen, ob sie zu einem EDR-Treiber gehören, und falls ja, werden Callbacks einfach durch Umschalten des Enabled-Flags deaktiviert.

Obwohl es eine ziemlich sichere Technik ist, hat sie den Nachteil, auf einer undokumentierten Struktur zu beruhen; 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 (nicht lachen, 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 beruht (und daher theoretisch robuster gegenüber NT-Kernel-Änderungen 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; }

root@kitploit:~
Making the `Flink` and `Blink` pointers of the `CallbackList` `LIST_ENTRY` point to
the `LIST_ENTRY` itself effectively make the list empty. Since the `_OBJECT_TYPE` structure
is published in the kernel' symbols, the technique does not rely on hardcoded offsets/structures.
However, it has some drawbacks.

The first being not able to only disable callbacks from EDR; indeed, the technique affects
all object callbacks that could have been registered by "legitimate" software. It should
nevertheless be noted that object callbacks are not used by any pre-installed component
on Windows 10 (at the time of writing) so disabling them should not affect the machine
stability (even more so if the disabling is only temporary).

The second drawback is that process or thread handle operation are really frequent (nearly
continuous) in the normal functioning of the OS. As such, if the kernel write primitive used
cannot perform a `QWORD` write "atomically", there is a good chance that the
`_OBJECT_TYPE.CallbackList.Flink` pointer will be accessed by the kernel in the middle
of its overwriting. For instance, the MSI vulnerable driver `RTCore64.sys` can only perform
a `DWORD` write at a time, so 2 distinct IOCTLs will be needed to overwrite the pointer, between
which the kernel has a high probability of using it (resulting in a crash). On the other hand,
the vulnerable DELL driver `DBUtil_2_3.sys` can perform writes of arbitrary sizes in one
IOCTL, so using this method with it does not risk causing a crash.

#### Disabling object callbacks altogether
One last technique we found was to disable entirely the object callbacks support for thread
and processes. Inside the `_OBJECT_TYPE` structure corresponding to the process and
thread types resides a `TypeInfo` field, following the documented `_OBJECT_TYPE_INITIALIZER`
structure. The latter contains a `ObjectTypeFlags` bit field, whose `SupportsObjectCallbacks`
flag determines if the described object type (Process, Thread, Desktop, Token, File, etc.)
supports object callback registering or not. As previously stated, only Process, Thread and
Desktop object types supports these callbacks on a Windows installation at the time of writing.

Since the `SupportsObjectCallbacks` bit is checked by `ObpCreateHandle` or
`ObDuplicateObject` before even reading the `CallbackList` (and before executing
callbacks, of course), flipping the bit at kernel runtime effectively disable all object callbacks
execution.

The main drawback of the method is simply that *KPP* ("*PatchGuard*") monitors the integrity
of some (all ?) `_OBJECT_TYPE` structures, and triggers a [`0x109 Bug Check`](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/bug-check-0x109---critical-structure-corruption)
with parameter 4 being equal to `0x8`, meaning an object type structure has been altered.

However, performing the disabling / re-enabling (and "malicious" action in-between) quickly
enough should be enough to "race" *PatchGuard* (unless you are unlucky and a periodic
check is performed just at the wrong moment).

### EDR bypass through minifilters' callbacks unlinking
The Windows Filter Manager system allows an EDR to load a "minifilter" driver and
register callbacks in order to be notified of I/O operations, such as file opening,
reading, writing, etc. 

Here is a quick sum-up of different internal structures used by the filter manager:
- The Filter Manager establishes a "frame" (`_FLTP_FRAME`) as its root structure;
- A "volume" structure (`_FLT_VOLUME`) is instanciated for each "disk" managed by the
Filter Manager (can be partitions, shadow copies, or special ones corresponding to
named pipes or remote file systems);
- To each registered minifilter driver corresponds a "filter" structure (`_FLT_FILTER`),
describing various properties such as its supported operations;
- These minifilters are not all attached to each volume; an "instance" (`_FLT_INSTANCE`)
structure is created to mark each of the 
		filter<->volume associations;
- Minifilters register callback functions that are to be executed before and/or after
 specific operations (file open, write, read, etc.). These callbacks are described in
`_CALLBACK_NODE` structures, and can be accessed by different ways:
  - An array of all `_CALLBACK_NODE`s implemented by an instance of a minifilter
    can be found in the `_FLT_INSTANCE` structure; the array is indexed by the IRP 
    "major function" code, a constant representing the operations handled by the 
    callbacks (`IRP_MJ_CREATE`, `IRP_MJ_READ`, etc.).
  - Also, all `_CALLBACK_NODE`s implemented by instances linked to a specific volume
  are regrouped in linked lists, stored in the `_FLT_VOLUME.Callbacks.OperationLists`
  array indexed by IRP major function codes.

These different structures are browsed by `EDRSandblast` to detect filters that are 
associated with EDR-related drivers, and the callback nodes containing monitoring 
functions are enumerated. To disable their effect, the nodes are unlinked from their 
lists, making them temporarily invisible from the filter manager.

This way, during a specified period, the EDR can be completely unaware of any file 
operations. A basic example would be the creation of an lsass memory dump file on disk,
that would not trigger any analysis from the EDR, and thus no detection based on the 
file itself.

### EDR bypass through deactivation of the ETW Microsoft-Windows-Threat-Intelligence provider

The `ETW Microsoft-Windows-Threat-Intelligence` provider logs data about the
usages of some Windows API commonly used maliciously. This include the
`nt!MiReadWriteVirtualMemory` API, called by `nt!NtReadVirtualMemory` (which is
used to dump `LSASS` memory) and monitored by the `nt!EtwTiLogReadWriteVm`
function.

EDR products can consume the logs produced by the `ETW TI` provider through
services or processes running as, respectively,
`SERVICE_LAUNCH_PROTECTED_ANTIMALWARE_LIGHT` or
`PS_PROTECTED_ANTIMALWARE_LIGHT`, and associated with an `Early Launch Anti
Malware (ELAM)` driver.

As published by
[`slaeryan` in a `CNO Development Labs` blog post](https://public.cnotools.studio/bring-your-own-vulnerable-kernel-driver-byovkd/exploits/data-only-attack-neutralizing-etwti-provider),
the `ETW TI` provider can be disabled altogether by patching, in kernel memory,
its `ProviderEnableInfo` attribute to `0x0`. Refer to the great aforementioned
blog post for more information on the technique.

Similarly to the Kernel callbacks removal, the necessary `ntoskrnl.exe` offsets
(`nt!EtwThreatIntProvRegHandleOffset`, `_ETW_REG_ENTRY`'s `GuidEntry`, and
`_ETW_GUID_ENTRY`'s `ProviderEnableInfo`) are computed in the
`NtoskrnlOffsets.csv` file for a number of the Windows Kernel versions.

### EDR bypass through userland hooking bypass
#### How userland hooking works
In order to easily monitor actions that are performed by processes, EDR products often
deploy a mechanism called *userland hooking*. First, EDR products register a kernel
callback (usually *image loading* or *process creation* callbacks, see above) that allows
them to be notified upon each process start.


When a process is loaded by Windows, and before it actually starts, the EDR is able to
inject some custom DLL into the process address space, which contains its monitoring
logic. While loading, this DLL injects "*hooks*" at the start of every function that is to
be monitored by the EDR. At runtime, when the monitored functions are called by the
process under surveillance, these hooks redirect the control flow to some supervision code
present in the EDR's DLL, which allows it to inspect arguments and return values of these
calls.

Most of the time, monitored functions are system calls (such as `NtReadVirtualMemory`,
`NtOpenProcess`, etc.), whose implementations reside in `ntdll.dll`. Intercepting calls to
`Nt*` functions allows products to be as close as possible to the userland / kernel-land
boundary (while remaining in userland), but functions from some higher-level DLLs may also
be monitored as well.

Bellow are examples of the same function, before and after beeing hooked by the EDR product:```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			

(empty)```assembly NtProtectVirtualMemory proc near jmp sub_7FFC74490298 ; --> "hook", jump to EDR analysis function int 3 ; overwritten instructions int 3 ; overwritten instructions int 3 ; overwritten instructions test byte_7FFE0308, 1 ; <-- execution resumes here after analysis jnz short loc_7FFCB44AD1E5 syscall retn loc_7FFCB44AD1E5: int 2Eh retn NtProtectVirtualMemory endp

root@kitploit:~
#### Hooks-Erkennung
Userland-Hooks haben die "Schwäche", dass sie sich im Userland-Speicher befinden, was bedeutet, dass sie
direkt beobachtbar und durch den überwachten Prozess modifizierbar sind. Um automatisch Hooks
im Prozessadressraum zu erkennen, besteht die Hauptidee darin, die Unterschiede zwischen
der ursprünglichen DLL auf der Festplatte und der Bibliothek im Speicher, die möglicherweise von
einem EDR verändert wurde, zu vergleichen. Um diesen Vergleich durchzuführen, werden von
EDRSandblast die folgenden Schritte befolgt:
* Die Liste aller geladenen DLLs wird mit Hilfe der `InLoadOrderModuleList` im
  `PEB` aufgelistet (um die Verwendung von APIs zu vermeiden, die überwacht und verdächtig sein könnten).
* Für jede geladene DLL wird ihr Inhalt auf der Festplatte gelesen und ihre Header analysiert. Die
  entsprechende Bibliothek im Speicher wird ebenfalls analysiert, um Sektionen, Exporte,
  usw. zu identifizieren.
* Die Relokationen der DLL werden analysiert und unter Berücksichtigung der Basisadresse der
  entsprechenden geladenen Bibliothek angewendet. Dadurch wird der Inhalt sowohl der In-Memory-
  Bibliothek als auch der DLL von der Festplatte identisch (in Sektionen, wo Relokationen
  angewendet werden), was den Vergleich zuverlässig macht.
* Exportierte Funktionen werden aufgelistet und die ersten Bytes der "In-Memory"- und "On-Disk"-
  Versionen werden verglichen. Jeder Unterschied deutet auf eine Änderung hin, die nach dem Laden
  der DLL vorgenommen wurde, und ist daher sehr wahrscheinlich ein EDR-Hook.

Hinweis: Der Prozess kann verallgemeinert werden, um Unterschiede überall in nicht beschreibbaren
Sektionen zu finden, und nicht nur am Anfang exportierter Funktionen, falls EDR-Produkte z. B.
beginnen, Hooks in der Mitte einer Funktion anzuwenden :) Daher wird dies vom Tool nicht
verwendet, wurde aber in `findDiffsInNonWritableSections` implementiert.

Um die Überwachung durch diese Hooks zu umgehen, sind mehrere Techniken
möglich, jede mit Vor- und Nachteilen.

#### Hook-Bypass mittels ... Unhooking
Die intuitivste Methode, um die Hook-basierte Überwachung zu umgehen, ist die Entfernung der
Hooks. Da sich die Hooks im Speicher befinden, der für den Prozess selbst erreichbar ist, kann
der Prozess zum Entfernen eines Hooks einfach:
* Die Berechtigungen auf der Seite, auf der sich der Hook befindet, ändern (RX -> RWX oder RW)
* Die ursprünglichen Bytes schreiben, die dank des DLL-Inhalts 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 Offensivtool zu Beginn ausgeführt wird, kann der restliche Code
den Hook-Mechanismus völlig ignorieren und normal funktionieren, ohne überwacht zu werden.

Er hat jedoch zwei Hauptnachteile. Das 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. Auch wenn ein
Thread vom EDR ausgeführt wird und regelmäßig die Integrität der Hooks überprüft, könnte dies
ebenfalls eine Erkennung auslösen.

Für Implementierungsdetails siehe den Codepfad der `unhook()`-Funktion, wenn `unhook_method`
`UNHOOK_WITH_NTPROTECTVIRTUALMEMORY` ist.

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

#### Hook-Bypass 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 gewohnt auszuführen. Zuerst müssen die ursprünglichen Bytes der überwachten Funktion,
die vom EDR überschrieben wurden, um den Hook zu installieren, 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

Das Identifizieren dieser Bytes ist eine einfache Aufgabe, da wir in der Lage sind, einen sauberen Diff der Speicher- und Datenträgerversion der Bibliothek durchzuführen, wie zuvor beschrieben. Dann assemblieren wir eine Sprunganweisung, die den Kontrollfluss auf den Code unmittelbar nach dem Hook umleitet, an der Adresse `NtProtectVirtualMemory + sizeof(overwritten_instructions)````assembly jmp NtProtectVirtualMemory+8

root@kitploit:~
Schließlich verketten wir diese Opcodes, speichern sie in neu ausführbarem Speicher und behalten einen Zeiger darauf. Dieses Objekt wird als "*trampoline*" bezeichnet und kann dann als Funktionszeiger verwendet werden, der strikt äquivalent zur ursprünglichen `NtProtectVirtualMemory`-Funktion ist.

Der Hauptvorteil dieser Technik, wie auch bei allen folgenden Techniken, ist, dass der Hook nie gelöscht wird, sodass alle Integritätsprüfungen, die vom EDR an den Hooks durchgeführt werden, bestanden werden sollten. Allerdings erfordert es die Zuweisung von zunächst beschreibbarem, dann ausführbarem Speicher, was typisch für eine Shellcode-Zuweisung ist und somit die Aufmerksamkeit des EDR auf sich zieht.

Für Implementierungsdetails überprüfen Sie den Codepfad der `unhook()`-Funktion, wenn `unhook_method` ist `UNHOOK_WITH_INHOUSE_NTPROTECTVIRTUALMEMORY_TRAMPOLINE`. Bitte beachten Sie, dass die Technik nur in unserer Implementierung demonstriert wird und letztendlich dazu dient, Hooks aus dem Speicher zu **entfernen**, wie alle folgenden Techniken.

#### Hook-Umgehung unter Verwendung des eigenen EDR-Trampolins
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*), um die ursprünglichen Anweisungen effektiv nutzen zu können, hat das EDR sich wahrscheinlich irgendwo ein *trampoline* zugewiesen, 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 zugewiesen 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 committiertem und ausführbarem Speicher. Für jede solche Speicherregion scannen wir sie nach einer Sprunganweisung, die auf die Adresse nach den überschriebenen Anweisungen abzielt (in unserem vorherigen Beispiel `NtProtectVirtualMemory+8`). Das Trampolin kann dann verwendet werden, um die gehookedte Funktion aufzurufen, ohne den Hook auszulösen.

Diese Technik funktioniert überraschend gut, da sie fast alle Trampoline auf getesteten EDRs wiederherstellt. Für Implementierungsdetails überprüfen Sie den Codepfad der `unhook()`-Funktion, wenn `unhook_method` ist `UNHOOK_WITH_EDR_NTPROTECTVIRTUALMEMORY_TRAMPOLINE`.

#### Hook-Umgehung unter Verwendung einer doppelten DLL
Eine weitere einfache Methode, um Zugriff auf eine unüberwachte Version der `NtProtectVirtualMemory`-Funktion zu erhalten, besteht darin, eine doppelte Version der `ntdll.dll`-Bibliothek in den Prozessadressraum zu laden. Da zwei identische DLLs in denselben 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 gute Erfolgschance, da die meisten EDR-Produkte nach dem Start des Prozesses keine Hooks auf neu geladene DLLs setzen. Der größte Nachteil ist jedoch, dass das Kopieren von Microsoft-signierten Binärdateien unter einem anderen Namen oft von EDR-Produkten selbst als verdächtig angesehen wird.

Diese Technik ist dennoch in `EDRSandblast` implementiert. Für Implementierungsdetails überprüfen Sie den Codepfad der `unhook()`-Funktion, wenn `unhook_method` ist `UNHOOK_WITH_DUPLICATE_NTPROTECTVIRTUALMEMORY`.

#### Hook-Umgehung mittels direkter Syscalls
Um systemaufrufbezogene Funktionen zu nutzen, kann ein Programm Syscalls (in Assembler) neu implementieren, um die entsprechenden Betriebssystemfunktionen aufzurufen, ohne tatsächlich den Code in `ntdll.dll` zu berühren, der möglicherweise vom EDR überwacht wird. Dies umgeht vollständig jegliches Userland-Hooking, das an Syscall-Funktionen in `ntdll.dll` durchgeführt wird.

Dies hat dennoch einige Nachteile. Erstens erfordert dies, die Liste der Syscall-Nummern der benötigten Funktionen zu kennen, die sich mit jeder Windows-Version ändert. Dies wird jedoch dadurch gemildert, dass mehrere Heuristiken implementiert werden, die in allen bisherigen Versionen von Windows NT funktionieren (Sortieren der `Zw*`-Exports von `ntdll`, Suchen nach der `mov rax, #syscall_number`-Anweisung in der zugehörigen `ntdll`-Funktion usw.) und überprüft wird, dass 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.

Für Implementierungsdetails überprüfen Sie den Codepfad der `unhook()`-Funktion, wenn `unhook_method` ist `UNHOOK_WITH_DIRECT_SYSCALL`.

### Ausnutzung anfälliger Treiber
Wie bereits erwähnt, beruht jede Aktion, die einen Kernel-Speicher-Lese- oder Schreibzugriff erfordert, auf einem anfälligen Treiber, um diese Primitive bereitzustellen. In EDRSanblast kann die Unterstützung für einen neuen Treiber, der die Lese-/Schreib-Primitive bereitstellt, 'einfach' hinzugefügt werden, es müssen nur drei Funktionen implementiert werden:
* Eine `ReadMemoryPrimitive_DRIVERNAME(SIZE_T Size, DWORD64 Address, PVOID Buffer)`-Funktion, die `Size` Bytes von der Kernel-Adresse `Address` in den Userland-Puffer `Buffer` kopiert;
* Eine `WriteMemoryPrimitive_DRIVERNAME(SIZE_T Size, DWORD64 Address, PVOID Buffer)`-Funktion, die `Size` Bytes vom Userland-Puffer `Buffer` in die Kernel-Adresse `Address` kopiert;
* Eine `CloseDriverHandle_DRIVERNAME()`-Funktion, die sicherstellt, dass alle Handles zum Treiber geschlossen werden (vor dem Deinstallationsvorgang erforderlich, der 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` ist zu aktualisieren, wenn der verwendete anfällige Treiber geändert werden muss 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

Erkennung von EDR-Treibern und -Prozessen

Mehrere Techniken werden derzeit verwendet, um festzustellen, ob ein bestimmter Treiber oder Prozess zu einem EDR-Produkt gehört oder nicht.

Zunächst kann der Name des Treibers einfach zu diesem Zweck verwendet werden. In der Tat weist Microsoft bestimmte Nummern, sogenannte "Altitudes", für alle Treiber zu, die Callbacks im Kernel einfügen müssen. Dies ermöglicht eine deterministische Reihenfolge der Callback-Ausführung, unabhängig von der Registrierungsreihenfolge, sondern nur basierend auf der Treibernutzung. Eine Liste der (Hersteller von) Treibern, die bestimmte Altitudes reserviert haben, findet sich auf MSDN. Folglich wird von Microsoft eine nahezu umfassende Liste von Sicherheitstreibernamen, die mit Sicherheits- produkten verbunden sind, bereitgestellt, hauptsächlich in den Listen "FSFilter Anti-Virus" und "FSFilter Activity Monitor". Diese Listen von Treibernamen sind in EDRSandblast eingebettet, ebenso wie zusätzliche Beiträge.

Darüber hinaus sind EDR-Executables und -DLLs mehr als oft digital mit dem Signierungszertifikat des Herstellers signiert. Daher kann die Überprüfung des Signierers einer mit einem Prozess verbundenen ausführbaren Datei oder DLL schnell die Identifizierung von EDR-Produkten ermöglichen.

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

Schließlich, wenn man auf ein EDR stößt, das 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-Umgehung

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 Kernelspeicher darzustellen, enthält ein _PS_PROTECTION-Feld, das die Schutzstufe eines Prozesses über seine Type- (_PS_PROTECTED_TYPE) und Signer-Attribute (_PS_PROTECTED_SIGNER) definiert.

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

EDRSandBlast implementiert den Selbstschutz wie folgt:

  • Öffnen eines Handles auf den aktuellen Prozess
  • Auslesen aller System-Handles mithilfe von NtQuerySystemInformation, um das geöffnete Handle auf den aktuellen Prozess und die Adresse der EPROCESS-Struktur des aktuellen Prozesses im Kernelspeicher zu finden.
  • Nutzung der willkürlichen Lese-/Schreib-Schwachstelle des verwundbaren Treibers, um das _PS_PROTECTION-Feld des aktuellen Prozesses im Kernelspeicher zu überschreiben. Die Offsets des _PS_PROTECTION-Feldes relativ zur EPROCESS-Struktur (definiert durch die verwendete ntoskrnl-Version) werden in der Datei NtoskrnlOffsets.csv berechnet.

Credential Guard-Umgehung

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

Wenn Credential 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 Hashs führt der LSA-Prozess einen RPC-Aufruf an den LSAIso-Prozess durch und wartet auf das Ergebnis des LSAIso, um fortzufahren. Somit enthält der LSASS-Prozess keine Geheimnisse, sondern speichert stattdessen LSA Isolated Data.

Wie in der ursprünglichen Forschung von N4kedTurtle ausgeführt: "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 bei neuen interaktiven Anmeldungen im LSASS-Speicher gespeichert werden (ohne einen Neustart des Systems zu erfordern). Weitere Einzelheiten zu dieser Technik finden Sie im ursprünglichen Forschungsblogbeitrag.

EDRSandBlast macht den ursprünglichen PoC lediglich ein wenig 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-Ermittlung

Um Kernel-Überwachungsumgehungen zuverlässig durchführen zu können, muss EDRSandblast genau wissen, wo im Kernelspeicher gelesen und geschrieben werden muss. Dies geschieht mithilfe von Offsets globaler Variablen innerhalb des Zielimages (ntoskrnl.exe, wdigest.dll) sowie Offsets bestimmter Felder in Strukturen, deren Definitionen von Microsoft in Symbol-Dateien veröffentlicht werden. Diese Offsets sind für jeden Build der Zielimages spezifisch und müssen mindestens einmal für eine bestimmte Plattformversion gesammelt werden.

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

Um Offsets für jede spezifische Version von Windows zu ermitteln, werden zwei Ansätze implementiert.

Manuelle Offsets-Ermittlung

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 zu extrahieren. 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 Binarys ntoskrnl.exe und wdigest.dll von Winbindex referenziert und können automatisch heruntergeladen (und ihre Offsets extrahiert) werden vom ExtractOffsets.py-Skript. Dies ermöglicht die Extraktion von Offsets aus nahezu allen Dateien, die jemals in Windows-Update-Paketen veröffentlicht wurden (derzeit 450+ ntoskrnl.exe- und 30+ wdigest.dll-Versionen verfügbar und vorberechnet).

Automatische Offsets-Ermittlung und -Aktualisierung

Eine zusätzliche Option wurde in EDRSandBlast implementiert, um dem Programm zu ermöglichen, die benötigten .pdb-Dateien selbst vom Microsoft Symbol Server herunterzuladen, die erforderlichen Offsets zu extrahieren und sogar die entsprechenden .csv-Dateien zu aktualisieren, falls vorhanden.

Die Verwendung der --internet-Option macht die Ausführung des Tools viel einfacher, birgt jedoch ein zusätzliches OpSec-Risiko, da während des Prozesses eine .pdb-Datei heruntergeladen und auf die Festplatte gelegt wird. Dies ist erforderlich für die von dbghelp.dll verwendeten Funktionen zur Analyse der Symbol-Datenbank; eine vollständige In-Memory-PDB-Analyse könnte jedoch in Zukunft implementiert werden, um diese Anforderung zu umgehen und den Fußabdruck des Tools zu verringern.

Verwendung

Verwundbare Treiber

EDRSandblast unterstützt öffentlich mindestens 3 verwundbare Treiber: gdrv.sys (Standard), RTCore64.sys und DBUtil_2_3.sys. Der tatsächlich verwendete Treiber wird vor der Kompilierung des Tools festgelegt (siehe #define VULN_DRIVER <Treibername> in includes/KernelMemoryPrimitive.h). Eine Kopie des verwundbaren Treibers sollte heruntergeladen und EDRSandblast für seine Kernel-Operationen bereitgestellt werden.

Die Hashes der getesteten Treiber werden am Anfang jeder Datei Driver<name>.c erwähnt, die die Kernelspeicher-Lese- und -Schreib-Primitiven implementiert, die von EDRSandblast verwendet werden. Mit diesen Hashes können Beispiele für Treiber leicht im Internet gefunden werden, insbesondere auf https://www.loldrivers.io.

Hier ist die Liste der unterstützten verwundbaren Treiber zusammen mit Download-Links:

Schnelle Verwendung```

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

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

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


Hooking-related options:

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

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

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

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


BYOVD options:

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


Driver sideloading options:

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


Offset-related options:

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

Dump options:

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

Build

EDRSandBlast (nur x64) wurde mit Visual Studio 2019 erstellt (Windows SDK Version: 10.0.19041.0 und Plateform Toolset: 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 Telemetrie des EDR untersuchen, usw.) 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 einem verwundbaren Treiber basiert, um beliebige Inhalte zu lesen/schreiben, sollten Treiberladeereignisse von EDR-Produkten (oder SOC-Analysten) stark überprüft werden und bei jedem ungewöhnlichen Treiberladen einen Alarm auslösen oder sogar bekannte verwundbare 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 Windows-Gerät mit aktiviertem HVCI (*Hypervisor-geschützte Codeintegrität*) enthält eine Treiber-Blockliste, und dies wird schrittweise zum Standardverhalten unter Windows werden (unter Windows 11 ist es bereits der Fall).

### Kernel-Speicher-Integritätsprüfungen
Da ein Angreifer immer noch einen unbekannten verwundbaren 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) 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 könnte diese Art von Datenstruktur durch 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 ETW-Threat-Intelligence-Ereignisgenerierung zu deaktivieren.

### Erkennung im Benutzermodus
Der erste Indikator, dass ein Prozess aktiv versucht, User-Land-Hooking zu umgehen, sind die Dateizugriffe auf jede DLL, die geladenen Modulen entspricht; bei normaler 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 zur Erkennung von Hooking-Umgehungen (Missbrauch eines Trampolins, Verwendung direkter Syscalls usw.), die kein Entfernen der Hooks erfordern, möglicherweise 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

- Kernel-Callbacks-Enumeration und -Entfernung:
  https://github.com/br-sn/CheekyBlinder

- Kernel-Speicher-Lese-/Schreib-Primitiven durch den verwundbaren
  `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

- Treiber installieren/deinstallieren: https://github.com/gentilkiwi/mimikatz

- Anfängliche Liste der EDR-Treibernamen:
  https://github.com/SadProcessor/SomeStuff/blob/master/Invoke-EDRCheck.ps1

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


## Autoren

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

## Danke an die Mitwirkenden
- [v1k1ngfr](https://github.com/v1k1ngfr): für die Umgehung der Treibersignaturerzwingung (via `g_CiOptions`-Patchen) und die Unterstützung des GDRV.sys-Treibers
- [Windy Bug](https://github.com/0mWindyBug): für eine KDP-kompatible Umgehung der Treibersignaturerzwingung (via *Callback-Swapping*) und ihren großen Beitrag zur Minifilter-Umgehungsfunktion


## Lizenz

CC BY 4.0 Lizenz - https://creativecommons.org/licenses/by/4.0/
Tool herunterladen
Unterstützter TreiberDownload-LinkSHA256
GDRV.sysLOLDrivers-Link31f4cfb4c71da44120752721103a16512444c13c2ac2d857a7e6f13cb679b427
RTCore64.sysLOLDrivers-Link01aa278b07b58dc46c84bd0b1b5c8e9ee4e62ea0bf7a695862444af32e87f1fd
DBUtil_2_3.sysLOLDrivers-Link0296e2ce999e67c76352613a718e11516fe1b0efc3ffdb8918fc999dd76a73a5