題目是經典類選單題型,可以new/modify/show/delete:
0x80–0x400
(small range),然後是用calloc給的題目保護為:NX + PIE + RELRO,使用libc-2.29!這已經是個我完全沒碰過的版本了…
另外還有個隱藏功能,可以malloc(0x217) 並read讀入,但會判斷tcache_perthread_struct(TPS)
上對應0x20大小的tcache count必須大於6才行.
但由於new功能限制的大小皆為small bin range,無法直接free掉一個fast chunk放進tache進而增加count,這時我腦中出現幾種思路:
首先第一個方法由於我們只能calloc(small chunk size),沒辦法要一塊fast chunk.
而第二個方法一開始我感覺可行,因為只要tcache還沒滿,那麼free掉fast/small chunk後都會先進tcache bin,但搞了很久才發現calloc不會從tcache拿…所以也放棄了這方法
第三個方法(貌似是其他多數人的做法?)後來沒有嘗試.
第四個方法也是一開始就想到,但是試了半天才發現unsorted bin unlink在libc 2.29已經新增了完整性檢查WTF(因為用docker架環境所以不知為何error message都沒收到,是後來把libc 2.27跟libc 2.29的malloc.c拿來diff一下才發現的QQ)。
於是我想到了第五種作法,這大概是去年libc 2.27剛出的時候我在啃code時無聊想到的打法XD不過由於限制很多,再加上他效果跟unsorted bin attack有87%像,所以也沒認真當一回事,場景是這樣的:
當要了一塊small chunk後,此時會遍歷跟這塊大小一樣的small bin上看有沒有其他free chunk,如果有就把它擺到tcache bin上(就是最近用到的放在快取上的概念),看似簡單的一句話其實是要符合挺多條件的
而這個情況會發生兩種不同的unlink
2. 把剩餘在small bin的chunk unlink到tcache bin中,不會做檢查。
而上面這個bck->fd = bin
就是關鍵,這個bin是一個libc中的位址,所以會是0x7f??????????
所以如果能控制這個bck,就能在任意位址寫入這個值。
*(bck+0x18) = 0x7f??????????
其實效果真的跟unsorted bin attack差不多,只是要符合挺多條件的,在本題的情況無非就是要改掉TPS count,調整一下讓count欄位被改為0x7f
即可。
然後有發現上面好像有三條很矛盾的狀況嗎?
正常來說free chunk只有在tcache bin滿了之後才會進small bin,第一條情況告訴我們起碼有一個small chunk,那通常代表tcache bin滿了,但第二第三條情況就衝突到了,怎麼辦?
這時可以利用unsorted bin中的last remainder,例如以下
[1] A = calloc(1, 0x400); free(A); *7
[2] A = calloc(1, 0x400); free(A);
[3] A = calloc(1, (0x400-0x100));
[4] calloc(1, 0x400);
[1] 塞滿tcache idx_0x400 bin
[2] 此時會進入到unsorted bin之中
[3] 要一塊(0x400–0x100),由於calloc不會從tcache拿,所以直接從unsorted bin拿走,切剩下的那塊last remainder為0x100
[4]此時要一塊比0x100還大的chunk,由於last remainder大小不夠,就會直接被送進small bin裡面。
就只是利用remainder不會進tcache的特性而已。