Pwnable.tw-tcache tear
Author: 堇姬Naup
analyze code
先IDA逆一波,把函數重新命名
main
1 | void __fastcall __noreturn main(__int64 a1, char **a2, char **a3) |
最多只能free 8個chunk
並且會free掉當前最新的chunk
ptr 在 bss上,並且沒有開PIE,若能任意寫掉free(ptr),就可以去free想要的地方
有以下功能
1 | puts(" 1. Malloc "); |
create (malloc)
1 | int sub_400B14() |
size不可以小於 0xFF,並且可以寫值到chunk上
info
印出 name ,位在0x602060,若能讓libc在name位置上,可以拿來leak libc
1 | ssize_t sub_400B99() |
分析
沒開PIE
首先我的想法是,如果size小於16,那size - 16會變成一個超大的數字,導致heap overflow,這邊考慮可以打tcache poinsoning到free hook上寫system
之後malloc一塊寫/bin/sh,最後free
我先malloc 一塊大小為0xe
一個大小為 0x60
這樣會拿到一塊 0x20
這樣會拿到一塊 0x70
1 | -------------------------- |
free 掉兩塊
接下來malloc一塊 0xe
就會拿到 0x20那塊
0xe - 0xf = -1 = 0xfffff…
1 | -------------------------- |
1 | tcache[0x70] -> chunk 2 -> fake chunk |
並且有heap overflow,可以蓋掉fd,之後malloc兩次就可以拿到任意寫
1 | from pwn import * |
那接下來要想想如何leak libc
這邊想要利用 unsorted bin來leak libc ,但是我們只能malloc小於0xff,這邊的想法是利用任意寫改chunk fd到bss段上偽造一個大小為unsorted bin 的 fake chunk
info會印出namespace上的東西,將fake chunk fd偽造到這上面,就可以了
但是unsorted bin free要指向 data,這邊可以透過覆蓋
1 | bss:0000000000602088 ptr |
也就是下個要free的位置來修改 pointer,free任意位置
1 | from pwn import * |
吃 double free or corruption (!prev)
感覺是連下一塊都要偽造
1 | from pwn import * |
這樣就成功leak libc了
目前用了5個FREE
加上寫掉 free_hook的兩個free,跟觸發free_hook的一個free,剛剛好
這邊再打一輪 tcache poinsoning 到free_hook,改成system 開一個 shell
這邊chunk狀況其實有點混亂了,所以最後改打double free來寫free hook,一樣用到兩個FREE
1 | tcache[0x50] -> chunk -> chunk -> chunk -> ... |
1 | tcache[0x50] -> chunk -> free_hook |
之後malloc一塊,此時free指向該chunk data,寫上/bin/sh再來free掉就會是 system(‘/bin/sh’)
exploit
1 | from pwn import * |
串起了 integer overflow 、 tcache poinsoning 、double free,終於排完了