Skip to content
KitploitKITPLOIT
أدواتعمليات الاستغلالالمدونة
Log in
إرسال
أدواتعمليات الاستغلالالمدونة
إرسال

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
أدوات/GitHubGitHub/jackhuyh/cve-2016-3308
تحليل الذاكرة الجنائيتحليل الثغرات الأمنيةالاستغلالاستغلال الملفات الثنائية
GitHubjackhuyh/cve-2016-3308

CVE-2016-3308

استخدم CVE-2016-3308 لفساد ذاكرة heap لسطح المكتب في win32k

عرض المستودع
12112منذ 10 سنواتلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

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

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

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

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

استخدم CVE-2016-3308 لإتلاف كومة سطح المكتب win32k

المؤلف : @55-AA، 18 سبتمبر 2016

##مقدمة

كومة سطح المكتب (Desktop heap) هي تجمع نواة يستخدمه win32k، ويمكن استغلالها بواسطة تطبيق وضع المستخدم. سأصف هنا بالتفصيل كيفية تنفيذ استغلال موثوق بحيث يمكن قراءة/كتابة عنوان عشوائي في النواة. هذا الشرح والتحليل المرتبط به تم على تثبيت win7_sp1_x86 (build 17842).

##الثغرة

في 9 أغسطس 2016، أصدرت Microsoft MS16-098. كود الثغرة موجود داخل الدالة win32k!xxxInsertMenuItem، النموذج الأولي للدالة هو:

BOOL xxxInsertMenuItem(
        PMENU pMenu, 
        UINT wIndex, 
        BOOL fByPosition, 
        LPMENUITEMINFOW lpmii, 
        PUNICODE_STRING pstrItem
    );

أولاً لنلق نظرة على كود الخلل الوهمي في xxxInsertMenuItem:

