介紹一種在多執行緒堆題中利用堆溢位達成任意地址分配的手法。
我們知道,一個程序的主執行緒的堆管理main_arena在libc中,分配的chunk在堆段中。那麼子執行緒的arena和堆塊都在哪裡呢?
這一大串在libc前面一點點的anon就是給子執行緒留的arena和堆空間。arena和tcache管理chunk在這個記憶體段的最上面。(下面那個紫色的800000大小的段好像不是,沒見過他被分配。)紫色的用完了就從白色哪裡擴充套件。那麼當圖中所有的紫色和白色都用完了應該用哪裡的記憶體地址了呢?
程式會用mmap或者其他的什麼辦法再搞來一段記憶體空間,然後把藍色箭頭指向的段(剛剛提到的帶有arena的那個堆段)上面一些地方的地址分配給他們。這時我們可以發現,只要我們把這次分配的空間再用完,然後在最後一個堆塊上實行堆溢位,溢位的部分就能覆蓋到子執行緒的arena。控制了arena就好說了,在fastbin上隨便寫寫就能任意地址分配了。
回到題目
例題:N12018 shopping
題目只有一個malloc功能,malloc完了以後可以在堆塊上寫點東西也可以不寫,沒有free沒有show沒有edit,單純看下來挺難做的。Read()函式有一個不易察覺的我沒發現的洞,只要一次讀入資料沒有把nbytes用完,那麼就可以再讀入nbytes,達成堆溢位。這樣就可以透過上述手法,申請大量堆塊,透過堆溢位覆蓋fastbin。達成任意寫之後在bss上畫一個system就能getshell了,很方便很仁慈。