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-2026-29923 — Proof-of-Concept-Exploit für CVE-2026-29923, eine BYOVD-Privilegieneskalation in pstrip64.sys. Demonstriert physikalisches Speicher-Lesen/Schreiben über IOCTL, um das SYSTEM-Token zu stehlen und eine erhöhte Shell zu starten. | Kitploit
Tools/GitHubGitHub/athenasec16/cve-2026-29923
Privilege EscalationSchwachstellenanalyseExploitationLernen & BildungBinary-ExploitationLabs & Praxis
GitHubathenasec16/cve-2026-29923

CVE-2026-29923

Proof-of-Concept-Exploit für CVE-2026-29923, eine BYOVD-Privilegieneskalation in pstrip64.sys. Demonstriert physikalisches Speicher-Lesen/Schreiben über IOCTL, um das SYSTEM-Token zu stehlen und eine erhöhte Shell zu starten.

Repository anzeigen
253vor 4 MonatenVon 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-2026-29923 - Lokaler Privilegieneskalationsangriff über pstrip64.sys

Haftungsausschluss: Dieser Code dient ausschließlich Bildungs- und Abwehrforschungszwecken. Er wurde entwickelt, um das Verständnis von Kernel-Ausnutzung zu fördern und Verteidigern zu helfen, sich vor ähnlichen Schwachstellen zu schützen. Jegliche unbefugte, illegale oder böswillige Nutzung dieses Projekts ist strengstens untersagt.


Beschreibung

Hash: ab01485bb7c8bc1a9c86096eeea6d31d8fad557bf4d44072b46373d2203faa6e

Treibername: pstrip64.sys

CVE: CVE-2026-29923

Ein "Bring Your Own Vulnerable Driver" (BYOVD)-Angriff ist eine alte, aber hochwirksame Methode für Angreifer, moderne Windows-Sicherheitsmechanismen zu umgehen, indem sie einen Legacy-Treiber verwenden, dem das Betriebssystem noch offiziell vertraut. Sobald der Treiber geladen ist, nutzt der Angreifer seine Schwachstellen aus, um die Lücke zwischen einem standardmäßigen, nicht privilegierten Prozess und vollständiger Systemkontrolle zu schließen.

Anfang dieser Woche wurde eine neue Schwachstelle im pstrip64.sys-Treiber unter der Bezeichnung CVE-2026-29923 offengelegt. Dieser Blogbeitrag beschreibt den gesamten Lebenszyklus des Exploits: von meiner ersten Schwachstellenforschung und der Entwicklung des Proof of Concept (PoC) bis hin zu umsetzbaren Abwehrstrategien für Verteidiger, die ihre Umgebungen sichern.

Der pstrip64.sys-Treiber ist eine Legacy-Kernelmodul-Komponente, die mit EnTech Taiwan PowerStrip (bis Version 3.90.736) verbunden ist. Obwohl sein legitimer Zweck darin besteht, erweiterte Grafikkarten-Display-Anpassungen zu ermöglichen, machen seine tiefen Systemprivilegien ihn zu einem hochattraktiven Ziel für Angreifer.


Die Schwachstelle

Als die Schwachstelle erstmals offengelegt wurde, begann ich mit der Analyse ihrer DriverEntry-Funktion. Diese dient als Hauptinitialisierungsroutine für den Kernel-Treiber, erstellt das Geräteobjekt \Device\PSTRIP64 und stellt es Benutzermodusanwendungen über den symbolischen Link \DosDevices\PSTRIP64 zur Verfügung. Noch wichtiger ist, dass sie die Dispatch-Tabelle des Treibers konfiguriert. Der Eintrag, der mir sofort ins Auge fiel, war Index 14 (IRP_MJ_DEVICE_CONTROL), der alle benutzergesteuerten IOCTL-Anfragen direkt an die Handler-Funktion sub_11340 weiterleitet – unser primäres Interessensgebiet.

IDA DriverEntry

Die Funktion sub_11340 dient als primärer IOCTL-Dispatcher, der Anfragen aus dem Benutzermodus interpretiert.