if (pMenu->cItems >= pMenu->cAlloced) {
    if (pMenu->rgItems) {
        pNewItems = (PITEM)DesktopAlloc(
                        pMenu->head.rpdesk,
                        (pMenu->cAlloced + CMENUITEMALLOC) * sizeof(ITEM),
                        DTAG_MENUITEM);
 ......

    pMenu->cAlloced += CMENUITEMALLOC;
    pMenu->rgItems = pNewItems;
    if (wIndex != MFMWFP_NOITEM)
        pItem = MNLookUpItem(pMenu, wIndex, fByPosition, &pMenuItemIsOn);

......

pMenu->cItems++;
if (pItem != NULL) {
    RtlMoveMemory(pItem + 1, pItem, (pMenu->cItems - 1) *
            sizeof(ITEM) - ((char *)pItem - (char *)pMenu->rgItems));
} else {

في الكود أعلاه، عندما تمت إضافة العنصر التاسع (من الأول) إلى pMenu، تم استدعاء DesktopAlloc() لإعادة تخصيص pMenu->rgItems جديد. ثم تم استدعاء MNLookUpItem() للحصول على موقع العنصر في pMenu->rgItems. لكن pItem الذي تم إرجاعه بواسطة MNLookUpItem() هو rgItems لقائمة فرعية أخرى (pSubMenu) بدلاً من pMenu، لذلك عندما تم استدعاء RtlMoveMemory()، تم الكتابة فوق pItem للقائمة الفرعية والباييتات التالية بسبب الحجم الخاطئ للنقل.

التالي هو كود التفكيك حول الخلل، والذي قد يؤدي إلى كتابة فوق الكومة، ويمكن استغلاله لبناء كتلة مزيفة:

0: kd> u win32k!xxxInsertMenuItem+0x1f5 l8
win32k!xxxInsertMenuItem+0x1f5:
95d295af 6bc06c          imul    eax,eax,6Ch
95d295b2 2bc3            sub     eax,ebx
95d295b4 034634          add     eax,dword ptr [esi+34h]
95d295b7 50              push    eax
95d295b8 8d436c          lea     eax,[ebx+6Ch]
95d295bb 53              push    ebx
95d295bc 50              push    eax
95d295bd e85ea40100      call    win32k!memmove (95d43a20)

لتتبع الخلل، أستخدم نقاط التوقف هذه في WinDbg:

ba e1 win32k!xxxInsertMenuItem

ba e1 win32k!xxxInsertMenuItem+0xf3    
95d294e3 e843e70200      call    win32k!DesktopAlloc (836d7bf5)

ba e1 win32k!xxxInsertMenuItem+0x129
95d294e3 e80de70200      call    win32k!DesktopAlloc (836d7bf5)

ba e1 win32k!xxxInsertMenuItem+0x1f5
95d295af 6bc06c          imul    eax,eax,6Ch

من أجل تشغيل الخلل، يجب تنفيذ المراحل التالية:

  1. إنشاء قائمة (menu).
  2. إنشاء قائمة فرعية كأول عنصر (ITEM) في القائمة مع المعرف 0x123، ومن الضروري تعيين MENUITEMINFO.hbmpItem بالقيمة HBMMENU_SYSTEM.
  3. إضافة 7 عناصر أخرى بالمعرفات من 0x1001 إلى 0x1007 إلى القائمة.
  4. إضافة عنصر بالمعرف 1 إلى القائمة الفرعية.
  5. إضافة 8 عناصر أخرى للقائمة الفرعية، من أجل الحصول على tagMENU.rgItems بسعة 16 خانة. لكن هذه الخطوة ليست ضرورية لتشغيل الخلل إذا كنت تحتاج فقط إلى تعطل.
  6. إضافة العنصر التاسع بالمعرف 0x123 إلى القائمة، وبالتالي سيتم استدعاء RtlMoveMemory() المتوقعة بمعاملات خاطئة.

##كومة سطح المكتب (Desktop Heap)

كومة سطح المكتب هي تجمع عام تستخدمه جميع عمليات واجهة المستخدم الرسومية (GUI). جميع كائنات GUI، مثل النافذة والقائمة، مخزنة في كومة سطح المكتب، وتتم إدارتها بواسطة موزع كومة النواة. يستخدم موزع كومة النواة دوال مألوفة مثل RtlAllocateHeap و RtlFreeHeap. على عكس كومة وضع المستخدم، لا تستخدم كومة سطح المكتب أي موزعات أمامية، لذلك لا توجد كومة تجزئة منخفضة (LFH)، ولا قائمة جانبية (Lookaside list)، إلخ. كما لا يوجد ترميز للكومة (Heap Encoding) حتى Windows 8 وما بعده. فيما يلي هيكل الكتلة (trunk) على win7_sp1_x86:

typedef struct _HEAP_ENTRY {
    USHORT Size;
    UCHAR Flags;
    UCHAR SegmentIndex;
    USHORT PreviousSize;
    UCHAR SegmentOffset;
    UCHAR UnusedBytes;
 } HEAP_ENTRY, *PHEAP_ENTRY;

يمثل الحقلان Size و PreviousSize حجم الكتل بعد الإزاحة لليمين بمقدار HEAP_GRANULARITY_SHIFT (المعرف بـ 3 في نظام 32 بت)، يحدد الحقل Size الكتلة الحالية، ويحدد PreviousSize الكتلة الأمامية. عادةً ما يتم تعيين البت الأدنى من Flags إلى HEAP_ENTRY_BUSY (0x01)، مما يمثل أن الكتلة قيد الاستخدام، وإلا إلى 0x00.

يوضح الشكل التالي العلاقة بين هذه الحقول وكتل الكتل. الكلمة المزدوجة (WORD) السفلية الخضراء الثانية (0x000f) تمثل أن حجم الكتلة الحالية هو 0x78 بايت، الكلمة المزدوجة (WORD) السفلية السوداء الثانية (0x0003) تمثل أن حجم الكتلة الأمامية هو 0x18 بايت، والكلمات المزدوجة (WORD) بالخط الأحمر (0x0001) تمثل أن الكتل الحالية قيد الاستخدام. هنا، حجم الكتلة يشمل حجم الرأس، والرأس معرف بهيكل HEAP_ENTRY أعلاه.

هذه هي الميزة الأكثر أهمية لفساد الكومة، حيث يحصل موزع الكومة دائمًا على الكتلة التي تم تحريرها مؤخرًا. هذا يعني أنه يمكننا فعليًا تخصيص كتلة بأي حجم وفي موقع معين نريده.

##الفساد (Corruption)

باستغلال الخلل، يمكنني الكتابة فوق بعض البايتات في كومة سطح المكتب، وبالتالي سأحصل على كتلة مزيفة تحل محل كتلة عادية، ثم أحرر الكتلة المستبدلة، بحيث يتم دفع الكتلة المزيفة إلى أعلى قائمة الكتل الحرة. بعد ذلك يتم إعادة استخدام الكتلة المزيفة، يمكنني كتابة أي بايتات فيها، وتتداخل المنطقة القابلة للكتابة مع عدة كتل عادية، لكنها لا تغطي مساحة النواة بأكملها. لذا أحتاج إلى بناء عملية قراءة/كتابة أولية (R/W primitive) أخرى في المنطقة المتداخلة، تستفيد من tagWND.strName لكتابة عنوان عشوائي. يمكن لمؤشر strName.Buffer أن يقودنا إلى أي مكان بما في ذلك مساحة النواة ومساحة المستخدم. بالطبع، هدفنا هو فقط nt!HalDispatchTable.

يوضح الشكل التالي إجراء تغيير الكومة:

وفقًا للتوضيحات، أقوم بإفساد كومة سطح المكتب خطوة بخطوة، وأنفذ الاستغلال عبر المراحل التالية:

  1. إنشاء بعض النوافذ (Window) بحجم نص WndText يساوي 1، وتكرار الحلقة FILL_HOLE_COUNT مرة لملء الفتحة القديمة.
  2. إنشاء WND_0 إلى WND_5 للتعامل مع بيانات الكتلة.
  3. إنشاء قائمة، وإنشاء قائمة فرعية كأول عنصر في القائمة بالمعرف 0x123. ثم إضافة 7 عناصر أخرى بالمعرفات 0x1001~0x1007 إلى القائمة.
  4. إضافة عنصر بالمعرف 1 و 7 عناصر أخرى بالمعرفات 0x2001~0x2007 إلى القائمة الفرعية.
  5. إضافة العنصر التاسع بالمعرف 0x2008 إلى القائمة الفرعية، من أجل الحصول على tagMENU.rgItems بسعة 16 خانة.
  6. تعيين نص WND_5 بحجم 0x360 بايت لملء الفتحة الأصلية للقائمة الفرعية * 8 عناصر.
  7. تعيين نص WND_1 بحجم 0x70 بايت، تحضير رأس الكتلة المزيفة.
  8. تعيين نص WND_2 بحجم 0x70 بايت، بناء مكان مؤقت للكتلة المزيفة.
  9. تعيين نص WND_0 بحجم 0x6c0 بايت، بناء مكان مؤقت لعناصر القائمة المستقبلية * 16.
  10. إنشاء النافذة الأولية (Primitive-WND) مع tagPROPLIST تم إنشاؤه تلقائيًا.
  11. إنشاء نافذة الفساد (Corrupt-WND) مع tagPROPLIST تم إنشاؤه تلقائيًا.
  12. تعيين نص WND_3 بحجم 0x10 بايت لكتلة مزيفة تالية تتبع تلك الموجودة في الخطوة 8.
  13. حفظ تخطيط الكومة لاستعادته في مرحلة الخروج.
  14. إعادة تعيين نص WND_0 إلى 0x700 بايت، بحيث يتم تحرير فتحة بحجم 0x6c0.
  15. إضافة العنصر التاسع إلى القائمة، حيث يقوم بإعادة استخدام الكتلة التي تم تحريرها في الخطوة 14، وسيتم تشغيل الخلل.
  16. إعادة تعيين نص WND_2 إلى 0x80 بايت، مما يتسبب في دفع الكتلة المزيفة إلى أعلى القائمة الحرة.
  17. تعيين نص Corrupt-WND إلى 0x8e0 بايت، ثم يتم إعادة استخدام الكتلة المزيفة.
  18. عن طريق تعيين نص Primitive-WND، تنفيذ عملية الكتابة الأولية للكتابة فوق nt!HalDispatchTable[1].
  19. تشغيل كود الصدفة (shellcode) عن طريق استدعاء NtQueryIntervalProfile.
  20. استعادة تخطيط الكومة المحفوظ والخروج.

الخطوات الرئيسية المذكورة أعلاه لبناء فنغ شوي الكومة (heap fengshui):

تنزيل الأداة