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
CVE-2022-37969 — Proof-of-Concept-Exploit für CVE-2022-37969, eine lokale Privilegieneskalation im Windows-Treiber für das Common Log File System. Demonstriert Heap-Spray, Token-Diebstahl und beliebiges Schreiben in den Kernel, um SYSTEM-Berechtigungen zu erlangen. | Kitploit
Tools/GitHubGitHub/fortra/cve-2022-37969
Privilege EscalationSpeicherforensikSchwachstellenanalyseExploitationBinary-Exploitation
GitHubfortra/cve-2022-37969

CVE-2022-37969

Proof-of-Concept-Exploit für CVE-2022-37969, eine lokale Privilegieneskalation im Windows-Treiber für das Common Log File System. Demonstriert Heap-Spray, Token-Diebstahl und beliebiges Schreiben in den Kernel, um SYSTEM-Berechtigungen zu erlangen.

Repository anzeigen
135381vor 3 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

CVE-2022-37969 Windows Local Privilege Escalation PoC

Autoren: Ricardo Narvaja & Daniel Kazimirow (Solid)

Nur zu Demonstrationszwecken. Der vollständige Exploit funktioniert auf anfälligen Windows 11 21H2-Systemen.

Funktionaler PoC basierend auf zuvor veröffentlichten Informationen von Zscaler

Siehe die Aufarbeitung Understanding the CVE-2022-37969 Windows Common Log File System Driver Local Privilege Escalation.

Nutzung

Die CVE-2022-37969 Windows Common Log File System Driver Local Privilege Escalation verstehen.

Exploit-Walkthrough:

  • Erstellen der anfänglichen BLF-Protokolldatei
    • Erstellen mehrerer zufälliger BLF-Protokolldateien
    • Erstellen der anfänglichen Protokolldatei
    • Durchführen eines kontrollierten Heap-Sprays
    • Vorbereiten der Methoden CreatePipe() / NtFsControlFile()
    • Sobald der Speicher vorbereitet ist, wird die Schwachstelle ausgelöst
    • Lesen des System-Tokens
    • Validieren des Tokens
    • Überschreiben des Tokens unseres Prozesses mit dem System-Token
    • Ausführen des Prozesses als System
    • Reverse Engineering des Patches: Analysieren der Strukturen
    • Beschädigen des „pContainer“-Zeigers
    • Erneute Betrachtung des Patches
    • Beschädigen der SignatureOffset
    • Beschädigen weiterer Werte
    • Kontrolle der Funktionen, die das Lesen des SYSTEM-Tokens ermöglichen
    • Schreiben in unseren eigenen Prozess, um eine lokale Privilegieneskalation zu erreichen
    • Quellcode des PoC

Das hier verwendete Szenario war Windows 11 21H2 (OS Build 22000.918) clfs.sys v10.0.22000.918

Erstellen der anfänglichen BLF-Protokolldatei

Der erste Schritt besteht darin, eine Datei namens MyLog.blf im öffentlichen Ordner (%public%) zu erstellen, indem die Funktion CreateLogFile() verwendet wird:

Erstellen mehrerer zufälliger BLF-Protokolldateien

Dann werden mehrere Protokolldateien mit zufälligen Namen in einer Schleife erstellt.

Und innerhalb der Schleife wird unsere Funktion getBigPoolInfo() aufgerufen:

Es wird NtQuerySystemInformation() mit 0x42 (66 dezimal) als erstem Argument aufgerufen; dies gibt in v5 die Informationen über die im bigpool vorgenommenen Zuordnungen zurück, deren Struktur vom Typ SYSTEM_BIGPOOL_INFORMATION ist.

Wir müssen diese Funktion zweimal aufrufen. Der erste Aufruf wird einen Fehler zurückgeben, aber uns die korrekte Größe des Puffers für den zweiten Aufruf liefern, um die gewünschten Informationen zu erhalten.

Interfaz de usuario gráfica, Aplicación Descripción generada automáticamente

v5 empfängt die Informationen der SYSTEM_BIG_POOL_INFORMATION-Struktur.

Die Anzahl der Zuweisungen im bigpool wird im ersten Feld namens Count gespeichert; im zweiten Feld befindet sich ein Array von SYSTEM_BIGPOOL_ENTRY-Strukturen.

Dann durchsuchen wir alle Strukturen nach dem Tag „Clfs“ und der Größe 0x7a00.

Es speichert in einem Array namens kernelAddrArray die VirtualAddress, das erste Feld jeder Struktur, die das CLFS-Tag und die Größe 0x7a00 hat. Von nun an werden die Pools, die beide Bedingungen erfüllen, als „right pools“ bezeichnet.

Zusätzlich zum Speichern jedes right pool im Array speichert es den letzten gefundenen right pool im Inhalt der Variablen a2, die als Argument der Funktion verwendet wird.

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Auf diese Weise zeigt a2 immer auf den zuletzt erstellten right pool mit CLFS-Tag und Größe 0x7a00.

Die Variable v26 speichert immer den zuvor gefundenen right pool, da sie vor dem Aufruf von getBigPoolinfo() gleich v24 ist (v26=v24), aber v24 wird beim Verlassen dieses Aufrufs mit dem letzten gefundenen right pool aktualisiert, und v26 bleibt mit dem zuvor gefundenen right pool.

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Dann subtrahiert es beide Adressen, und falls das Ergebnis negativ ist, werden die Operanden umgekehrt, sodass es immer positiv ist.

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Auf diese Weise speichert v32 die Differenz zwischen den VirtualAddresses der letzten beiden gefundenen right pools.

Dann macht es etwas Ähnliches; in diesem Fall ist v23 anfänglich null, also setzt es v23 = v32 beim ersten Mal.

Beim nächsten Durchlauf der Schleife hat v23 immer noch denselben Wert und ist nicht null, also bricht es ab und geht hierhin.

V32 hat die letzte Differenz und v23 die vorherige; wenn sie gleich sind, wird ausgegeben und um eins erhöht, aber der Zähler wird auf null zurückgesetzt.

Die Idee ist, 6 aufeinanderfolgende Vergleiche von CLFS-Tags und Größe 0x7a00 zu finden, deren Differenzen gleich sind, und diese Differenz wird 0x11000 sein. Wir werden sehen, dass bei der Ausführung, wenn 6 (da bei null begonnen wird) aufeinanderfolgende mit gleichen Abständen gefunden werden, dieser Wert der Differenz zwischen ihnen ausgegeben wird.

Texto Descripción generada automáticamente

