
استغلال لـ CVE-2021-40449 - ثغرة رفع الامتيازات في Win32k (LPE)
استغلال لثغرة CVE-2021-40449 (Win32k - رفع الامتيازات المحلية)
ثغرة CVE-2021-40449 هي ثغرة استخدام بعد التحرير (use-after-free) في Win32k تسمح برفع الامتيازات المحلية.
تم اكتشاف الثغرة في البرية من قبل Kaspersky.
الاستغلال المكتوب يدعم منتجات Windows التالية:
ومع ذلك، تم اختبار هذا الاستغلال حالياً فقط على الإصدارات التالية:
أوصي بشدة بقراءة الشرح الفني لـ Kaspersky قبل المتابعة.
كما ذكر في الشرح الفني من Kaspersky، توجد الثغرة في GreResetDCInternal. إذا قام المهاجم باعتراض (hooking) الاستدعاء العكسي في وضع المستخدم DrvEnablePDEV، والذي يتم استدعاؤه أثناء hdcOpenDCW، فمن الممكن تدمير سياق الجهاز الأصلي عن طريق استدعاء ResetDC، مما يسبب استخدام بعد التحرير (use-after-free) في النواة عند عودة الاستدعاء العكسي لوضع المستخدم.
الكود الزائف التالي تم إنشاؤه جزئياً من كود مصدر Windows XP المسرب ومن خلال الهندسة العكسية لأحدث إصدارة (قبل التصحيح) لـ GreResetDCInternal من Win32kfull.sys. تمت إزالة الأجزاء غير ذات الصلة باستخدام [...]. ابحث عن التعليقات VULN: .
BOOL GreResetDCInternal(
HDC hdc,
DEVMODEW *pdmw,
BOOL *pbBanding,
DRIVER_INFO_2W *pDriverInfo2,
PVOID ppUMdhpdev)
{
// [...]
HDC hdcNew;
{
// Create DCOBJ from HDC
DCOBJ dco(hdc);
if (!dco.bValid())
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
}
else
{
// Create DEVOBJ from `dco`
PDEVOBJ po(dco.hdev());
// [...]
// Create the new DC
// VULN: Can result in a usermode callback that destroys old DC, which
// invalidates `dco` and `po`
hdcNew = hdcOpenDCW(L"",
pdmw,
DCTYPE_DIRECT,
po.hSpooler,
prton,
pDriverInfo2,
ppUMdhpdev);
if (hdcNew)
{
po->hSpooler = NULL;
DCOBJ dcoNew(hdcNew);
if (!dcoNew.bValid())
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
}
else
{
// Transfer any remote fonts
dcoNew->pPFFList = dco->pPFFList;
dco->pPFFList = NULL;
// Transfer any color transform
dcoNew->pCXFList = dco->pCXFList;
dco->pCXFList = NULL;
PDEVOBJ poNew((HDEV)dcoNew.pdc->ppdev());
// Let the driver know
// VULN: Method is taken from old (possibly destroyed) `po`
PFN_DrvResetPDEV rfn = po->ppfn[INDEX_DrvResetPDEV];
if (rfn != NULL)
{
(*rfn)(po->dhpdev, poNew->dhpdev);
}
// [...]
}
}
}
}
// Destroy old DC
// [...]
}
كما يمكن رؤيته من الكود الزائف، يمكن تحرير سياق الجهاز القديم في استدعاء عكسي لوضع المستخدم من استدعاء hdcOpenDCW، وبعد ذلك، يتم استرجاع الطريقة DrvResetPDEV من سياق الجهاز القديم واستدعاؤها باستخدام (po->dhpdev, poNew->dhpdev).
لإنشاء واعتراض سياق جهاز، يمكن القيام بما يلي:
EnumPrintersOpenPrinter و GetPrinterDriver و LoadLibraryExAGetProcAddress و DrvEnableDriverVirtualProtectCreateDC(NULL, printerName, NULL, NULL)يجب أن يكون لدينا الآن سياق جهاز لطابعة مع استدعاءات عكسية معترضة في وضع المستخدم.
نحن مهتمون باعتراض واحد فقط، وهو DrvEnablePDEV. هذا الاعتراض مثير للاهتمام من ناحيتين: إثارة ثغرة استخدام بعد التحرير (UAF) والتحكم في الوسائط، كما هو موضح سابقاً. لإثارة ثغرة UAF، سنقوم باستدعاء ResetDC داخل الاعتراض، مما سيدمر سياق الجهاز القديم. عند العودة من الاعتراض، سنظل داخل أول GreResetDCInternal، والتي ستقوم بعد ذلك بجلب واستدعاء مؤشر الدالة لـ DrvResetPDEV من سياق الجهاز القديم والمُدمر مع الوسيطين اللذين تم إرجاعهما من DrvEnablePDEV؛ الـ DHPDEV القديم والجديد.
إذا كانت عمليتك تعمل بمستوى تكامل متوسط، فلا ينبغي أن تكون KASLR مشكلة بمساعدة EnumDeviceDrivers و NtQuerySystemInformation.
تذكر Kaspersky أن الاستغلال الأصلي استخدم كائنات لوحة ألوان GDI واستدعاء دالة نواة واحدة لتحقيق قراءة/كتابة عشوائية للذاكرة. يستخدم هذا الاستغلال تقنية لتخصيص BitMapHeader في المجمع الكبير و RtlSetAllBits لتمكين جميع الامتيازات على رمز العملية الحالي لدينا. سوف يشير BitMapHeader إلى _SEP_TOKEN_PRIVILEGES الخاص برمز العملية الحالي لدينا. من خلال استدعاء RtlSetAllBits(BitMapHeader)، يمكن تمكين جميع الامتيازات لرمز العملية الحالي لدينا باستدعاء دالة نواة واحدة. من هنا، يمكن إساءة استخدام الامتيازات الجديدة للحصول على SYSTEM. يستخدم هذا الاستغلال SeDebugPrivilege لحقن شيل كود في عملية winlogon.exe.
