Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2025-21298 — ثغرة حرجة في Windows OLE بدون نقرة. هذا إثبات مفهوم لـ CVE-2025-21298 - ثغرة تنفيذ التعليمات البرمجية عن بُعد في Windows OLE (CVSS 9.8). هذا PoC لفساد الذاكرة | Kitploit
أدوات/GitHubGitHub/thebl4ckph4nt0m/cve-2025-21298
تحليل الذاكرة الجنائيتحليل الثغرات الأمنيةالاستغلالاستغلال الملفات الثنائية
GitHubthebl4ckph4nt0m/cve-2025-21298

CVE-2025-21298

ثغرة حرجة في Windows OLE بدون نقرة. هذا إثبات مفهوم لـ CVE-2025-21298 - ثغرة تنفيذ التعليمات البرمجية عن بُعد في Windows OLE (CVSS 9.8). هذا PoC لفساد الذاكرة

عرض المستودع
1منذ سنة واحدةلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

CVE-2025-21298

المحتوى

هذا إثبات مفهوم لـ CVE-2025-21298 - ثغرة تنفيذ التعليمات البرمجية عن بُعد في OLE لنظام Windows (CVSS 9.8). إنه إثبات مفهوم لفساد الذاكرة، وليس استغلالاً.

الثغرة

تقع الثغرة في ole32.dll!UtOlePresStmToContentsStm. الغرض من الدالة هو تحويل البيانات الموجودة في تدفق "OlePres" داخل مخزن OLE إلى بيانات منسقة بشكل مناسب وإدراجها في تدفق "CONTENTS" في نفس المخزن. تتلقى مؤشر IStorage إلى كائن مخزن وثلاث وسائط غير مهمة نسبياً.

أدناه نرى تنفيذ الدالة مع فرق من تصحيح يناير 2025:

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;
  // إنشاء تدفق "CONTENTS" في المخزن وتخزينه في pstmContents
  if ( (lpVtbl->CreateStream)(pstg, L"CONTENTS", 18LL, 0LL, 0, &pstmContents) )
    return 0LL;
  // إطلاق pstmContents فوراً، لن نستخدمه الآن
  (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);// الخيار الثاني للفشل -> لا يوجد تدفق OlePres
  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);
  // إطلاق pstmContents إذا كان لا يزال موجوداً، نحتاج للتنظيف
  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;
}

المشكلة تكمن في المتغير pstmContents. في البداية يُستخدم لتخزين المؤشر إلى كائن تدفق "CONTENTS" الذي يتم إنشاؤه في بداية الدالة. يتم تدمير التدفق فوراً بعد إنشائه ويتم إطلاق المؤشر المخزن في pstmContents (مما يحرره في coml2.dll!ExposedStream::~ExposedStream). ومع ذلك، لا يزال المتغير يحتوي على المؤشر المحرّر. في جزء لاحق من الدالة، قد يُعاد استخدام المتغير لتخزين المؤشر إلى تدفق "CONTENTS" مرة أخرى - ولهذا السبب، يوجد كود تنظيف في نهاية الدالة يُطلق المؤشر في حال كان مخزناً في المتغير. يفشل الكود في مراعاة أن UtReadOlePresStmHeader قد تفشل - إذا حدث ذلك، سيظل pstmContents يشير إلى المؤشر المحرّر وسننتقل إلى كود التنظيف، الذي سيُطلق المؤشر مرة أخرى. وبالتالي، يحدث موقف تحرير مزدوج.

كما هو موضح في فرق التصحيح، قامت Microsoft بإصلاح المشكلة عن طريق تعيين pstmContents إلى صفر بعد تحرير المؤشر الذي يحتويه في البداية.

إعادة الإنتاج

في المستودع يوجد ملف rtf يُعيد إنتاج الثغرة. اختبرت ذلك بفتح الملف في MS Word ولكن يمكنك أيضًا اختباره مع تطبيقات أخرى تقوم بتحليل بيانات RTF (مثل Outlook). قد يكون الاستغلال ممكنًا من خلال تنسيقات أخرى تُضمّن كائنات OLE، لم أجرب ذلك.

الفيديو:

إثبات المفهوم

تنزيل الأداة