Dort sehen wir, dass er 6 aufeinanderfolgende gefunden hat und die Schleife zum Erstellen der Protokolldateien verlassen hat.

Im Ordner „public“ können wir die erstellten Dateien sehen

Erstellen der anfänglichen Protokolldatei:

Unsere Funktion craftFile() öffnet die ursprüngliche Datei (MyLog.blf) und modifiziert sie, um den Fehler auszulösen.

Nach dem Ändern der Datei ist es notwendig, die CRC32 zu ändern, da sonst ein Fehler wegen einer beschädigten Datei auftritt.

Dieser Wert befindet sich an Offset 0x80C der Datei.

Durchführen eines kontrollierten Heap-Sprays

Als Nächstes wird ein Heap-Spray mit der Funktion VirtualAlloc() durchgeführt, um Speicher an den willkürlichen Adressen 0x10000 und 0x5000000 zu reservieren, und in der zweiten Zuweisung (0x10000) wird der Wert 0x5000000 alle 0x10 Bytes gespeichert.

Vorbereiten der Methoden CreatePipe() / NtFsControlFile()

Es verwendet CreatePipe(), um eine anonyme Pipe zu erstellen, und ruft NtFsControlFile() mit dem Argument 0x11003c auf, um ein Attribut hinzuzufügen; später kann dieselbe Funktion mit dem Argument 0x110038 aufgerufen werden, um es zu lesen.

Weitere Details zu dieser Methode finden Sie HIER

Dort sehen wir den Eingabepuffer, der das hinzugefügte Attribut ist; wenn wir NtFsControlFile() erneut mit dem Argument 0x11038 aufrufen, sollte dieser im Ausgang dasselbe Attribut zurückgeben.

Suche im Pool nach dem Tag des erstellten Attributs (NpAt)

Und wenn es gefunden wird, speichert es die VirtualAddress dieses Pools in v30.Pointer.

V30.pointer+24 zeigt auf AttributeValueSize im Kernel-Pool und speichert es in einem der Heap-Sprays, die wir zuvor erstellt haben.

Die Idee ist, auf diese Kernel-Adresse+8 zu schreiben, um den AttributeValue zu überschreiben.

Texto Descripción generada automáticamente

Die PipeAttribute-Struktur hat als erstes Feld eine LIST_ENTRY mit einer Größe von 16 Bytes, dann einen Zeiger auf den Namen des Attributs mit einer Größe von 8 Bytes, und dann kommt bei 0x18 (24 dezimal) das Feld AttributeValueSize, das wir im Heap-Spray speichern.

Danach laden wir CLFS.sys und ntoskrnl im Benutzermodus und finden mit GetProcAddress() die Adressen der Funktionen ClfsEarlierLsn() und SeSetAccessStateGenericMapping().

Dann rufen wir die Funktion FindKernelModulesBase() auf, die die Kernel-Basis beider Module mit NtquerySystemInformation() findet, diesmal mit dem Argument SystemModuleInformation, um die Informationen aller Module zurückzugeben.

Auf diese Weise können wir den Offset jeder Funktion berechnen und sie dann im Kernel erhalten.

Sobald der Speicher vorbereitet ist, wird die Schwachstelle ausgelöst:

Die Funktion pipeArbitraryWrite() wird zweimal aufgerufen; es gibt ein Flag, das beim ersten Aufruf anfänglich null ist und beim zweiten Aufruf den Wert 1 hat; dies ändert die Werte des Heap-Sprays.

Texto Descripción generada automáticamente

Beim ersten Aufruf werden an der Speicheradresse 0x5000000 die folgenden Werte abgelegt.

Denken Sie daran, dass dieser Wert zusätzlich zur Zuordnung in diese Richtung in unserem Heap-Spray gespeichert wird.

So sieht der Speicher nach dem ersten Aufruf aus, wie gesagt bei der Adresse um 0x5000000.

Und im Heap-Spray ab Speicher 0x10000 wird der Zeiger auf AttributeValueSize alle 0x10 Bytes gespeichert, zusätzlich zum Zeiger auf 0x5000000.

Lesen des System-Tokens:

Diese Sequenz löst den Fehler aus:

CreateLogFile() wird erneut auf der erstellten Datei und auf einer anderen mit einem zufälligen Namen aufgerufen.

AddLogContainer() wird dann mit den Handles dieser Dateien aufgerufen.

NtSetinformationFile() wird aufgerufen, und die Handles werden geschlossen, wodurch der Zeiger beschädigt wird (wird später erklärt).

Interfaz de usuario gráfica, Aplicación Descripción generada automáticamente con confianza media

Das Heap-Spray verhindert an dieser Stelle einen BSOD:

Wenn wir dort einen Breakpoint setzen, sehen wir, dass der Zeiger beschädigt ist und auf unser Heap-Spray zeigt, mit dem wir die nächsten beiden Funktionsaufrufe der vtable steuern können.

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Texto Descripción generada automáticamente

RAX nimmt den Wert 0x5000000 an und springt zuerst zur Funktion an 0x5000000+18 und dann zu 0x5000000+8.

Texto Descripción generada automáticamente con confianza media

Imagen que contiene Interfaz de usuario gráfica Descripción generada automáticamente

Also springt es zuerst zu fnClfsEarlierLns() und dann zu fnSeSetAccessStateGenericMapping().

Wir verfolgen ab dem Breakpoint und sehen, dass es CLFS!ClfsEarlierLsn() erreicht.

Texto Descripción generada automáticamente

Diese Funktion wird speziell aufgerufen, weil sie bei der Rückkehr EDX auf 0xFFFFFFFF setzt.

Interfaz de usuario gráfica Descripción generada automáticamente con confianza media

An der Adresse 0xFFFFFFFF hatten wir das Ergebnis von SYSTEM _EPROCESS & 0xFFFFFFFFFFFFFFF000 gespeichert.

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Wie erwähnt, ist der RDX-Wert bei der Rückkehr von CLFS!ClfsEarlierLsn() 0x00000000FFFFFFFF.

Texto Descripción generada automáticamente

Wir kommen zur zweiten Funktion nt!SeSetAccessStateGenericMapping().

Interfaz de usuario gráfica, Aplicación Descripción generada automáticamente

Diese Funktion ist nützlich, da RCX auf unser Heap-Spray zeigt und RDX den Wert 0xFFFFFFFF hat, dessen Inhalt wir kontrollieren.

Interfaz de usuario gráfica, Aplicación, Teams Descripción generada automáticamente

Texto Descripción generada automáticamente

Der Inhalt von RCX+0x48 enthält den Zeiger auf AttributeValueSize, der in v30.Pointer+24 gespeichert wurde.

