IO FILE 之任意读写
字数 1975 2025-08-03 16:44:31
IO FILE 之任意读写技术详解
概述
本文详细分析如何利用IO FILE结构体中的缓冲区指针进行任意内存读写操作。主要内容包括:
- 使用stdin标准输入缓冲区进行任意地址写
- 使用stdout标准输出缓冲区进行任意地址读写
前置知识
在阅读本文前,建议先了解以下内容:
- IO FILE系列基础函数(fopen/fread/fwrite/fclose)的实现原理
- IO FILE的vtable劫持及FSOP技术
- 基本的堆利用知识
stdin标准输入缓冲区任意地址写
原理分析
通过控制输入缓冲区指针,使得输入缓冲区指向目标地址,在调用系统调用读取数据时实现任意地址写。
关键函数调用链:
fread -> _IO_file_xsgetn -> __underflow -> _IO_SYSREAD
必要条件
- 设置
_IO_read_end等于_IO_read_ptr - 设置
_flag &~ _IO_NO_READS(即_flag &~ 0x4) - 设置
_fileno为0(标准输入) - 设置
_IO_buf_base为write_start,_IO_buf_end为write_end - 确保
_IO_buf_end - _IO_buf_base大于fread要读的数据
实践案例:whctf2017 stackoverflow
-
漏洞利用:
- 通过未初始化的name变量泄露libc地址
- 存在溢出写'\x00'的漏洞
-
利用步骤:
- 利用溢出漏洞修改stdin结构体中的
_IO_buf_base指针 - 通过输入操作覆盖
_IO_buf_end为__malloc_hook+0x8 - 控制输入数据覆盖
__malloc_hook
- 利用溢出漏洞修改stdin结构体中的
-
关键点:
IO_getc函数用于刷新_IO_read_ptr- 使用ROP绕过one gadget限制
stdout标准输出缓冲区任意地址读写
任意写实现
原理
通过控制输出缓冲区指针,将可控数据拷贝至目标地址。
关键函数调用链:
fwrite -> _IO_new_file_xsputn -> memcpy
必要条件
- 设置
_IO_write_ptr指向write_start - 设置
_IO_write_end指向write_end
任意读实现
原理
控制输出缓冲区指针指向目标地址,构造条件使缓冲区"满",从而输出目标地址数据。
关键函数调用链:
fwrite -> _IO_new_file_xsputn -> _IO_OVERFLOW -> _IO_do_write -> _IO_SYSWRITE
必要条件
- 设置
_flag &~ _IO_NO_WRITES(即_flag &~ 0x8) - 设置
_flag & _IO_CURRENTLY_PUTTING(即_flag | 0x800) - 设置
_fileno为1(标准输出) - 设置
_IO_write_base指向read_start,_IO_write_ptr指向read_end - 设置
_IO_read_end等于_IO_write_base或设置_flag & _IO_IS_APPENDING(即_flag | 0x1000) - (可选)设置
_IO_write_end等于_IO_write_ptr
实践案例:hctf2018 babyprintf_ver2
-
漏洞利用:
- 存在溢出可以覆盖stdout结构体
- 无法覆盖vtable(有修正机制)
-
利用步骤:
- 构造stdout结构体实现任意读泄露libc地址
- 构造stdout结构体实现任意写修改
__malloc_hook - 通过
%n触发malloc调用one gadget
-
关键点:
- 需要设置
_flag | 0x8000(_IO_USER_LOCK)避免死锁 %n可以触发malloc(通过__readonly_area调用fopen)
- 需要设置
构造技巧与注意事项
-
flags字段构造:
- 最容易出错的部分
- 建议直接拷贝原始stdout/stdin结构体的flags进行修改
-
调试工具:
- 使用pwn_debug的
IO_FILE_plus模块 - 使用
arbitrary_write_check和arbitrary_read_check进行验证
- 使用pwn_debug的
-
常见问题:
- 忘记设置
_fileno - flags设置不正确导致流程分支错误
- 缓冲区大小计算错误
- 忘记设置
总结
IO FILE的任意读写技术是一种强大的利用方式,关键在于:
- 精确控制缓冲区指针
- 正确设置flags标志位
- 理解IO操作的内在流程
通过深入分析源码可以更好地掌握这些技术,建议读者结合具体案例进行实践练习。