Von allen verfügbaren IOCTLs ist 0x80002008 zweifellos der interessanteste. Während die Standardfälle kleinere I/O-Port-Interaktionen behandeln, fungiert 0x80002008 als Tor zu sub_11000, indem es den SystemBuffer direkt an diese Funktion übergibt.

IDA ioctl

Diese Routine sub_11000 ist der entscheidende Beweis. Zunächst verwendet sie HalTranslateBusAddress, um unsere benutzergesteuerte Adresse in eine gültige System-Physikalische-Adresse zu übersetzen. Dann öffnet sie \Device\PhysicalMemory und bildet es mit ZwMapViewOfSection ab. Durch die Hartcodierung des Zielprozess-Handles auf (HANDLE)0xFFFFFFFFFFFFFFFFLL (was ZwCurrentProcess() darstellt) bildet der Treiber diesen physischen Speicher direkt in den virtuellen Adressraum unseres aufrufenden Prozesses ab. Entscheidend ist, dass er diese neu abgebildete virtuelle Adresse dann zurück in den SystemBuffer schreibt, um sie an den Benutzer zurückzugeben – und so unserer Anwendung offiziell einen direkten Zeiger zum Lesen und Schreiben von physischem Speicher übergibt.

IDA MapViewofSection

Nachdem die Schwachstelle vollständig verstanden und eine physische Lese-/Schreib-Primitive etabliert ist, habe ich alle benötigten Puzzleteile. Jetzt ist es Zeit, mit dem Schreiben des Proof of Concept zu beginnen.


Der Proof of Concept (PoC)

Hinweis: Dieser PoC wurde speziell in einer Windows 10 22H2-Umgebung entwickelt und getestet. Da der Exploit auf der Manipulation von rohem physischem Speicher beruht, sind die Kernel-Struktur-Offsets und physischen Speichergrenzen derzeit für mein Setup fest codiert. Um dies auf Ihrem eigenen Rechner zu testen, müssen Sie die Windows-Kernel-Offsets aktualisieren und die physischen Adress-Scanbereiche an Ihre spezifische OS-Build- und RAM-Konfiguration anpassen.

Der erste Schritt in meinem Exploit ist die Kommunikation mit dem Treiber. Dies tat ich durch Aufruf von CreateFileA auf dem symbolischen Link des Treibers (\\.\PSTRIP64). Sobald ich ein gültiges Handle hatte, brauchte ich eine saubere Möglichkeit, den zuvor analysierten IOCTL 0x80002008 zu missbrauchen. Ich erstellte eine Wrapper-Funktion namens MapPhysicalMemory(). Diese Funktion befüllt meine benutzerdefinierte Struktur PSTRIP_MAP_REQUEST mit der Ziel-Physikalischen-Adresse und der Länge des Speicherblocks, den ich lesen möchte.

Ich sende diese Struktur dann über DeviceIoControl direkt an den Treiber. Im Erfolgsfall bildet der Treiber diesen physischen Speicher direkt in meine Benutzermodusanwendung ab und gibt die virtuelle Basisadresse im Feld OutputResult zurück. Ich kann diese zurückgegebene Adresse nun in einen standardmäßigen C++-Zeiger umwandeln, was mir rohen, nicht privilegierten Zugriff auf den physischen RAM des Systems verschafft.

Mit meiner voll funktionsfähigen physischen Lese-/Schreib-Primitive war mein Ziel, die Kernel-Datenstrukturen zu finden, die Prozessprivilegien enthalten. In Windows wird jeder laufende Prozess durch eine EPROCESS-Struktur dargestellt.

Windows weist EPROCESS-Strukturen im Kernel-Pool mit einem spezifischen 4-Byte-Identifier namens Pool-Tag zu. Für Prozesse ist dieses Tag der String Proc (was hexadezimal 0x636F7250 entspricht). Durch das Scannen des physischen RAMs des Systems konnte ich nach genau diesem String suchen.