Interfaz de usuario gráfica, Texto Descripción generada automáticamente

Interfaz de usuario gráfica, Texto Descripción generada automáticamente con confianza media

Interfaz de usuario gráfica, Texto Descripción generada automáticamente

Dieser Zeigerwert von AttributeValueSize wird nach RAX verschoben, dann wird der Inhalt der Adresse 0xFFFFFFFF gelesen, wo wir die Adresse von SYSTEM _EPROCESS & 0xFFFFFFFFFFFFFFF000 gespeichert hatten.

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Dann überschreibt es in RAX+8 das nächste Feld, das AttributeValue() ist.

Texto Descripción generada automáticamente

Texto Descripción generada automáticamente

Natürlich würde der AttributeValue normalerweise im Kernel auf das von uns hinzugefügte Attribut zeigen.

Calendario Descripción generada automáticamente

Und jetzt überschreiben wir es mit einem Zeiger auf das Ergebnis von system _EPROCESS & 0xFFFFFFFFFFFFFFF00.

Das bedeutet, dass bei erneutem Aufruf der Funktion NtFsControlFile() mit dem Argument 0x110038 zum Lesen des Attributs, anstatt des „A“, auf das der AttributeValue-Zeiger zeigte, nun von _EPRROCESS & 0xFFFFFFFFFFFFFFFFF000 die angeforderte Anzahl von Bytes gelesen und im Ausgabepuffer zurückgegeben wird, sodass wir beim ersten Aufruf den Wert des SYSTEM TOKEN erhalten können.

Texto Descripción generada automáticamente

v9b ist die Startadresse des Output-Buffers, in den der Inhalt des Ergebnisses von System EPROCESS & 0xFFFFFFFFFFFFFFF000 kopiert wurde.

Dazu addiert er v14, die letzten 3 Bytes des System- EPROCESS, und dann 0x4b8, den Offset von Token für diese Windows 11-Version; dann findet er den Inhalt dieser Adresse, der den Wert des System-Tokens gespeichert hat.

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Texto Descripción generada automáticamente

Validieren des Tokens

Texto Descripción generada automáticamente con confianza baja

Denken Sie daran, dass die letzten 4 Bits geändert wurden; das ist nicht signifikant, also stimmt der Wert immer noch überein.

Überschreiben des Tokens unseres Prozesses mit dem System-Token

Beim zweiten Aufruf ist der Wert von Flag 1, da er am Ende des ersten Aufrufs erhöht wurde.

Interfaz de usuario gráfica, Texto, Aplicación, Correo electrónico Descripción generada automáticamente

Dort sehen wir die Reihenfolge, in der die Werte gespeichert werden.

Interfaz de usuario gráfica, Texto Descripción generada automáticamente

Die Adresse 0xFFFFFFFF mit dem Wert, den wir gerade vom System Process Token gefunden haben.

Interfaz de usuario gráfica, Texto Descripción generada automáticamente

Texto Descripción generada automáticamente

Und im Heap-Spray befindet sich der Wert der Token-Adresse meines Prozesses, von dem ich 8 subtrahiere. Dieser Wert plus acht wird als Ziel verwendet. Denken Sie daran, dass auf die Adresse geschrieben wird, auf die RAX+8 zeigt.

Graphical user interface, text Description automatically generated

Texto Descripción generada automáticamente

An der Speicheradresse ab 0x5000000.

Interfaz de usuario gráfica Descripción generada automáticamente

Wir sehen auch, dass der Name eines anderen Containers verwendet wird, da der vorherige vom Systemprozess verwendet wird und nicht erneut geöffnet oder gelöscht werden kann.

Dann wird der Fehler ein zweites Mal auf dieselbe Weise ausgelöst wie beim ersten Versuch.

Es kommt erneut zu CLFS!ClfsEarlierLsn().

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Setzt RDX auf 0xFFFFFFFF.

Una captura de pantalla de un celular Descripción generada automáticamente

Dann kommt es zu nt!SeSetAccessStateGenericMapping().

Texto Descripción generada automáticamente

Liest die Adresse des Tokens meines Prozesses minus 8, wohin geschrieben wird.

Texto Descripción generada automáticamente

Dann liest es das SYSTEM TOKEN.

Texto Descripción generada automáticamente

Und schreibt an die Adresse des Tokens meines Prozesses (es addiert 8) das System Token.

Und auf diese Weise hat mein Prozess das System-Token.

Texto Descripción generada automáticamente

Sobald das Token geschrieben ist, starten wir einen Prozess, um die Berechtigungen zu überprüfen; in diesem Fall starten wir Notepad.exe.

Ausführen des Prozesses als System:

Texto Descripción generada automáticamente

Interfaz de usuario gráfica, Aplicación, Word Descripción generada automáticamente

Texto Descripción generada automáticamente con confianza baja

Denken Sie daran, dass dieser PoC nur unter Windows 11 funktioniert; unter Windows 10 führt er zu einem BSOD, sodass Sie einige Änderungen vornehmen müssen, damit er korrekt funktioniert. Dies wird in diesem Blogpost nicht erklärt.

Reverse Engineering des Patches:

Analyse der Strukturen

Die Strukturen und der größte Teil der Dokumentation zum CLFS-Dateiformat haben wir der hervorragenden Arbeit von IONESCU über CLFS Internals entnommen.

Wir können sehen, dass in der Funktion ClfsBaseFilePersisted::LoadContainerQ eine Prüfung hinzugefügt wurde.

Texto Descripción generada automáticamente con confianza media

Die Werte, die eine Addition durchführen, gehören zur Struktur _CLFS_BASE_RECORD_HEADER.

Escala de tiempo Descripción generada automáticamente con confianza media

Beachten Sie, dass der Base Block bei Offset 0x800 der Datei beginnt und bei Offset 0x71FF endet, wobei die ersten 0x70 Bytes dem Log Block Header entsprechen.

Als bewährte Methode können wir die _CLF_LOG_BLOCK_HEADER-Struktur in IDA hinzufügen

struct _CLFS_LOG_BLOCK_HEADER

{

UCHAR MajorVersion;

UCHAR MinorVersion;

UCHAR Usn;

char ClientId;

USHORT TotalSectorCount;

USHORT ValidSectorCount;

ULONG Padding;

ULONG Checksum;

ULONG Flags;

CLFS_LSN CurrentLsn;

CLFS_LSN NextLsn;

ULONG RecordOffsets[16];

ULONG SignaturesOffset;

};

