بسم الله الرحمن الرحيم الحمد لله رب العالمين والصلاة والسلام على أشرف المرسلين سيدنا محمد وعلى آله وصحبه ومن تبعهم بإحسان إلى يوم الدين.


حسابي في التويتر هنا


المتطلبات:

  1. معرفة بأساسيات الHeap و التعامل مع malloc

  2. معرفة ببعض هجمات الHeap

  3. قرأءة مقالاتي السابقة بخصوص الHeap Attacks


البداية

ماهو Unsafe Unlink ؟

هو تكنيك فكرته أنشاء 2 chunks بحجم يناسب الsmallbins أول chunk نضع لها FD & BK ولازم يأشرون على نفس الchunk أو مكان فيه العنوان حق الchunk عشان تكون الfake chunk حقتنا وعشان نتخطى unlink check ثم نحاول إضافة prev_size الى chunk رقم أثنين وجعل prev_inuse flag الخاص بالchunk رقم 2 يساوي 0 ثم نسوي free لchunk رقم أثنين كي نستدعي unlink() macro وتندمج Chunk 1 و Chunk 2 ثم يعطينا هذا arbitrary write.

راح أشرح بعد التفاصيل لاحقاً

ماهو smallbins ؟

هي bin تشبه fastbin لكن فيه كذا أختلاف بسيط نوعها doubly linked, circular list فيها 62 bin تحتوي على الchunks الي صار لها free وحجمها أكبر من fastbin أو أقل, تتعامل مع FD & BK عكس fastbin الي تتعامل فقط مع FD

Doubly Linked List:

هاذي الصورة مأخوذه من كورس HeapLab 

مثال:

Chunk A الFD حقها يأشر على Chunk B FD و Chunk B ال BK حقها يأشر على Chunk A FD و الBK حق Chunk A يأشر على Chunk B


أول Chunk موجودة في الbin الBK حقها يأشر على على أخر chunk موجودة في الBin 

أخر Chunk موجودة في الbin الFD حقها يأشر على على أول chunk موجودة في الBin 

عندما تطلب من malloc أن تحجز لك chunk حجمها 0xa00 سوف تذهب للبحث عن الchunk في unsortedbin و smallbin تبدأ البحث من الخلف (Tail).

الunsortedbin و الsmallbin عملية فك أرتبط الChunks فيهم هي Partial Unlink.

ماهو Partial Unlink ؟

هو عملية فك أرتباط الchunk جزئياً من smallbins و unsortedbins حيث يتم تتبع BK الخاص با victim chunk و نسخ العنوان الموجود في أعلى (Head) الbin سواً كانت smallbins او unsortedbins الى العنوان الموجود في الFD الخاص با victim chunk وبعد ذالك يتم نسخ BK الخاص با victim chunk الى BK الخاص با الHead الموجود في الBin.

أدري حوسه صح ؟ لكن في الشرح راح تفهمون الفكره

ماهي unlink() macro ؟

عندما نريد حذف chunk من bin نستدعي ()unlink كي تحذفها من الbin وترجعها للمستخدم.

FD = P->fd; /* forward chunk */ BK = P->bk; /* backward chunk */ FD->bk = BK; /* update forward chunk's bk pointer */ BK->fd = FD; /* updated backward chunk's fd pointer */

هنا تتأكد الunlink من الFD و الBK اذا كانت ال FD تأشر على BK و الBK تأشر على الFD

/* consolidate backward */ if (!prev_inuse(p)) { prevsize = prev_size (p); size += prevsize; p = chunk_at_offset(p, -((long) prevsize)); if (__glibc_unlikely (chunksize(p) != prevsize)) malloc_printerr ("corrupted size vs. prev_size while consolidating"); unlink_chunk (av, p); }

هنا الsource code حق ()unlink حق اذا بغينا ندمج 2 smallbins chunks وتصير chunk وحدة زي مانشوف أول شرط تتأكد اذا كان الprev_inuse حق الchunk يساوي 0, ثم تتأكد اذا كان فيه prev_size للchunk ثم تتأكد اذا كان الprev_size صحيح او لا واذا كان صحيح راح تدمجه مع حجم الchunk و اذا كان حجم الchunk مايساوي prev_size الي مكتوب يعني اذا كان فيه Chunk A و Chunk B وكان حجم Chunk A 0x90 وحطينا في prev_size حق Chunk B 0x60 راح يصير abort ويطلع لنا error من glibc اذا كان لا الprev_size صحيح راح تستدعي ()unlink