Mein Exploit durchläuft den physischen Adressraum von 0x10000000 bis 0x140000000 und bildet Speicher in 2MB-Blöcken (STEP_SIZE = 0x200000) ab. Ich wandle jeden abgebildeten Block in ein rohes Byte-Array um und durchsuche ihn in 16-Byte-Schritten (sizeof(_POOL_HEADER)).

Allerdings reicht es nicht aus, einfach das Proc-Tag im physischen Speicher zu finden. Speicher ist unordentlich – dieses Tag könnte ein Überbleibsel eines beendeten Prozesses oder nur zufällige Daten sein, die zufällig dem Hex-Wert entsprechen. Wenn ich blind annehmen würde, dass jedes Proc-Tag eine gültige EPROCESS-Struktur ist, und Speicher modifizieren würde, würde ich sofort einen BSOD verursachen.

Um Stabilität zu gewährleisten, musste ich die Struktur mit Heuristiken validieren. Zuerst berechne ich den Start der EPROCESS-Struktur (die ein wenig vom Pool-Tag versetzt ist). Von dort aus überprüfe ich einige bekannte Konstanten für einen laufenden Prozess:

  • PriorityClass: Ich überprüfe, ob dieser Wert 0x2 (Normale Priorität) ist.
  • ProcessLock: Ich stelle sicher, dass dieser Wert 0x0 ist.
  • ImageFileName: Ich überprüfe, ob das erste Zeichen des Prozessnamens ein gültiges, druckbares ASCII-Zeichen ist.

Wenn alle diese Heuristiken bestanden werden, kann ich ziemlich sicher sein, dass ich einen gültigen, aktiven Prozess betrachte. Ich lese dann seine eindeutige Prozess-ID (PID). Wenn die PID mit meinem eigenen Exploit-Prozess übereinstimmt, speichere ich die physische Adresse seines Token-Zeigers. Wenn die PID 4 ist (der Windows System-Prozess), extrahiere und speichere ich den tatsächlichen Wert seines hochprivilegierten Tokens.

Schließlich richte ich die gespeicherte physische Adresse meines Prozess-Token-Zeigers auf die nächste 4KB-Grenze aus und verwende MapPhysicalMemory() ein letztes Mal, um genau diese Seite abzubilden.

Als Nächstes navigiere ich zum exakten Offset und überschreibe mein Token mit dem System-Token-Wert. Sofort behandelt der Windows-Kernel meinen Exploit-Prozess als NT AUTHORITY\SYSTEM.

Nachdem ich die Seite zur Sicherstellung der Systemstabilität wieder abgebildet habe, rufe ich einfach CreateProcessA auf, um cmd.exe zu starten. Da mein aktueller Prozess erhöht ist, erbt die neue Eingabeaufforderung diese höchsten Privilegien – der Angriff ist erfolgreich abgeschlossen!


Anmerkungen

Hinweis: Ein kritisches Detail, das ich während meiner frühen Debugging-Phase entdeckte, ist die Art und Weise, wie der Treiber den abgebildeten Zeiger behandelt. Indem er SystemBuffer->LowPart = (unsigned int)BaseAddress; ausführt, wandelt der Treiber die 64-Bit-virtuelle Basisadresse in einen 32-Bit-Wert um, bevor er ihn zurückgibt. Diese Kürzung verliert die höheren Bits der Adresse, was zu sofortigen Zugriffsverletzungen führte, als ich versuchte, sie in meinem 64-Bit-Exploit zu dereferenzieren. Um dieses Problem sauber zu umgehen, habe ich meinen Benutzermodus-PoC einfach als 32-Bit-Anwendung kompiliert, sodass der zurückgegebene Zeiger perfekt gültig blieb.

IDA MapViewofSection - Kopie

Hinweis: Während meiner ersten Tests stieß ich auf einen faszinierenden Grenzfall: Mein PoC fand meinen Exploit-Prozess erfolgreich im Speicher, aber er konnte den System-Prozess (PID 4) nicht finden.

Um zu verstehen, warum, musste ich den physischen Speicher direkt inspizieren. Ich habe einen Kernel-Debugger (WinDbg) angehängt und Befehle verwendet, um die virtuelle Adresse und die Verzeichnisbasis des System-Prozesses abzurufen. Dann habe ich !vtop verwendet, um diese virtuelle Adresse in ihre exakte physische Adresse im RAM zu übersetzen.