Dann haben wir den Basis-Datensatz-Header (_CLFS_BASE_RECORD_HEADER), der am Offset 0x870 vom Dateianfang beginnt und 0x1338 Bytes lang ist.

Interfaz de usuario gráfica, Texto, Aplicación, Correo electrónico Descripción generada automáticamente

Wenn Sie es in IDA importieren möchten, müssen Sie zuvor die folgenden Typen und fehlenden Strukturen hinzufügen

typedef GUID CLFS_LOG_ID;
typedef UCHAR CLFS_LOG_STATE;

struct _CLFS_METADATA_RECORD_HEADER

{

ULONGLONG ullDumpCount;

};

Jetzt kann es hinzugefügt werden:

typedef struct _CLFS_BASE_RECORD_HEADER

{

CLFS_METADATA_RECORD_HEADER hdrBaseRecord;

CLFS_LOG_ID cidLog;

ULONGLONG rgClientSymTbl[0x0b];

ULONGLONG rgContainerSymTbl[0x0b];

ULONGLONG rgSecuritySymTbl[0x0b];

ULONG cNextContainer;

CLFS_CLIENT_ID cNextClient;

ULONG cFreeContainers;

ULONG cActiveContainers;

ULONG cbFreeContainers;

ULONG cbBusyContainers;

ULONG rgClients[0x7c];

ULONG rgContainers[0x400];

ULONG cbSymbolZone;

ULONG cbSector;

USHORT bUnused;

CLFS_LOG_STATE eLogState;

UCHAR cUsn;

UCHAR cClients;

} CLFS_BASE_RECORD_HEADER, *PCLFS_BASE_RECORD_HEADER;

Interfaz de usuario gráfica, Texto Descripción generada automáticamente

Nach Einbindung der Strukturen stellen wir fest, dass eine Addition zwischen der cbSymbolZone und der Adresse, wo der _CLFS_BASE_RECORD_HEADER endet, durchgeführt wird. (Start + 1338h)Texto, Aplicación Descripción generada automáticamente

Denken Sie daran, dass cbSymbolZone in der präparierten Logdatei von 0x000000F8 auf 0x0001114B geändert wurde.

(Offset 0x1b98 der Datei)

0x800(offset of the start of the Base Block) + 0x70 (logBlockHeader) + 0x1328 (cbsymbolZone)

0x800+0x70+0x1328 = 0x1b98

Präparierte cbsymbolZone in der Datei MyLog.blf:

Tabla Descripción generada automáticamente

Imagen que contiene Texto Descripción generada automáticamente

Da der Patch in der Funktion CClfsBaseFilePersisted::LoadContainerQ liegt, müssen wir uns das CClfsBaseFilePersisted-Objekt ansehen.

Setzen Sie einen Haltepunkt in CLFS!CClfsBaseFilePersisted::LoadContainerQ; wenn CreateLogFile mit dem Handle der präparierten Datei aufgerufen wird, wird es anhalten.

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Rufen Sie die Funktion CClfsBaseFile::GetBaseLogRecord auf, um die Adresse des Basis-Log-Datensatzes (_CLFS_BASE_RECORD_HEADER) zu erhalten.

Graphical user interface, application, timeline Description automatically generated

RAX wird auf die Adresse von _CLFS_BASE_RECORD_HEADER zeigen.

Interfaz de usuario gráfica, Texto, Aplicación, Correo electrónico Descripción generada automáticamente

Beachten Sie die _CLFS_BASE_RECORD_HEADER-Struktur im Speicher und das Feld cbsymbolZone 0x1328 Bytes voraus.

Imagen que contiene Texto Descripción generada automáticamente

Texto Descripción generada automáticamente

r14 speichert die Struktur, die dem „this“ entspricht, also CClfsBaseFilePersisted, da es das this der Funktion CClfsBaseFilePersisted::LoadContainerQ ist.

Interfaz de usuario gráfica, Aplicación Descripción generada automáticamente

Die CClfsBaseFilePersisted-Struktur im Speicher:

Texto Descripción generada automáticamente

Also erstellen wir eine Struktur mit der Länge 0x21c0, um seine Felder während des Reverse Engineerings zu vervollständigen (es ist eine undokumentierte Struktur); wir nennen sie struct_CClfsBaseFilePersisted.

Tabla Descripción generada automáticamente con confianza media

Innerhalb der Funktion CClfsBaseFile::GetBaseLogRecord() wird der Zeiger auf _CLFS_BASE_RECORD_HEADER abgerufen. Und wir wissen, dass das „this“ in dieser Funktion die Struktur struct_CClfsBaseFilePersisted ist.

Escala de tiempo Descripción generada automáticamente con confianza media

Liest zwei Felder (Offset 0x28 und 0x30)

Interfaz de usuario gráfica, Aplicación, Tabla Descripción generada automáticamente

Feld 0x28 ist ein Word und hat den Wert 6, daher ändern wir den Typ in word in der Struktur.

Texto Descripción generada automáticamente

Texto Descripción generada automáticamente con confianza media

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Vorerst benennen wir es in Konstante 6 (const_6) um.

Texto Descripción generada automáticamente

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Laut Dokumentation wäre 6 die Anzahl der Blöcke CLFS_METADATA_BLOCK_COUNT. Das Feld könnte auf diesen Wert verweisen.

Und dieser Zeiger befindet sich am Offset 0x30.

Tabla Descripción generada automáticamente

Beachten Sie, dass die dort angezeigte Größe den Header mit der Länge 0x10 einschließt.

Texto Descripción generada automáticamente

Forma Descripción generada automáticamente con confianza media

Wenn die Funktion ExAllocatePoolWithTag aufgerufen wird, werden einige Bytes angefordert, aber der Header ist nicht enthalten, daher werden 0x90 Bytes (0xa0 – 0x10) im Aufruf angefordert.

Beim Durchsuchen nach dem Text +30h] fanden wir eine lange Liste von Anweisungen, die am Offset 0x30 schreiben. Wenn wir die Liste jedoch nach dem Objekttyp CClfsBaseFilePersisted filtern, bleiben nur wenige Ergebnisse übrig, und wir finden sofort, wo diese Größe mit demselben Tag alloziert wird. (Tipp: Funktionsnamen wie Create und Initialize sind immer die ersten, die man sich ansieht.)

Texto Descripción generada automáticamente con confianza baja

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Da wir den Namen noch nicht kennen, nennen wir es pool_0x90, eine weitere undokumentierte Struktur, und wir erstellen eine Struktur dieser Größe.

Texto Descripción generada automáticamente

Interfaz de usuario gráfica, Tabla Descripción generada automáticamente

