[HSCTF6] – hardheap

Pada saat penulisan writeup, challenge ini memiliki poin sebesar 480 dan total 16 solve.

Binary dan libc.

Sebelum melanjutkan, ada baiknya pembaca mengenali cara kerja malloc, dan FSOP.

Terima kasih pada writeup ini, karena writeup ini membantu saya menemukan langkah umum untuk menyelesaikan challenge ini pada saat CTF berlangsung.

Analisa

Diberikan binary dengan konfigurasi sebagai berikut:

Sepertinya sulit. Ketika program dijalankan, program memiliki menu seperti heap exploitation pada umumnya.

Sepertinya, kita bisa melakukan alokasi, print, dan menghapus data. Pseudocode dari fungsi allocate:

Kita hanya bisa melakukan alokasi fastbin, dan maksimal jumlah alokasi tidak boleh lebih dari 19. Fungsi view tidak perlu banyak dijelaskan, karena hanya melakukan puts(ptrs[idx]). Pada fungsi delete, terdapat kerentanan:

Karena variabel ptrs tidak dikosongkan setelah difree, dan juga buffer heapnya tidak dikosongkan, double free dan UAF bisa dilakukan. Kita akan melakukan fastbin attack dengan sedikit keberuntungan untuk mendapatkan shell pada program ini.

 

Eksploitasi

Pertama, sudah pasti kita membutuhkan leak pointer heap dan libc. Kita mengalokasikan 7 buffer heap, dan kita akan bermain-main dengan 5 (dikurangi buffer pertama dan terakhir). Kita menuliskan size palsu pada buffer pertama, yang nanti akan kita perlukan:

Kemudian kita menaruh prev size palsu pada buffer keempat, yang nantinya akan dibutuhkan:

Sekarang waktunya untuk eksploitasi. Kita lakukan double free pada buffer berukuran 0x20 yang telah kita alokasikan, dan leak pointer heap dari buffer pertama yang difree.  Kita lakukan fastbin attack untuk mengganti ukuran buffer kedua dari 0x20 menjadi 0x80. Di sinilah size dan prev size palsunya dibutuhkan.

Kita lakukan free pada buffer kedua, dan kita telah berhasil mendapatkan leak libc, karena pointer dari main_arena ditaruh pada buffer kedua yang baru saja difree.

Sekarang kita dapat melakukan RCE; tetapi tidak semudah itu, karena kita tidak bisa mengalokasikan buffer didekat __malloc_hook (akan dijelaskan di bawah). Ingat kembali bahwa top adalah sebuah buffer khusus yang melayani setiap permintaan malloc.

Jika kita dapat mengontrol pointer ini, kita dapat mengontrol di mana buffer kita akan dialokasikan selanjutnya. Pertanyaannya adalah “Bagaimana kita dapat mengalokasikan buffer di dekat pointer ini ?”. Kita bisa melakukannya dengan fastbin attack dan sedikit keberuntungan. Dalam writeup ini, disebut bahwa kita dapat melakukan alokasi buffer di dekat __malloc_hook jika kita memanfaatkan fakta bahwa alamat alokasi tidak harus selalu kelipatan 8. Pada contoh yang saya berikan di bawah ini, main_arena tidak memiliki buffer heap berukuran 0x10-0x40 di dekat top.

Karena kita tidak boleh mengalokasikan buffer dengan ukuran lebih dari 0x48, kita tidak dapat menggunakan buffer berukuran 0x60 untuk mendapatkan pointer di dekat 0x00007f883fa2daf0. Mari kita free dua buffer fastbin dan lihat apa yang terjadi:

Sudah terlihat solusi kita. Kita tidak dapat menggunakan pointer fastbin berukuran 0x40, karena kita akan menaruh alamat main_arena pada fastbin freed list kita, dan malloc akan melakukan abort karena 0x30 != 0x60. Ini juga di mana keberuntungan kita berpengaruh. Tanpa ASLR, size akan menjadi 0x15, dan exploit sudah pasti gagal. Exploit hanya akan bekerja jika byte pertama dari heap adalah 0x56, kemungkinan karena tidak ada PREV_INUSE bit. Setelah empat alokasi, buffer kita akan berada di atas top.

Kita telah menimpa pointer top dengan pointer milik kita, alamat dari buffer heap akan berada pada pointer+16 byte. Sebelum kita dapat mengalokasikan buffer, ingat bahwa kita telah melakukan free pada smallbin, yang artinya terdapat last remainder. Sekali alokasi berukuran 0x40 akan mengatasi ini, dan alokasi berukuran 0x40 berikutnya akan mengembalikan alamat yang kita inginkan. Bagian terakhir ini agak membingungkan karena penulis kesulitan mendapat tempat yang cocok untuk dialokasikan buffer heap. Pada akhirnya penulis memilih vtable stdin dan menggantinya dengan alamat heap (dan mengisi buffer heap dengan one_gadget). scanf akan memanggil __GI___uflow, yang akan memanggil [vtable+0x28], dan memanggil one_gadget.

Script:

Output:

P.S. Solusi lainnya yang saya dapatkan setelah CTF usai adalah dengan mengalokasikan buffer di atas __malloc_hook, menaruh one_gadget, dan dengan sengaja melakukan abort melalui free (abort melakukan alokasi buffer melalui malloc juga).

Leave a Reply

Your email address will not be published. Required fields are marked *