In diesem Beitrag analysieren die Offensive-Hacker von IBM Security X-Force Red, wie Angreifer mit erhöhten Berechtigungen ihren Zugriff nutzen können, um Post-Ausbeutungs-Funktionen des Windows-Kernels zu nutzen. In den letzten Jahren haben öffentliche Berichte zunehmend gezeigt, dass auch weniger erfahrene Angreifer diese Technik einsetzen, um ihre Ziele zu erreichen. Es ist daher von Bedeutung, dass wir diese Fähigkeit in den Fokus rücken und mehr über ihre potenziellen Auswirkungen erfahren. Insbesondere werden wir in diesem Beitrag untersuchen, wie Kernel-Post-Ausbeutung dazu genutzt werden kann, ETW-Sensoren zu beeinträchtigen, und dies mit Malware-Beispielen in Verbindung bringen, die im letzten Jahr in freier Wildbahn identifiziert wurden.
Im Laufe der Zeit haben sich die Sicherheitsvorkehrungen und die Telemetrie zur Erkennung von Sicherheitslücken unter Windows erheblich verbessert. In Kombination mit gut konfigurierten EDR-Lösungen (Endpoint Detection & Response) können diese Fähigkeiten eine nicht zu vernachlässigende Hürde für die Nachbearbeitung von Sicherheitslücken darstellen. Angreifer müssen ständig Taktiken, Techniken und Verfahren (TTPs) entwickeln und iterieren, um Erkennungsheuristiken zu vermeiden. Im Adversary Simulation Team bei IBM Security X-Force stehen wir vor dem gleichen Problem. Unser Team hat die Aufgabe, fortschrittliche Bedrohungsfunktionen in einigen der größten und robustesten Umgebungen zu simulieren. Die Kombination aus komplexen, fein abgestimmten Sicherheitslösungen und gut ausgebildeten Teams im Security Operations Center (SOC) kann für das Handwerk eine große Belastung darstellen. In einigen Fällen wird die Verwendung einer bestimmten TTP innerhalb von drei bis vier Monaten vollständig überflüssig (in der Regel in Verbindung mit bestimmten Technologie-Stacks).
Angreifer können sich dafür entscheiden, die Codeausführung im Windows-Kernel zu nutzen, um einige dieser Schutzmaßnahmen zu manipulieren oder eine Reihe von Sensoren auf Benutzerebene vollständig zu umgehen. Die erste veröffentlichte Demonstration einer solchen Funktion erfolgte 1999 im Phrack Magazine. In den vergangenen Jahren gab es eine Reihe gemeldeter Fälle, in denen Bedrohungsakteure Kernel-Rootkits für die Post-Exploitation verwendet haben. Einige ältere Beispiele sind die Derusbi-Familie und das Lamberts Toolkit.
Traditionell waren diese Arten von Funktionen meist auf fortgeschrittene TAs beschränkt. In den letzten Jahren haben wir jedoch gesehen, dass immer mehr Commodity-Angreifer Bring Your Own Vulnerable Driver (BYOVD) Ausbeutung-Primitive nutzen, um Aktionen am Endpunkt zu erleichtern. In einigen Fällen waren diese Techniken recht primitiv und auf einfache Aufgaben beschränkt, es gab jedoch auch leistungsfähigere Demonstrationen.
Ende September 2022 veröffentlichten Forscher von ESET ein Whitepaper über eine solche Kernel-Funktion, die von der Lazarus TA bei einer Reihe von Angriffen auf Unternehmen in Belgien und den Niederlanden zum Zweck der Datenexfiltration eingesetzt wurde. Dieses Dokument beschreibt eine Reihe von DKOM-Primitiven (Direct Kernel Object Manipulation), die die Nutzlast verwendet, um die Telemetrie von Betriebssystemen, Antivirenprogrammen und EDR-Lösungen zu verschleiern. Die öffentlich zugänglichen Forschungsergebnisse zu diesen Techniken sind sehr begrenzt. Ein umfassenderes Verständnis der Kernel-Post-Exploitation-Techniken ist für die Verteidigung von entscheidender Bedeutung. Ein häufig vorgebrachtes, klassisches und naives Argument lautet, dass ein Angreifer mit erhöhten Berechtigungen alles tun kann. Warum sollten wir also in diesem Szenario Fähigkeiten modellieren? Das ist eine schwache Argumentation. Verteidiger müssen verstehen, über welche Fähigkeiten ein Angreifer verfügt, wenn er sich erhöht hat, welche Datenquellen zuverlässig bleiben (und welche nicht), welche Eindämmungsoptionen es gibt und wie fortschrittliche Techniken erkannt werden können (auch wenn die Fähigkeiten zur Durchführung dieser Erkennungen nicht vorhanden sind). In diesem Beitrag konzentriere ich mich speziell auf das Patchen von Strukturen der Kernel-Ereignisverfolgung für Windows (ETW), um Anbieter entweder unwirksam oder nicht funktionsfähig zu machen. Ich werde einige Hintergrundinformationen zu dieser Technik bereitstellen, analysieren, wie ein Angreifer Kernel-ETW-Strukturen manipulieren kann, und auf einige der Mechanismen zum Auffinden dieser Strukturen eingehen. Abschließend werde ich erläutern, wie diese Technik von Lazarus in ihrer Nutzlast implementiert wurde.
Branchen-Newsletter
Bleiben Sie mit dem Think-Newsletter über die wichtigsten – und faszinierendsten – Branchentrends in den Bereichen KI, Automatisierung, Daten und mehr auf dem Laufenden. Weitere Informationen finden Sie in der IBM Datenschutzerklärung.
Ihr Abonnement wird auf Englisch geliefert. In jedem Newsletter finden Sie einen Abmeldelink. Hier können Sie Ihre Abonnements verwalten oder sich abmelden. Weitere Informationen finden Sie in unserer IBM Datenschutzerklärung.
ETW ist eine in das Windows-Betriebssystem integrierte Hochgeschwindigkeits-Tracing-Funktion. Es ermöglicht das Protokollieren von Ereignissen und Systemaktivitäten durch Anwendungen, Treiber und das Betriebssystem und bietet detaillierte Einblicke in das Systemverhalten für Debugging, Leistungsanalysen und Sicherheitsdiagnosen.
In diesem Abschnitt werde ich einen allgemeinen Überblick über Kernel ETW und die zugehörige Angriffsfläche geben. Dies wird dazu beitragen, ein besseres Verständnis der Mechanismen bei der Manipulation von ETW-Anbietern und der damit verbundenen Auswirkungen dieser Manipulationen zu erlangen.
In diesem Beitrag konzentrieren wir uns auf die Angriffsfläche im Kernel-Bereich.
Dieser Beitrag befasst sich ausschließlich mit Angriffen der ersten Angriffskategorie aus „Abbildung 2“, bei denen die Ablaufverfolgung entweder deaktiviert oder in irgendeiner Weise verändert wird.
Bitte beachten Sie, dass bei der Betrachtung undurchsichtiger Strukturen unter Windows stets zu berücksichtigen ist, dass diese Änderungen unterliegen und sich tatsächlich häufig zwischen verschiedenen Windows-Versionen ändern. Dies ist besonders wichtig, wenn Sie Kernel-Daten überschreiben, da Fehler wahrscheinlich zu einem Blue Screen of Death (BSoD) führen können. Seien Sie vorsichtig!
Kernel-Provider werden mit nt!EtwRegister registriert, einer Funktion, die von ntoskrnl exportiert wird. Eine dekompilierte Version der Funktion ist unten zu sehen.
Die vollständige Initialisierung erfolgt innerhalb der inneren Funktion EtwpRegisterKMProvider, aber es gibt zwei wichtige Erkenntnisse:
Lassen Sie uns kurz die Strukturen auflisten, die Binarly auf der Folie in Abbildung 2 hervorgehoben hat.
Eine vollständige 64-Bit-Auflistung der _ETW_REG_ENTRY-Struktur ist unten dargestellt. Weitere Einzelheiten finden Sie hier im Blog von Geoff Chappell. Diese Struktur kann auch im Rahmen des Vergilius Project weiter untersucht werden.
// 0x70 Bytes (sizeof)
// Win11 22H2 10.0.22621.382
struct _ETW_REG_ENTRY
{
struct _LIST_ENTRY RegList; //0x0
struct _LIST_ENTRY GroupRegList; //0x10
struct _ETW_GUID_ENTRY* GuidEntry; //0x20
struct _ETW_GUID_ENTRY* GroupEntry; //0x28
union
{
struct _ETW_REPLY_QUEUE* ReplyQueue; //0x30
struct _ETW_QUEUE_ENTRY* ReplySlot[4]; //0x30
struct
{
VOID* Caller; //0x30
ULONG SessionId; //0x38
};
};
union
{
struct _EPROCESS* Process; //0x50
VOID* CallbackContext; //0x50
};
VOID* Callback; //0x58
USHORT Index; //0x60
union
{
USHORT Flags; //0x62
struct
{
USHORT DbgKernelRegistration:1; //0x62
USHORT DbgUserRegistration:1; //0x62
USHORT DbgReplyRegistration:1; //0x62
USHORT DbgClassicRegistration:1; //0x62
USHORT DbgSessionSpaceRegistration:1; //0x62
USHORT DbgModernRegistration:1; //0x62
USHORT DbgClosed:1; //0x62
USHORT DbgInserted:1; //0x62
USHORT DbgWow64:1; //0x62
USHORT DbgUseDescriptorType:1; //0x62
USHORT DbgDropProviderTraits:1; //0x62
};
};
UCHAR EnableMask; //0x64
UCHAR GroupEnableMask; //0x65
UCHAR HostEnableMask; //0x66
UCHAR HostGroupEnableMask; //0x67
struct _ETW_PROVIDER_TRAITS* Traits; //0x68
};
Einer der eingebetteten Einträge innerhalb _ETW_REG_ENTRY ist GuidEntry, eine _ETW_GUID_ENTRY Struktur. Weitere Informationen zu dieser undokumentierten Struktur finden Sie im Blog von Geoff Chappell hier und im Vergilius Project.
// 0x1a8 bytes (sizeof)
// Win11 22H2 10.0.22621.382
struct _ETW_GUID_ENTRY
{
struct _LIST_ENTRY GuidList; //0x0
struct _LIST_ENTRY SiloGuidList; //0x10
volatile LONGLONG RefCount; //0x20
struct _GUID Guid; //0x28
struct _LIST_ENTRY RegListHead; //0x38
VOID* SecurityDescriptor; //0x48
union
{
struct _ETW_LAST_ENABLE_INFO LastEnable; //0x50
ULONGLONG MatchId; //0x50
};
struct _TRACE_ENABLE_INFO ProviderEnableInfo; //0x60
struct _TRACE_ENABLE_INFO EnableInfo[8]; //0x80
struct _ETW_FILTER_HEADER* FilterData; //0x180
struct _ETW_SILODRIVERSTATE* SiloState; //0x188
struct _ETW_GUID_ENTRY* HostEntry; //0x190
struct _EX_PUSH_LOCK Lock; //0x198
struct _ETHREAD* LockOwner; //0x1a0
};
Schließlich ist einer der eingebetteten Einträge innerhalb von _ETW_GUID_ENTRY ProviderEnableInfo, eine Struktur vom Typ _TRACE_ENABLE_INFO. Weitere Informationen zu den Elementen dieser Datenstruktur finden Sie in der offiziellen Dokumentation von Microsoft und im Vergilius Project. Die Einstellungen in dieser Struktur beeinflussen direkt den Betrieb und die Funktionen des Providers.
// 0x20 Bytes (sizeof)
// Win11 22H2 10.0.22621.382
Struct _TRACE_ENABLE_INFO
{
ULONG IsEnabled; //0x0
UCHAR Level; //0x4
UCHAR Reserved1; //0x5
USHORT LoggerId; //0x6
ULONG EnableProperty; //0x8
ULONG Reserved2; //0xc
ULONGLONG MatchAnyKeyword; //0x10
ULONGLONG MatchAllKeyword; //0x18
};
Auch wenn ein theoretischer Hintergrund gut ist, ist es immer am besten, konkrete Beispiele zu betrachten, um ein umfassendes Verständnis für ein Thema zu gewinnen. Sehen wir uns ein kurzes Beispiel an. Die meisten entscheidenden Kernel-ETW-Provider werden innerhalb von nt!EtwpInitialize initialisiert, welches nicht exportiert wird. Ein Blick in diese Funktion offenbart etwa fünfzehn Provider.
Nehmen wir den Eintrag Microsoft-Windows-Threat-Intelligence (EtwTi) als Beispiel, können wir den globalen Parameter ThreatIntProviderGuid überprüfen, um den GUID für diesen Provider wiederherzustellen.
Eine Online-Suche nach diesem GUID zeigt sofort, dass wir den richtigen Wert wiederherstellen konnten (f4e1897c-bb5d-5668-f1d8-040f4d8dd344).
Sehen wir uns ein Beispiel an, in dem der Registrierungshandle-Parameter EtwThreatIntProvRegHandle verwendet wird, und analysieren wir, wie er verwendet wird. Eine Stelle, an der auf das Handle verwiesen wird, ist nt!EtwTiLogDriverObjectUnLoad. Aus dem Namen dieser Funktion lässt sich erahnen, dass sie dazu dient, Ereignisse zu generieren, wenn ein Treiberobjekt vom Kernel entladen wird.
Die Funktionen nt!EtwEventEnabled und nt!EtwProviderEnabled werden hier beide aufgerufen, wobei das Registrierungshandle als eines der Argumente übergeben wird. Sehen wir uns eine dieser Unterfunktionen genauer an, um besser zu verstehen, was hier vor sich geht.
Zugegebenermaßen ist das etwas schwer zu verstehen. Die Zeigerarithmetik ist jedoch nicht von besonderer Bedeutung. Konzentrieren wir uns stattdessen darauf, wie diese Funktion das Registrierungshandle verarbeitet. Es scheint, dass die Funktion eine Reihe von Eigenschaften der Struktur _ETW_REG_ENTRY und ihrer Unterstrukturen wie beispielsweise die Eigenschaft GuidEntry validiert.
struct _ETW_REG_ENTRY
{
…
struct _ETW_GUID_ENTRY* GuidEntry; //0x20
…
}
Und die Eigenschaft GuidEntry->ProviderEnableInfo .
struct _ETW_GUID_ENTRY
{
…
struct _TRACE_ENABLE_INFO ProviderEnableInfo; //0x60
…
}
Anschließend durchläuft die Funktion ähnliche, ebenenbasierte Prüfungen. Schließlich gibt die Funktion true oder false zurück, um anzuzeigen, ob ein Provider für die Ereignisprotokollierung auf einer bestimmten Ebene und mit einem bestimmten Schlüsselwort aktiviert ist. Weitere Einzelheiten finden Sie in der offiziellen Dokumentation von Microsoft.
Wir können sehen, dass die Integrität dieser Strukturen für den Betrieb des Anbieters von großer Bedeutung ist, wenn auf einen Anbieter über dessen Registrierungshandle zugegriffen wird. Umgekehrt könnte ein Angreifer, wenn er in der Lage wäre, diese Strukturen zu manipulieren, den Kontrollfluss des Aufrufers beeinflussen, um Ereignisse aus der Aufzeichnung zu entfernen oder zu eliminieren.
Wenn wir uns die von Binarly angegebene Angriffsfläche ansehen und uns auf unsere Lichtanalyse stützen, können wir einige Strategien vorschlagen, um die Ereigniserfassung zu stören.
Wir haben jetzt eine gute Vorstellung davon, wie ein DKOM-Angriff auf ETW aussehen könnte. Nehmen wir an, der Angreifer verfügt über eine Schwachstelle, die ihm eine Lese-/Schreibberechtigung für den Kernel gewährt, so wie es die Malware Lazarus in diesem Fall durch das Laden eines anfälligen Treibers tut. Was fehlt, ist eine Möglichkeit, diese Registrierungshandles zu finden.
Ich werde zwei Haupttechniken skizzieren, um diese Handles zu finden, und die Variante davon zeigen, die Lazarus in ihrer Kernel-Payload verwendet.
Zunächst sollte man darauf hinweisen, dass Kernel ASLR zwar existiert, dies aber keine Sicherheitsgrenze für lokale Angreifer darstellt, wenn diese Code auf MedIL-Niveau oder höher ausführen können. Es gibt viele Möglichkeiten, Kernel-Pointer zu leaken, die nur in Sandbox- oder LowIL-Szenarien eingeschränkt sind. Als Hintergrundinformation können Sie einen Blick in „I Got 99 Problems But a Kernel Pointer Ain't One“ von Alex Ionescu werfen; viele dieser Techniken sind auch heute noch anwendbar.
Das Tool der Wahl ist hier ntdll!NtQuerySystemInformation mit der Klasse SystemModuleInformation:
internal static UInt32 SystemModuleInformation = 0xB;
[DllImport(“ntdll.dll”)]
internal static extern UInt32 NtQuerySystemInformation(
UInt32 SystemInformationClass,
IntPtr SystemInformation,
UInt32 SystemInformationLength,
ref UInt32 ReturnLength);
Diese Funktion gibt die aktuelle Basisadresse aller im Kernel-Bereich geladenen Module zurück. An diesem Punkt ist es möglich, diese Module auf der Festplatte zu analysieren und Rohdatei-Offsets in relative virtuelle Adressen umzuwandeln und umgekehrt.
public static UInt64 RvaToFileOffset(UInt64 rva, List<SearchTypeData.IMAGE_SECTION_HEADER> sections)
{
foreach (SearchTypeData.IMAGE_SECTION_HEADER section in sections)
{
if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.VirtualSize)
{
return (rva – section.VirtualAddress + section.PtrToRawData);
}
}
return 0;
}
public static UInt64 FileOffsetToRVA(UInt64 fileOffset, List<SearchTypeData.IMAGE_SECTION_HEADER> sections)
{
foreach (SearchTypeData.IMAGE_SECTION_HEADER section in sections)
{
if (fileOffset >= section.PtrToRawData && fileOffset < (section.PtrToRawData + section.SizeOfRawData))
{
return (fileOffset – section.PtrToRawData) + section.VirtualAddress;
}
}
return 0;
}
Ein Angreifer kann diese Module auch mithilfe von Standard-Ladebibliotheks-API-Aufrufen (z. B. ntdll!LdrLoadDll) in seinen Benutzerprozess laden. Auf diese Weise vermeiden Sie Komplikationen bei der Konvertierung von Datei-Offsets in RVAs und zurück. Aus Sicht der operativen Sicherheit (OpSec) ist dies jedoch nicht ideal, da dadurch mehr Erkennungstelemetrie generiert werden kann.
Wo immer möglich, bevorzuge ich diese Technik, da sie die Portabilität von Lecks über verschiedene Modulversionen hinweg verbessert, weil diese weniger von Patch-Änderungen betroffen sind. Der Nachteil ist, dass Sie auf eine Gadget-Kette angewiesen sind, die für das Objekt existiert, das Sie leaken möchten.
Sehen wir uns die ETW-Registrierungshandles am Beispiel von Microsoft-Windows-Threat-Intelligence an. Nachfolgend sehen Sie den vollständigen Aufruf von nt!EtwRegister.
Hier wollen wir den Zeiger auf das Registrierungshandle EtwThreatIntProvRegHandle verlieren. Wie in param_4 in der ersten Zeile von Abbildung 8 geladen. Dieser Zeiger wird innerhalb des Abschnitts .data des Kernel-Moduls zu einem globalen Wert aufgelöst. Da dieser Aufruf in einer nicht exportierten Funktion erfolgt, können wir ihre Adresse nicht direkt erfahren. Stattdessen müssen wir prüfen, wo diese globale Variable referenziert wird und ob sie in einer Funktion verwendet wird, deren Adresse leaken kann.
Eine kurze Erkundung einiger dieser Einträge zeigt schnell einen Kandidaten in nt!KeInsertQueueApc.
Dies ist aus mehreren Gründen ein hervorragender Kandidat:
Ein Blick auf das Assembly zeigt das folgende Layout.
Das Weitergeben dieses Registrierungs-Handles ist dann unkompliziert. Wir lesen eine Reihe von Bytes unter Ausnutzung unserer Schwachstelle aus und suchen nach der ersten Anweisung mov R10, um den relativen virtuellen Offset der globalen Variablen zu berechnen. Die Berechnung würde in etwa so aussehen:
Int32 pOffset = Marshal.ReadInt32((IntPtr)(pBuff.ToInt64() + i + 3));
hEtwTi = (IntPtr)(pOffset + i + 7 + oKeInsertQueueApc.pAddress.ToInt64());
Mit dem Registrierungshandle ist es dann möglich, auf die Datenstruktur _ETW_REG_ENTRY zuzugreifen.
Im Allgemeinen können solche Gadget-Ketten verwendet werden, um eine Vielzahl von Kernel-Datenstrukturen zu leaken. Es ist jedoch anzumerken, dass es nicht immer möglich ist, solche Gadget-Ketten zu finden, und dass Gadget-Ketten manchmal mehrere komplexe Stufen aufweisen können. Eine mögliche Gadget-Kette zum Auslesen von Konstanten aus dem Seitenverzeichniseintrag (PDE) könnte beispielsweise wie folgt aussehen.
MmUnloadSystemImage -> MiUnloadSystemImage -> MiGetPdeAddress
Tatsächlich ergab eine oberflächliche Analyse der ETW-Registrierungshandles, dass die meisten keine geeigneten Gadget-Ketten haben, die wie oben beschrieben verwendet werden können.
Die andere wichtige Möglichkeit, diese ETW-Registrierungshandles zu leaken, ist die Verwendung von Speicherscans, entweder aus dem Live-Kernel-Speicher oder aus einem Modul auf der Festplatte. Beachten Sie, dass beim Scannen von Modulen auf der Festplatte Datei-Offsets in RVAs konvertiert werden können.
Dieser Ansatz besteht darin, eindeutige Byte-Muster zu identifizieren, nach diesen Mustern zu suchen und schließlich einige Operationen an den Offsets der Musterübereinstimmung durchzuführen. Betrachten wir nt!EtwpInitialize noch einmal genauer, um dies besser zu verstehen:
Alle fünfzehn Aufrufe von nt!EtwRegister sind größtenteils in dieser Funktion zusammengefasst. Die Hauptstrategie besteht darin, ein eindeutiges Muster zu finden, das vor dem ersten Aufruf von nt!EtwRegister auftritt, und ein zweites Muster, das nach dem letzten Aufruf von nt!EtwRegister auftritt. Das ist nicht allzu kompliziert. Ein Trick, mit dem sich die Portabilität verbessern lässt, besteht darin, einen Musterscanner zu erstellen, der mit Platzhalter-Byte-Zeichenfolgen umgehen kann. Diese Aufgabe bleibt dem Leser überlassen.
Sobald ein Start- und Stoppindex identifiziert wurde, können Sie alle Anweisungen dazwischen einsehen.
Sobald alle CALL-Anweisungen gefunden wurden, ist es möglich, rückwärts zu suchen und die Funktionsargumente zu extrahieren, zunächst den GUID, der den ETW-Provider identifiziert, und dann die Adresse des Registrierungshandles. Mit diesen Informationen sind wir in der Lage, gezielte DKOM-Angriffe auf die Registrierungshandles durchzuführen, um den Betrieb der identifizierten Provider zu beeinträchtigen.
Ich habe mir eine Probe der im ESET-Whitepaper erwähnten FudModle DLL besorgt und sie analysiert. Diese DLL lädt einen signierten, anfälligen Dell-Treiber (aus einer inline XOR-codierten Ressource) und steuert dann den Treiber, um viele Kernelstrukturen zu patchen, um die Telemetrie auf dem Host einzuschränken.
Als letzten Teil dieses Beitrags möchte ich die Strategie von Lazarus zur Suche nach Kernel-ETW-Registrierungshandles noch einmal zusammenfassen. Es handelt sich um eine Variante der oben beschriebenen Scanmethode.
Zu Beginn der Suchfunktion löst Lazarus nt!EtwRegister auf und verwendet diese Adresse, um den Scan zu starten
Diese Entscheidung ist etwas ungewöhnlich, da sie davon abhängt, wo diese Funktion existiert und wo die Funktion aufgerufen wird. Die relative Position einer Funktion in einem Modul kann von Version zu Version variieren, da neuer Code eingeführt, entfernt oder geändert werden kann. Aufgrund der Art und Weise, wie Module kompiliert werden, ist jedoch zu erwarten, dass Funktionen eine relativ stabile Reihenfolge beibehalten. Man kann davon ausgehen, dass es sich hierbei um eine Optimierung der Suchgeschwindigkeit handelt.
Bei der Suche nach Verweisen auf nt!EtwRegister in ntoskrnl zeigt sich, dass mit dieser Methode nicht viele Einträge übersehen werden. Lazarus hat möglicherweise auch zusätzliche Analysen durchgeführt, um festzustellen, dass die fehlenden Einträge nicht wichtig sind oder aus anderen Gründen nicht gepatcht werden müssen. Die fehlenden Einträge sind unten hervorgehoben. Durch die Anwendung dieser Strategie kann Lazarus während des Scans 0x7b1de0 Bytes überspringen, was bei einem langsamen Scanner eine nicht unerhebliche Menge sein kann.
Zusätzlich werden beim Start des Scans die ersten fünf Treffer übersprungen, bevor mit der Aufzeichnung der Registrierungshandles begonnen wird. Ein Teil der Suchfunktion ist unten dargestellt.
Der Code ist etwas schwer verständlich, aber wir verstehen die wichtigsten Punkte der Handlung. Der Code sucht nach Aufrufen von nt!EtwRegister, extrahiert den Registrierungshandle, konvertiert diesen Handle mithilfe eines KASLR-Bypasses in die Live-Adresse und speichert den Zeiger in einem Array, das zu diesem Zweck innerhalb einer Malware-Konfigurationsstruktur (bei der Initialisierung zugewiesen) reserviert ist.
Sehen wir uns zum Schluss noch einmal an, wie Lazarus diese Provider deaktiviert.
Das macht größtenteils Sinn. Was Lazarus hier tut, ist, die zuvor erwähnte globale Variable zu leaken und dann den Zeiger an dieser Adresse mit NULL zu überschreiben. Dadurch wird der Verweis auf die Datenstruktur _ETW_REG_ENTRY effektiv gelöscht, sofern diese vorhanden ist.
Ich bin aus mehreren Gründen nicht ganz zufrieden mit den gezeigten Methoden:
Ich habe diese Technik für die Wissenschaft neu implementiert, jedoch einige Anpassungen an der Vorgehensweise vorgenommen.
Insgesamt ist die oben beschriebene Technik nach den vorgenommenen Anpassungen eindeutig die beste Methode, um diese Art von Aufzählung durchzuführen. Da die Suchzeit bei optimierten Algorithmen vernachlässigbar ist, ist es sinnvoll, das gesamte Modul auf der Festplatte zu scannen und anschließend eine zusätzliche Nachbearbeitungslogik zu verwenden, um die Ergebnisse herauszufiltern.
Es ist ratsam, kurz zu bewerten, wie schwerwiegend die Auswirkungen eines solchen Angriffs sein könnten. Wenn Providerdaten reduziert oder vollständig eliminiert werden, kommt es zu einem Informationsverlust, aber gleichzeitig melden nicht alle Provider sicherheitsrelevante Ereignisse.
Eine Untergruppe dieser Anbieter ist jedoch sicherheitssensibel. Das offensichtlichste Beispiel dafür ist Microsoft Windows-Threat-Intelligence (EtwTi), eine zentrale Datenquelle für Microsoft Defender Advanced Threat Protection (MDATP), das jetzt Defender for Endpoint heißt (das ist alles sehr verwirrend). Bitte beachten Sie, dass der Zugang zu diesem Anbieter stark eingeschränkt ist. Nur Early Launch Anti Malware(ELAM)-Treiber können sich bei diesem Anbieter registrieren. Ebenso müssen die Prozesse im Benutzerland, die diese Ereignisse empfangen, einen geschützten Status (ProtectedLight / Antimalware) haben und mit demselben Zertifikat wie der ELAM-Treiber signiert sein.
Mit EtwExplorer lässt sich besser nachvollziehen, welche Arten von Informationen dieser Provider signalisieren kann.
Das XML-Manifest ist zu umfangreich, um es hier vollständig wiederzugeben, aber unten ist ein Ereignis aufgeführt, um einen Eindruck davon zu vermitteln, welche Arten von Daten mit DKOM unterdrückt werden können.
Der Kernel war und ist nach wie vor ein wichtiger, umkämpfter Bereich, in dem Microsoft und Drittanbieter Anstrengungen unternehmen müssen, um die Integrität des Betriebssystems zu gewährleisten. Datenkorruption im Kernel ist nicht nur ein Merkmal der Nachausnutzung, sondern auch ein zentraler Bestandteil der Entwicklung von Kernel-Exploits. Microsoft hat in diesem Bereich bereits erhebliche Fortschritte erzielt, insbesondere durch die Einführung von Virtualization Based Security (VBS) und einer seiner Komponenten, Kernel Data Protection (KDP).
Die Nutzer des Windows-Betriebssystems müssen ihrerseits sicherstellen, dass sie diese Fortschritte nutzen, um potenziellen Angreifern möglichst hohe Kosten aufzuerlegen. Windows Defender Application Control (WDAC) kann verwendet werden, um sicherzustellen, dass VBS-Sicherheitsvorkehrungen getroffen wurden und dass Richtlinien vorhanden sind, die das Laden potenziell gefährlicher Treiber verhindern.
Diese Bemühungen sind umso wichtiger, als wir zunehmend beobachten, dass Commodity-TAs BYOVD-Angriffe nutzen, um DKOM im Kernel-Bereich durchzuführen.
Erfahren Sie hier mehr über X-Force Red. Vereinbaren Sie hier eine kostenlose Beratung mit X-Force.