Das pool_0x90 im Speicher hat einen weiteren Zeiger an seinem eigenen Offset 0x30.

Aplicación, Tabla Descripción generada automáticamente con confianza media

Dieser andere Zeiger zeigt auf den Basisblock in der Datei (Basisblock beginnt bei Offset 0x800).

Forma Descripción generada automáticamente

A picture containing calendar Description automatically generated

Bild entnommen aus dem Zscaler-Blogpost:

Graphical user interface, application, email Description automatically generated

Die Allozierung ist riesig, da sie den gesamten Basisblock enthält.

Text Description automatically generated

Graphical user interface, text, application Description automatically generated

Also erstellen wir eine neue Struktur der Größe 0x7a00 und nennen sie BASE_BLOCK.

Graphical user interface, text, application Description automatically generated

Die ersten 70 Bytes entsprechen, wie wir bereits wussten, _CLFS_LOG_BLOCK_HEADER und die folgenden 0x1338 _CLFS_BASE_RECORD_HEADER.

Text Description automatically generated

Indem wir also den Anfang des Basisblocks mit dem Offset zum nächsten Datensatz (0x70) addieren, erhalten wir den _CLFS_BASE_RECORD_HEADER.

Application Description automatically generated with low confidence

Der _CLFS_BASE_RECORD_HEADER im Speicher.

Calendar Description automatically generated

Betrachtet man andere Methoden desselben CClfsBaseFilePersisted-Objekts, erhält man in CClfsBaseFilePersisted::AddContainer ebenfalls die Adresse von _CLFS_BASE_RECORD_HEADER mittels CClfsBaseFile::GetBaseLogRecord.

Text Description automatically generated

Als nächstes wird CClfsBaseFile::OffsetToAddr mit cbOffset aufgerufen, es erhält die Adresse von _CLFS_CONTAINER_CONTEXT und speichert cboffset im Array rgbcontainers, das sich am Offset 0x328 des _CLFS_BASE_RECORD_HEADER befindet.

Graphical user interface, application Description automatically generated

Die Funktion CClfsBaseFile::OffsetToAddr wird verwendet, um Strukturadressen aus Offsets zu ermitteln.

Graphical user interface, text, application Description automatically generated

An diesem Punkt ist der Container-Offset, der bei 0x328 gespeichert wird, noch 0, da wir noch keinen Container hinzugefügt haben.

Background pattern Description automatically generated with low confidence

Der PoC ruft CreateLogFile zweimal auf, das erste Mal mit der fehlerhaften Datei MyLog.blf und das zweite Mal mit der normalen Datei MyLogxxx.blf. Daher müssen wir das Debuggen an allen oben genannten Stellen zweimal anhalten und uns die Adressen der oben genannten Strukturen für beide Dateien im Editor notieren.

Text Description automatically generated

Spulen wir ein wenig vor zu CLFS!CClfsLogFcbPhysical::AllocContainer, indem wir dort einen Haltepunkt setzen und dorthin laufen.

Wenn AddLogContainer() im POC erreicht wird, stoppen wir am Haltepunkt.

A picture containing application Description automatically generated

Setzen wir auch einen Haltepunkt auf CClfsBaseFilePersisted::AddContainer+176, wo wir zuvor gesehen haben, dass der Offset und der Zeiger auf die _CLFS_CONTAINER_CONTEXT-Struktur gefunden werden.

A screenshot of a computer Description automatically generated with medium confidence

Graphical user interface, text, application Description automatically generated

Wenn der Debugger anhält, sehen wir, dass der Offset 0x1468 ist.

Text Description automatically generated

In RAX wird die Adresse der _CLFS_CONTAINER_CONTEXT-Struktur zurückgegeben.

Graphical user interface, text, application, table Description automatically generated

Die Struktur ist noch leer, da der Container noch nicht hinzugefügt wurde.

Text Description automatically generated

Beachten Sie, dass der Wert SignatureOffset=0x50, den wir bei Offset 0x868 in die fehlerhafte Datei geschrieben haben, nach Abzug der 0x800 vom Beginn des Basisblocks in der _CLFS_LOG_BLOCK_HEADER-Struktur bei Offset 0x68 zu finden ist.

Graphical user interface, text, application Description automatically generated

Text, letter Description automatically generated

Wenn der PoC die Funktion AddLogContainer() mit der fehlerhaften Datei aufruft, steht an Offset 0x68 von _CLFS_LOG_BLOCK_HEADER anstelle des dort geschriebenen Werts 0x50 aktuell 0xFFFF0050 im Speicher.

A picture containing text Description automatically generated

Irgendwann wurde dieser Wert vom Programm geändert. Um zu sehen, wann das passiert, setzen wir bei der nächsten Ausführung einen Speicher-Haltepunkt auf Schreiben.

Der Offset wird bei r15 + 0x328 gespeichert (r15 zeigt auf die _CLFS_BASE_RECORD_HEADER-Struktur).

Text Description automatically generated with medium confidence

Graphical user interface Description automatically generated with low confidence

RBX speichert den Offset 0x1468.

A picture containing calendar Description automatically generated

Also befindet sich an der Adresse Basisblock + 0x70 + dem ermittelten Offset 0x1468 die Adresse des CLFS_CONTAINER_CONTEXT-Containers.

Text Description automatically generated

In der CLFS_CONTAINER_CONTEXT-Struktur am Offset 0x18 wird der pContainer-Zeiger gespeichert. Wir können einen Haltepunkt auf Schreiben setzen und sehen, wann er geschrieben wird.

Text Description automatically generated

A picture containing text Description automatically generated

Dies ist der Zeiger, den wir korrumpieren müssen, da die Funktion, in der sich die Schwachstelle befindet, zuerst den CLFS_CONTAINER_CONTEXT liest, dann in r15 verschiebt und anschließend den Wert von r15+18 liest, also diesen Zeiger, für den wir gerade den Haltepunkt auf Schreiben gesetzt haben.

Graphical user interface, application, table Description automatically generated

Graphical user interface, application, Word Description automatically generated

Es speichert pContainer am Offset 0x1c0 der struct_CClfsBaseFilePersisted-Struktur.

Text, application, whiteboard Description automatically generated

Nach mehreren Unterbrechungen erreichen wir den Moment, in dem es korrumpiert wird. Die oberen Bytes der Zeigeradresse wurden von FFs auf Null geändert.

Calendar Description automatically generated

Dies geschieht, wenn der zweite AddLogContainer() der fehlerhaften Datei aufgerufen wird; der Zeiger des vorherigen MyLogxxx wird korrumpiert.

