今天會把 Educational Heap Exploitation 做個結尾,另外昨天的例題 plaiddb 做的時間比預期中的長.,加上這兩天難得出門到剛剛才回來......預期明天才會補上內容
stack_buffer_1[2] = victim_chunk;
nb
(nb 要小於 top chunk 被篡改的 size),在這計算下一次 top chunk 的位置會是用 old top + nb + 8
去計算,因此我們可以把 top chunk 調整到任意的 buffer 上,下一次就可以拿到任意位置算是 Poison Null Byte 的變形應用,透過 null byte off-by-one 蓋成 \x00
的特性來取消 chunk 的 PREV_INUSE,讓觸發 chunk 對上一塊 merge & unlink
chunk 對上一塊 merge & unlink 時,會根據 prev_size 尋找上一塊 chunk 的位置
chunk 的 prev_size
會在記憶體的前一塊 chunk 視為 data 使用,而且 free 完之後不會清掉 heap data,因此可以留資料偽造 prev_size
讓 unlink 跟記憶體前一塊 chunk 做 unlink,這樣下次 malloc 就會把前面的 chunk 當 unsorted bin 來使用
prev_size
可以給很大的數字,讓他在找前一個 chunk 時發生 int overflow,這樣就可以對任意位置的 chunk 做 unlink文件上寫可利用版本是 < 2.26,但避開觸發 tcache 之後應該還是能使用
範例 code 利用 off-by-one 改掉 PREV_INUSE,也是真實漏洞常見的寫法
a[real_a_size] = 0;
_IO_list_all
的值讓 vtable 指向 main_arena 的位置,在後續觸發 abort 控制 control flow這題是考 House of Einherjar,會當成今天的例題是是因為 House of Einherjar 兩點原因:
又是 heap 標準的選單題,除了 PIE 以外保護全開,程式有 create, delete, edit 三個功能
因為 delete 實際上不會清空 ptr,因此即使 delete 掉之後還是會印出 heap 上的 data,我們可以藉由 create 時分配 smallbin 和 fastbin 的 chunk 來 leak libc 和 heap
接著透過 edit 的 off-by-one 來 overwrite PREV_INUSE,因為可以 edit 多次,所以可以繞過用 strcpy
被 \x00
截斷的問題,然後最後一次 edit 用來在 bss buffer 偽造 chunk,由於沒有開 PIE,因此可以簡單把 fd 和 bk 都設成自己來避開 circular check
最後 delete 掉 off-by-one 改掉的 chunk 觸發 unlink,unsorted bin 中就會多出剛才偽造在 bss 段上的 chunk,下次 malloc 就可以取得 bss 上的 buffer,並覆蓋掉其他 create 出來的指標,後續就能達成任意讀和任意寫入
malloc(): memory corruption
的訊息,因此這邊要在 edit 一次修改 chunk size 讓他落在合理範圍最後提個兩點,這題無法用 unlink 的方式解的原因是,因為程式本身 edit 時能讀寫的長度取決於目前 strlen
的長度,因此 unlink 完將 ptr 變成 &p-0x18
之後就會因為可改的長度不夠無法進行後續利用,會需要從 create 的地方拿到 buffer 才能任意改值
前面提過 House of Einherjar 的原理其實就是 Poison Null Byte 的應用,因此這題其實也可以用 overlap + fastbin attack 解,可以參考原作者的 說明