عشان نوصل لل()unlink لازم نحط prev_size حق Chunk B ويكون صحيح عشان تندمج من الchunk الي قبلها, ونخلي prev_inuse حق Chunk B = 0

 في إصدارت الglibc الجديدة unlink تتأكد من FD و BK حق الchunk  اذا كان

FD = BK و BK = FD راح نتخطى الcheck

FD = P->fd; BK = P->bk; if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) malloc_printerr (check_action, "corrupted double-linked list", P, AV); else { FD->bk = BK; BK->fd = FD; }

اذا ماكان الFD و الBK يأشرون على نفس الChunk راح يطلع Error

خطوات الهجوم

  1. ننشئ 2 chunks

  2. نحط لا أول Chunk الFD و الBK يأشرون على المتغير table الي راح يكون فيه العنوان حق Chunk A وكذا نتخطى الcheck حق unlink

  3. نحط 0 كا الprev_size حق Chunk A و حجم أقل بقليل من حجم Chunk A في Chunk A عشان نقنع chunk_B ان ذا الprev_size و الsize حق Chunk A

  4. نحط الحجم حق chunk A - 0x10 في prev_size حق Chunk B عشان نوصل للمكان الي حطينا فيه الprev_size  و الsize حق Chunk A ونحط الحجم حق Chunk B في size field حق Chunk B نفسه بالزبط لكن prev_inuse = 0

  5. نحرر Chunk B وراح تندمج Chunk A و Chunk B وأي شيء نكتبه في Chunk A راح ينكتب في المتغير table بحكم أنها الFake Chunk حقتنا وراح نغير الpointer الموجود في المتغير حق Chunk A الى free GOT وبكذا أي بعدها نكتبه في Chunk A راح ينكتب في free GOT ونغيره الى ()system ونحصل على Arbitrary Code Execution

في التطبيق راح أشرح الي ماهو مفهوم 

رابط البرنامج المستخدم في الشرح هنا

الخطوة رقم 1

ننتقل الى الخطوة رقم 2

الخطوة رقم 2

ليش في الFD والBK نقصنا من العنوان ؟

عشان لو حطينا العنوان زي ماهو راح يزيد عليه 0x18 byte والBK كذالك راح يزيد عليه 0x10 byte وهذا الي مانبيه عشان كذا نقصنا منها عشان لو زاد راح يجي على العنوان حق المتغير table بالزبط ونتخطى unlink check>

الخطوة رقم 3

نروح للخطوة رقم 4

الخطوة رقم 4

نشغل السكربت ونسوي attach للprocess id من الgdb

نشوف قدرنا  نحط new prev_size و new size لا Chunk A و Chunk B فا لو رجعنا نقصنا من العنوان حق Chunk B - 0x80 byte راح نرجع للfake prev_size و fake size حق chunk A ولو سوينا free لChunk B الحين راح تعتقد أن Chunk A محررة بعد فا راح تندمج وأي شيء نكتبه راح يروح للمتغير table بحكم أن حنا حطيناه في الFD و الBK حق Chunk A بسبب أنه يحتوي على العنوان حق Chunk A الي راح يخلي Chunk A تأشر على نفسها و نتخطى unlink check وعشان وراح يكون المتغير table هو الFake Chunk حقتنا وراح نقدر نسوي overwrite للبيانات الي فيه

الخطوة رقم 5 و الأخيره

نشغل السكربت ونسوي attach للprocess id من الgdb

نشوف الحين الchunk الوحيدة الموجودة هي Chunk A الحين نحاول نكتب فيها أي شيء ونشوف هل راح ينكتب في المتغير Table ولالا ؟

نروح نسوي attach للprocess id من الgdb

نشوف الحمدلله قدرنا نسوي overwrite للمتغير table بنجاح وراح نحط العنوان حق الGOT الخاص با ()free بدال العنوان حق Chunk A الموجود في المتغير table وأي شيء من بعدها نكتبه في Chunk A راح ينكتب في الGOT الخاص با ()free

نروح نسوي attach للprocess id من الgdb

قدرنا نسوي overwrite بنجاح للfree GOT والحين نسوي chunk فيها “bin/sh/“ ونسوي لها free ويوم نستدعي free راح نستدعي system(“/bin/sh“)

نشغل السكربت

Arbitrary Code Execution


النهاية

وفي النهاية أتمنى عجبكم الموضوع وباذن الله أكون شرحت كل شيء والله يوفقكم جميعا وأسال الله أن يوفقني ويوفقكم جميعا.

Resources:

  • https://ir0nstone.gitbook.io/notes/types/heap/unlink-exploit

  • https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit

  • https://www.youtube.com/watch?v=HWhzH--89UQ

  • https://github.com/shellphish/how2heap/blob/master/glibc_2.35/unsafe_unlink.c