Das Problem tritt auf, weil der SignaturesOffset, der 0x50 sein sollte, jetzt 0xFFFF0050 ist, was einen Schreibzugriff außerhalb der Grenzen im folgenden memset ermöglicht.

Graphical user interface, text, application Description automatically generated

Graphical user interface, text Description automatically generated

Korrumpieren des „pContainer“-Zeigers:

Die Funktion memset() wird die darunterliegende _CLFS_CONTAINER_CONTEXT-Struktur korrumpieren; diese Struktur gehört zur MyLogxxx-Datei, da sie bei der Erstellung 0x11000 Bytes voneinander entfernt platziert wurden.

Auf diese Weise berechnet es genau, wo in die nächste Struktur geschrieben werden muss, und setzt die oberen Bytes des Zeigers auf Null, sodass er auf den User-Heap zeigt, wo der HeapSpray erstellt wurde.

Die Basisblockstruktur der fehlerhaften Datei liegt genau 0x11000 vor der der MyLogxxx-Datei.

Fehlerhaft:

Shape Description automatically generated

MyLogxxx

A picture containing text Description automatically generated

RCX ist kleiner als RDX, da 0xFFFF0050 hinzugefügt wurde, anstatt 0x50, wie es sein sollte.

Graphical user interface, text, application Description automatically generated

Und wir gelangen zur Funktion memset(), die 0xb0 Bytes mit Nullen füllt, wobei RCX auf die CLFS_CONTAINER_CONTEXT-Struktur der MyLogxxx-Datei zeigt, genauer gesagt auf die oberen fünf Bytes von pContainer.

Text Description automatically generated

Dieser Zeiger wird durch Überschreiben der ersten Bytes korrumpiert:

Text Description automatically generated

und zeigt so auf eine zuvor von uns durch HeapSpray kontrollierte Speicheradresse

Text Description automatically generated

A picture containing text Description automatically generated

Dann wird das Handle der MyLogxxx-Datei geschlossen, und es erreicht CClfsBaseFilePersisted::RemoveContainer; die Schwachstelle wird schließlich ausgelöst.

Text, application Description automatically generated with medium confidence

Erneute Betrachtung des Patches

Jetzt, da wir mehr Informationen haben, stellen wir fest, dass hier Base_Block.LOG_BLOCK_HEADER.SignaturesOffset und Base_Block..LOG_BLOCK_HEADER.TotalSectorCount gelesen werden.

Im ersten Teil des Patches darf SignaturesOffset nicht größer als 0x7a00 sein; bei uns war es ursprünglich 0x50, wenn es mit einem Wert größer als 0x7a00 ankäme, würde es uns rauswerfen.

A picture containing diagram Description automatically generated

Wenn der PoC auf der gepatchten Maschine ausgeführt wird, vergleicht es 0x50 mit 0x7a00, und da es kleiner ist, fährt es fort.

Text Description automatically generated

Im folgenden Block wird die fehlerhafte cbSymbolZone zum Wert der Endadresse von _CLFS_BASE_RECORD_HEADER addiert, und diese Summe wird in result_1 gespeichert.

Text Description automatically generated

Dann wird die Adresse des Base_Block mit dem SignatureOffset-Wert addiert, der in einer normalen Datei 0x7980 ist.

Text Description automatically generated

Die maximale Adresse des base_block ist 0x7a00, jetzt ist die SymbolZone bis zu 0x80 vor der Grenze erlaubt.

Es wird in result_2 gespeichert; das wäre die maximale Grenze für die SymbolZone innerhalb des Basisblocks. Dann vergleicht es beide Ergebnisse: wenn das erste größer als das zweite ist, bedeutet das, dass es außerhalb der Grenzen liegt.

Text Description automatically generated

Text Description automatically generated

Offensichtlich wird der erste Wert größer sein als der zweite, und es wird nicht fortfahren, da die erste Summe von cbSymbolZone + Endadresse des _CLFS_BASE_RECORD_HEADER die Grenze (also result_2) überschreitet und zu einem „out of bounds“ führt.

Graphical user interface, text, application Description automatically generated

Korrumpieren des SignatureOffset

Das Letzte, was wir herausfinden müssten, ist, wo der SignatureOffset-Wert von 0x50 zu 0xFFFF0050 wird.Also, fangen wir von vorne an, starten neu und stoppen bei CLFS!CClfsBaseFilePersisted::LoadContainerQ, wo der Wert im Speicher noch nicht geändert wurde und immer noch 0x50 beträgt.

Setzen Sie einen Zugriffs-Breakpoint beim Offset 0x68 in SignatureOffset.

Calendar Description automatically generated

Und nach mehreren Stopps erkennen wir den richtigen Moment, in dem der Wert geändert wird, in der ClfsEncodeBlockPrivate.

Graphical user interface, text Description automatically generated

Diese Funktion ist nicht gepatcht, also könnte es sich um ein Verhalten handeln, das durch den niedrigen Wert von 0x50 und die Manipulation der restlichen Werte verursacht wird.

Unter den manipulierten Werten sehen wir den ccoffsetArray-Wert, dessen Name in der __CLFS_BASE_RECORD_HEADER**-Struktur rgClients ist und das Array von Offsets darstellt, die auf das Client Context-Objekt zeigen.

Das rgClients-Feld befindet sich beim Offset 0x138 (0x9a8-0x800-0x70) der _CLFS_BASE_RECORD_HEADER**-Struktur.

Graphical user interface, table Description automatically generated

Text Description automatically generated with medium confidence

Im PoC ist dieser Wert fehlerhaft, sodass er auf ein gefälschtes Client-Context-Objekt namens FakeClientContext zeigt.

Text, whiteboard Description automatically generated

A screenshot of a computer Description automatically generated with medium confidence

Dies ist die Client Context-Struktur __CLFS_CLIENT_CONTEXT**

struct _CLFS_CLIENT_CONTEXT

{

CLFS_NODE_ID cidNode;

CLFS_CLIENT_ID cidClient;

USHORT fAttributes;

ULONG cbFlushThreshold;

ULONG cShadowSectors;

ULONGLONG cbUndoCommitment;

LARGE_INTEGER llCreateTime;

LARGE_INTEGER llAccessTime;

LARGE_INTEGER llWriteTime;

CLFS_LSN lsnOwnerPage;

CLFS_LSN lsnArchiveTail;

CLFS_LSN lsnBase;

CLFS_LSN lsnLast;

CLFS_LSN lsnRestart;

CLFS_LSN lsnPhysicalBase;

CLFS_LSN lsnUnused1;

CLFS_LSN lsnUnused2;

CLFS_LOG_STATE eState;

union

{

HANDLE hSecurityContext;

ULONGLONG ullAlignment;

};

};

