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-2025-21298 — Proof of Concept & Details für CVE-2025-21298 | Kitploit
Tools/GitHubGitHub/ynwarcs/cve-2025-21298
SpeicherforensikSchwachstellenanalyseExploitationReverse EngineeringBinäranalyse
GitHubynwarcs/cve-2025-21298

CVE-2025-21298

Proof of Concept & Details für CVE-2025-21298

Repository anzeigen
197492vor 1 JahrVon 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

Inhalt

Dies ist ein Proof-of-Concept für CVE-2025-21298 - Windows OLE Remote Code Execution Vulnerability (CVSS 9.8). Es handelt sich um einen Memory-Corruption-PoC, nicht um einen Exploit.

Vollständiger Patch-Diff via ghidriff: LINK

Schwachstelle

Die Schwachstelle befindet sich in ole32.dll!UtOlePresStmToContentsStm. Der Zweck der Funktion ist es, Daten in einem "OlePres"-Stream innerhalb eines OLE-Speichers in angemessen formatierte Daten umzuwandeln und sie in den "CONTENTS"-Stream im selben Speicher einzufügen. Sie erhält einen IStorage-Pointer auf ein Speicherobjekt und drei eher unwichtige Argumente.

Unten sehen wir die Implementierung der Funktion mit einem Diff vom Januar 2025 Patch:

root@kitploit:~
__int64 __fastcall UtOlePresStmToContentsStm(IStorage *pstg, wchar_t *puiStatus, __int64 a3, unsigned int *lpszPresStm)
{
  struct IStorageVtbl *lpVtbl; // rax
  int v7; // r14d
+ bool IsEnabled; // al
  IStream *v10; // rcx
  bool v11; // zf
  struct IStorageVtbl *v12; // rax
  int v13; // ebx
  HRESULT v14; // eax
  const wchar_t *v15; // rdx
  IStream *pstmContents; // [rsp+40h] [rbp-19h] BYREF
  IStream *pstmOlePres; // [rsp+48h] [rbp-11h] BYREF
  tagFORMATETC foretc; // [rsp+50h] [rbp-9h] BYREF
  tagHDIBFILEHDR hdfh; // [rsp+70h] [rbp+17h] BYREF

  *lpszPresStm = 0;
  lpVtbl = pstg->lpVtbl;
  pstmContents = 0LL;
  v7 = 1;
  // Create a "CONTENTS" stream in the storage and store it into pstmContents
  if ( (lpVtbl->CreateStream)(pstg, L"CONTENTS", 18LL, 0LL, 0, &pstmContents) )
    return 0LL;
  // Immediately release pstmContents, we're not going to be using it right now
  (pstmContents->lpVtbl->Release)(pstmContents);
+ IsEnabled = wil::details::FeatureImpl<__WilFeatureTraits_Feature_3047977275>::__private_IsEnabled(&`wil::Feature<__WilFeatureTraits_Feature_3047977275>::GetImpl'::`2'::impl);
+ v10 = pstmContents;
+ v11 = !IsEnabled;
  v12 = pstg->lpVtbl;
+ if ( !v11 )
+   v10 = 0LL;
+ pstmContents = v10;
  (v12->DestroyElement)(pstg, L"CONTENTS");
  v13 = (pstg->lpVtbl->OpenStream)(pstg, &OlePres, 0LL, 16LL, 0, &pstmOlePres);// 2nd option to fail -> no OlePres stream
  if ( v13 )
  {
    *lpszPresStm |= 1u;
    if ( (pstg->lpVtbl->OpenStream)(pstg, L"CONTENTS", 0LL, 16LL, 0, &pstmContents) )
    {
      *lpszPresStm |= 2u;
    }
    else
    {
      (pstmContents->lpVtbl->Release)(pstmContents);
+     wil::details::FeatureImpl<__WilFeatureTraits_Feature_3047977275>::__private_IsEnabled(&`wil::Feature<__WilFeatureTraits_Feature_3047977275>::GetImpl'::`2'::impl);
    }
    return v13;
  }
  foretc.ptd = 0LL;
  v13 = UtReadOlePresStmHeader(pstmOlePres, &foretc, 0LL, 0LL);
  if ( v13 >= 0 )
  {
    v13 = (pstmOlePres->lpVtbl->Read)(pstmOlePres, &hdfh, 16LL);
    if ( v13 >= 0 )
    {
      v13 = OpenOrCreateStream(pstg, L"CONTENTS", &pstmContents);
      if ( v13 < 0 )
      {
        *lpszPresStm |= 2u;
        goto $errRtn_197;
      }
      if ( foretc.dwAspect == 4 )
      {
        *lpszPresStm |= 4u;
        v7 = 0;
        v13 = 0;
        goto $errRtn_197;
      }
      if ( foretc.cfFormat == 8 )
      {
        v14 = UtDIBStmToDIBFileStm(pstmOlePres, hdfh.dwSize, pstmContents);
LABEL_19:
        v13 = v14;
        goto $errRtn_197;
      }
      if ( foretc.cfFormat == 3 )
      {
        v14 = UtMFStmToPlaceableMFStm(pstmOlePres, hdfh.dwSize, hdfh.dwWidth, hdfh.dwHeight, pstmContents);
        goto LABEL_19;
      }
      v13 = -2147221398;
    }
  }
$errRtn_197:
  if ( pstmOlePres )
    (pstmOlePres->lpVtbl->Release)(pstmOlePres);
  // Release pstmContents if it still exists, we need to clean up
  if ( pstmContents )
    (pstmContents->lpVtbl->Release)(pstmContents);
  if ( foretc.ptd )
    CoTaskMemFree(foretc.ptd);
  if ( v13 )
  {
    v15 = L"CONTENTS";
    goto LABEL_31;
  }
  if ( v7 )
  {
    v15 = &OlePres;
LABEL_31:
    (pstg->lpVtbl->DestroyElement)(pstg, v15);
  }
  return v13;
}

Das Problem liegt in der Variable pstmContents. Zunächst wird sie verwendet, um den Pointer auf das "CONTENTS"-Stream-Objekt zu speichern, das zu Beginn der Funktion erstellt wird. Der Stream wird unmittelbar nach der Erstellung zerstört und der in pstmContents gespeicherte Pointer wird freigegeben (was ihn in coml2.dll!ExposedStream::~ExposedStream freigibt). Allerdings enthält die Variable immer noch den freigegebenen Pointer. Weiter unten in der Funktion kann die Variable erneut verwendet werden, um den Pointer auf den "CONTENTS"-Stream zu speichern – aus diesem Grund gibt es am Ende der Funktion einen Aufräumcode, der den Pointer freigibt, falls er in der Variable gespeichert ist. Der Code berücksichtigt nicht die Tatsache, dass UtReadOlePresStmHeader fehlschlagen kann – wenn das passiert, zeigt pstmContents immer noch auf den freigegebenen Pointer und wir gelangen in den Aufräumcode, der den Pointer erneut freigibt. Somit kommt es zu einer Double-Free-Situation.

Wie im Patch-Diff zu sehen ist, hat Microsoft das Problem behoben, indem pstmContents auf Null gesetzt wird, nachdem der darin enthaltene Pointer initial freigegeben wurde.

Reproduktion

Im Repository befindet sich eine RTF-Datei, die die Schwachstelle reproduziert. Ich habe es getestet, indem ich die Datei in MS Word geöffnet habe, aber Sie können es auch mit anderen Anwendungen testen, die RTF-Daten parsen (z.B. Outlook). Eine Ausnutzung durch andere Formate, die OLE-Objekte einbetten, ist möglicherweise möglich, habe ich nicht getestet.

Video:

poc.webm

Details

Details werde ich später veröffentlichen.

Tool herunterladen