windbg kernel debugger system physische adresse windbg kernel debugger db system adresse

Ich wechselte zurück zu meinem Benutzermodus-Debugger, der an meinem PoC angehängt war. Ich setzte einen bedingten Breakpoint in meiner Speicher-Scan-Schleife und wies ihn an, die Ausführung anzuhalten, sobald meine MapPhysicalMemory()-Funktion den 2MB-Chunk greift, der die physische Adresse des System-Prozesses enthält.

windbg breakpoint

Sobald der Breakpoint getroffen wurde, begann ich, die rohen Bytes des abgebildeten Speichers manuell zu inspizieren. Hier entdeckte ich ein entscheidendes Detail über Windows-Kernel-Pool-Zuweisungen.

windbg eprocessBase offset 88000

Wenn Windows Speicher für einen Prozess zuweist, beginnt es mit einem _POOL_HEADER (das unser Proc-Tag enthält), gefolgt von einem _OBJECT_HEADER und schließlich der EPROCESS-Struktur selbst. Bei standardmäßigen Benutzermodus-Anwendungen enthalten diese Header zusätzliche Tracking-Daten, sodass die eigentliche EPROCESS-Struktur 0x80 Bytes nach dem Pool-Tag beginnt.

offset für benutzermodus prozess

Die Inspektion des Speichers des System-Prozesses zeigte jedoch ein anderes Layout. Dem System-Prozess fehlen einige dieser standardmäßigen Tracking-Header. Der Offset vom Proc-Tag zum Start der EPROCESS-Struktur betrug nur 0x40 Bytes!

windbg db 88000 offset windbg db 88000 - 0x40 offset offset für system prozess

Die Lösung war einfach. Ich aktualisierte meinen PoC, um beide Pool-Header-Größen zu handhaben, indem ich ein Array möglicher Offsets (0x40 und 0x80) durchlaufe, wann immer er ein Proc-Tag findet.

möglicheoffsets

Abwehr & Erkennung

Cybersicherheit ist ein endloses Katz-und-Maus-Spiel zwischen Angreifern und Verteidigern. Während Angreifer ständig nach anfälligen Treibern suchen, haben moderne Sicherheitsprodukte und blaue Teams mehrere robuste Möglichkeiten, diesen genauen Vorgang zu erkennen und zu blockieren.

Der effektivste Weg, einen BYOVD-Angriff zu stoppen, ist, das Laden des Treibers von vornherein zu verhindern.

  • Verteidiger sollten sicherstellen, dass der Hash von pstrip64.sys zu ihren Blocklisten hinzugefügt wird.
  • Darüber hinaus sollten Organisationen die Microsoft Vulnerable Driver Blocklist über Windows Defender Application Control (WDAC) durchsetzen und Hypervisor-Protected Code Integrity (HVCI) aktivieren, um streng zu begrenzen, welche Kernel-Komponenten geladen werden können.
  • Überwachen Sie auf neue Dienst-Erstellungsereignisse und achten Sie auf unerwartete Installationen von Kernel-Modus-Treibern.

Wenn der Treiber bereits geladen ist, können Sicherheitsprodukte den Exploit während der Token-Manipulationsphase dennoch erkennen.

  • Fortgeschrittene Überwachung auf Anomalien in Prozess-Tokens. Ein standardmäßiger Benutzermodus-Prozess, der sein anfängliches primäres Token auf NT AUTHORITY\SYSTEM erhöht, ohne eine legitime Authentifizierungskette, ist ein massives Alarmzeichen.
  • Zusätzlich können Sicherheitsteams Regeln erstellen, um zu erkennen, wenn ein Prozess mit niedriger oder mittlerer Integrität einen hochprivilegierten Kindprozess (wie cmd.exe) startet, insbesondere wenn der übergeordnete Prozess nichts mit SYSTEM zu tun hat.

Demo

poc_demo

Tool herunterladen