Der eState-Wert befindet sich beim Offset 0x78 vom Anfang der Struktur, in der manipulierten Datei bei 0x23a0+0x78.

Text Description automatically generated with medium confidence

Chart, scatter chart Description automatically generated

Dieser Wert zeigt den Status des Protokolls.

typedef UCHAR CLFS_LOG_STATE, *PCLFS_LOG_STATE;
const CLFS_LOG_STATE CLFS_LOG_UNINITIALIZED = 0x01;
const CLFS_LOG_STATE CLFS_LOG_INITIALIZED = 0x02;
const CLFS_LOG_STATE CLFS_LOG_ACTIVE = 0x04;
const CLFS_LOG_STATE CLFS_LOG_PENDING_DELETE = 0x08;
const CLFS_LOG_STATE CLFS_LOG_PENDING_ARCHIVE = 0x10;
const CLFS_LOG_STATE CLFS_LOG_SHUTDOWN = 0x20;
const CLFS_LOG_STATE CLFS_LOG_MULTIPLEXED = 0x40;
const CLFS_LOG_STATE CLFS_LOG_SECURE = 0x80;

dieser Wert ist auf CLFS_LOG_STATE CLFS_LOG_SHUTDOWN = 0x20 gesetzt.

Der andere fehlerhafte Wert ist fAttributes, der dem Satz von FILE_ATTRIBUTE-Flags entspricht, die mit der Basis-Protokolldatei verknüpft sind (wie System und Versteckt).

Graphical user interface Description automatically generated with low confidence

Text, letter Description automatically generated

Da das Feld ein Byte früher bei 0xa beginnt und sich über zwei Bytes erstreckt, ist der Wert von fAttributes 0x100.

A picture containing table Description automatically generated

Graphical user interface, text, application Description automatically generated

Schließlich gibt es den blocknameoffset-Wert, der auf den Offset 0x1bb8 zeigt; ich meine, durch Addition von 0x78 und 0x800 zeigt er auf den Offset 0x2428 der Datei.

Text Description automatically generated

Text, letter Description automatically generated

Beachten Sie, dass der Offset zum Client Context 0x1b30 beträgt.

Table Description automatically generated

Der Client Context befindet sich also beim Offset 0x23a0.

Text Description automatically generated with medium confidence

Table Description automatically generated

Und nur 0x10 davor befindet sich der Wert, der blocknameoffset entspricht.

Text, letter Description automatically generated

Table Description automatically generated with low confidence

Welcher auf den String mit dem Namen zeigen würde.

Der letzte Wert ist der blockattributeoffset, der 0xC vor dem Client Context bei 0x2394 liegt.

Table Description automatically generated

Diese letzten beiden Werte gehören zu einer Struktur, die dem Client Context mit einer Länge von 0x30 Bytes vorausgeht, genannt _CLFSHASHSYM.

typedef struct _CLFSHASHSYM
{
CLFS_NODE_ID cidNode;
ULONG ulHash;
ULONG cbHash;
ULONGLONG ulBelow;
ULONGLONG ulAbove;
LONG cbSymName;
LONG cbOffset;
BOOLEAN fDeleted;
} CLFSHASHSYM, *PCLFSHASHSYM;

A picture containing diagram Description automatically generated

Text Description automatically generated

Sie befinden sich bei 0x20 und 0x24 Bytes vom Anfang der _CLFSHASHSYM-Struktur, also ist in der _CLFSHASHSYM-Struktur der Wert namens blockNameOffset im PoC das cbSymName-Feld und der blockAttributteoffset ist das cbOffset-Feld.

A picture containing text Description automatically generated

Text Description automatically generated with medium confidence

Das sind die manipulierten Werte; jetzt müssen wir sehen, wie sie unseren SignaturesOffset von 0x50 auf 0xFFFF0050 ändern.

Werfen wir einen Blick auf die Funktion CClfsBaseFile::AcquireClientContext(), die den Client-Kontext zurückgeben sollte.

Graphical user interface, text, application, email Description automatically generated

Sie ruft CClfsBaseFile::GetSymbol mit dem vierten Argument auf, das __CLFS_CLIENT_CONTEXT **** sein wird, wo der Zeiger auf den Client Context gespeichert wird.

Graphical user interface, text, application Description automatically generated

Innerhalb der Funktion CClfsBaseFile::GetSymbol übergeben wir den manipulierten ccoffsetArray-Offset an CClfsBaseFile::OffsetToAddr und erhalten die Adresse des Client-Kontexts. Setzen wir dort einen Breakpoint, sodass er anhält, wenn die mit CreatelogFile erstellte Datei aufgerufen wird.

Graphical user interface, application Description automatically generated with medium confidence

Dort wird mit dem manipulierten ccoffsetArray-Argument angehalten.

Graphical user interface, application Description automatically generated

Table Description automatically generated

Die Funktion CClfsBaseFile::OffsetToAddr gibt den falschen Client Context zurück.

A picture containing graphical user interface Description automatically generated

Und prüft, dass der Wert von cbOffset nicht Null ist, da sich 0xC vor der _CLFS_CLIENT_CONTEXT-Struktur befindet, die sich in RAX befindet.

A screenshot of a computer Description automatically generated

A picture containing text Description automatically generated

Dann vergleicht es cbOffset mit dem ccoffsetArray (der sich in RSI befindet), sie müssen gleich sein, sonst erhalten wir einen Fehler.

A screenshot of a computer Description automatically generated

Es prüft auch, dass cbSymName gleich cbOffset+0x88 ist, andernfalls erhalten wir ebenfalls einen Fehler.

Graphical user interface, text, application Description automatically generated with medium confidence

Und schließlich vergleicht es das cidClient-Byte mit Null.

A picture containing diagram Description automatically generated

Wenn all diese Prüfungen erfolgreich sind, wird der Client Context gespeichert.

A screenshot of a computer Description automatically generated

Die Ausgabe der Funktion r14 zeigt auf den Client Context.

Graphical user interface, text, application Description automatically generated

Beim Verlassen von CClfsLogFcbPhysical::Initialize haben wir die Adresse von CLFS_CLIENT_CONTEXT.

Text Description automatically generated

Jetzt liest es den Wert von fAttributes (0x100).

Graphical user interface, text, application Description automatically generated

Diese Funktion gehört zur Klasse CClfsLogFcbPhysical.

Text Description automatically generated

Graphical user interface, text, application Description automatically generated

