记一次IO_FILE结构体attack
字数 1345 2025-08-29 08:30:05
IO_FILE结构体攻击技术详解
1. IO_FILE结构体概述
IO_FILE是glibc中用于处理文件输入输出的核心结构体,它定义了标准I/O流的所有属性和操作。在Linux系统中,标准输入(stdin)、标准输出(stdout)和标准错误(stderr)都是通过IO_FILE结构体实现的。
1.1 关键结构体成员
struct _IO_FILE {
int _flags; // 文件流状态标志
char* _IO_read_ptr; // 当前读取位置指针
char* _IO_read_end; // 读取缓冲区结束位置
char* _IO_read_base; // 读取缓冲区起始位置
char* _IO_write_base; // 写入缓冲区起始位置
char* _IO_write_ptr; // 当前写入位置指针
char* _IO_write_end; // 写入缓冲区结束位置
char* _IO_buf_base; // 缓冲区起始位置
char* _IO_buf_end; // 缓冲区结束位置
// ... 其他成员
struct _IO_jump_t *vtable; // 虚函数表指针
};
1.2 标准I/O流的内存位置
在64位系统中,标准I/O流通常位于.bss段:
- stdout: 0x6020C0
- stdin: 0x6020D0
- stderr: 0x6020E0
2. IO_FILE利用原理
通过修改IO_FILE结构体的关键指针,可以控制程序的输入输出行为,实现信息泄露或代码执行。
2.1 利用条件
- 能够越界访问到IO_FILE结构体
- 能够修改IO_FILE结构体的关键字段
- 程序后续会使用被修改的I/O流
2.2 常见利用方式
- 修改_IO_read_ptr指向敏感数据区域实现信息泄露
- 修改_IO_write_ptr控制写入位置
- 伪造vtable实现控制流劫持
3. 实例分析:log_file攻击
3.1 漏洞分析
- 存在数组越界漏洞,可通过负数索引访问log_file结构体
- log_file是一个IO_FILE结构体,位于wizards数组前两个位置(wizards[-2])
- 可以修改log_file+40处(_IO_write_ptr)的位置
3.2 利用步骤
第一步:定位log_file地址
- 通过越界访问泄露log_file地址
- 计算关键指针的偏移量
第二步:控制IO_FILE结构体
- 修改_IO_buf_base指向目标区域
- 确保_IO_read_ptr > _IO_read_end以绕过检查
- 设置_IO_write_base和_IO_write_end覆盖目标区域
第三步:实现GOT表覆盖
- 将_IO_buf_base指向GOT表附近
- 通过写入操作修改GOT表项
- 本例中将atoi的GOT表项修改为system地址
第四步:触发shell
- 输入"sh"字符串
- 程序调用atoi("sh")实际执行system("sh")
4. 关键点总结
- 结构体布局:必须清楚IO_FILE结构体各字段的偏移量
- 指针关系:需要满足_IO_read_ptr < _IO_read_end等条件才能触发特定代码路径
- 写入控制:注意_IO_write_ptr会在写入后自动更新,需要精心设计写入位置
- 利用链构造:通常需要结合信息泄露和写原语完成完整利用
5. 防御措施
- 避免数组越界漏洞
- 对IO_FILE结构体关键字段进行保护
- 启用RELRO保护防止GOT表被修改
- 使用最新的glibc版本(修复了部分IO_FILE相关漏洞)
6. 扩展思考
- 如何在没有信息泄露的情况下利用IO_FILE结构体?
- 除了修改GOT表,还有哪些利用IO_FILE结构体的方式?
- 如何检测和防御IO_FILE结构体攻击?
通过深入理解IO_FILE结构体的内部机制,可以更好地防御此类攻击,同时在CTF比赛中能够快速识别和利用相关漏洞。