Die hier zugewiesen wurde und deren Größe 0x15d0 und deren Tag „ClfC“ ist.

Text Description automatically generated with medium confidence

Lassen Sie uns eine Struktur erstellen, um das zu speichern, was wir reversen; nennen wir sie: struct_CClfsLogFcbPhysical.

A picture containing table Description automatically generated

Beachten Sie, dass bei 0x2b0 die Adresse der CClfsBaseFilePersisted-Struktur gespeichert wird.

A picture containing application Description automatically generated

Nachdem viele Werte in der Struktur gespeichert wurden, gelangt es zu einem wichtigen Teil: Es testet eState mit 0x20.

Graphical user interface, text, application Description automatically generated

Graphical user interface, text, application, table Description automatically generated

Da der manipulierte Wert 0x20 war, gibt der Test 1 zurück.

Table Description automatically generated

Graphical user interface, text, application Description automatically generated

Wir sehen, dass im Konstruktor in der vtable ist.

Text Description automatically generated

Es wird prüfen, ob die Datei multiplexed ist.

Graphical user interface, application Description automatically generated

Es geht also den gewünschten Weg und erreicht CClfsLogFcbPhysical::ResetLog.

Graphical user interface, application Description automatically generated

Text, application, table Description automatically generated with medium confidence

Mehrere Felder werden auf Null initialisiert, mit Ausnahme eines, das auf 0xFFFFFFFF00000000 initialisiert wird.

Graphical user interface Description automatically generated with low confidence

Hier holt es den Client Context.

Graphical user interface, application Description automatically generated with medium confidence

Es speichert den Wert 0xFFFFFFFF00000000.

Graphical user interface, application Description automatically generated

Graphical user interface, application Description automatically generated

A picture containing calendar Description automatically generated

Es schreibt 0xFFFFFFFF an Offset 0x5c, was der höhere Teil von CLFS_LSN lsnRestart.ullOffset ist.

Table Description automatically generated

Text Description automatically generated with medium confidence

Graphical user interface, text, letter Description automatically generated

Jetzt führen wir die Funktion ClfsEncodeBlockPrivate() aus, die, wie wir zuvor gesehen haben, dafür verantwortlich ist, die 0x50 mit 0xFFFF0050 zu überschreiben.

Dort liest es den Wert von SignatureOffset = 0x50, der noch so ist, wie wir ihn in der manipulierten Datei gesetzt haben, und addiert ihn zum Start von CLFS_LOG_BLOCK_HEADER.

Text Description automatically generated

Dies ist eine Schleife, die 2 Bytes schreibt. Da der SignatureOffset statt auf einen korrekten Wert, der in einer normalen Datei ein hoher Wert ist, z.B. 0x3f8, wodurch weiter vorne geschrieben wird, hier im selben CLFS_LOG_BLOCK_HEADER schreibt.

Die Idee ist, das Schreibziel zu ändern, um zu versuchen, den SignatureOffset-Wert zu korrumpieren.

Normale Datei

Table Description automatically generated

An diesem Punkt beginnt es zu loopen und zwei Bytes zu schreiben.

Graphical user interface, application Description automatically generated

Der Zähler muss den Wert 0x3d erreichen, um die Schleife zu verlassen.

Graphical user interface, application Description automatically generated

RCX erhöht sich ab 0x200, wir sind bereits im dritten Zyklus und sein Wert ist 0x600.

Graphical user interface, text, application Description automatically generated

In der Iteration 0xe ist RCX 0x1a00.

Graphical user interface, text Description automatically generated

A picture containing calendar Description automatically generated

Das war, wo er die 0xFFFFFFFF000000 geschrieben hatte.

Graphical user interface, text, application Description automatically generated

Table Description automatically generated with medium confidence

Es liest die letzten zwei Bytes FFFF.

Text Description automatically generated

Und es kopiert sie dann in R8.

A picture containing calendar Description automatically generated

A picture containing calendar Description automatically generated

Wie wir gesehen haben, ist dieser Wert kritisch, da er es ermöglicht, die Prüfung zu umgehen und außerhalb der Grenzen zu schreiben, um den pContainer-Zeiger der Datei zu korrumpieren, die dem memset() folgt, und Nullen oben zu schreiben und ihn auf unseren kontrollierten Speicher (HeapSpray) zeigen zu lassen.

In CClfsBaseFilePersisted::AllocSymbol wird die gleiche Summe, die das Ziel des memset ermittelt, also cbSymbolZone + Endadresse von CLFS_BASE_RECORD_HEADER, mit Base_block + 0xFFFF0050 verglichen, sodass auf beiden Seiten der Gleichung korrumpierte Werte vorliegen.

CbSymbolZone = 0x1114B

Es ist der manipulierte Wert, der zur Endadresse von CLFS_BASE_RECORD_HEADER addiert wird, wodurch er außerhalb der Grenzen schreibt, und das andere Element des Vergleichs, das die Adresse des Base Block + SignatureOffset sein sollte, bleibt SignatureOffset = 0xFFFF0050, was es dieser Prüfung ermöglicht, zu bestehen und außerhalb der Grenzen im memset() zu schreiben und die Spitze des Zeigers zu nullen, der auf unseren HeapSpray zeigen wird.

Graphical user interface, application, table Description automatically generated

Da RCX kleiner als RDX ist.

Graphical user interface, application Description automatically generated

Wie wir zuvor gesehen haben. (Werte können abweichen, da sie zu einer vorherigen Ausführung gehören.)

Es wird den Zeiger korrumpieren, indem es die höchsten Bytes auf 0 setzt.

Table Description automatically generated

Dadurch zeigt er auf einen Speicherbereich, den wir durch HeapSpray kontrollieren.

A screenshot of a computer Description automatically generated with low confidence

Table Description automatically generated

Wenn die Sicherheitslücke ausgelöst wird, gelangen wir zu CClfsBaseFilePersisted::RemoveContainer.

A picture containing graphical user interface Description automatically generated

Dort befindet sich der bereits korrumpierte Zeiger und er kann, wie wir zuvor gesehen haben, ausgenutzt werden.

Graphical user interface, application Description automatically generated

An diesem Punkt haben wir den Bug ausgenutzt; er führt zur Kontrolle der Funktionen, die das Lesen des SYSTEM-Tokens und das Schreiben in unseren eigenen Prozess ermöglichen, um die lokale Privilegienausweitung zu erreichen.

Wir hoffen, dass es nützlich ist. Bei Fragen können Sie uns unter [email protected] und [email protected] kontaktieren.

Viel Spaß!

Tool herunterladen