使用fgetc冲破全缓冲
字数 1682 2025-08-29 22:41:01
利用fgetc冲破全缓冲区的技术分析
背景介绍
在二进制安全领域,缓冲区溢出攻击是常见的技术手段。本文档将详细分析如何利用fgetc函数冲破全缓冲区(full buffering)的技术细节,这种技术在CTF比赛(如XYCTF2025中的Ret2libc's Revenge题目)中有着实际应用。
问题描述
在题目Ret2libc's Revenge中,攻击者面临以下挑战:
- 需要泄露libc地址但无法直接控制足够多的寄存器
- 传统的缓冲区溢出方法(如塞满缓冲区)在远程环境中失效
- 无法直接调用
setvbuf或fflush来刷新缓冲区
传统方法及其局限性
方法1:修改main函数返回地址
- 通过覆盖
libc_start_call_main后的返回地址 - 需要爆破,成功概率为1/4096
- 本地ASLR开启时可成功,但无法执行
cat /flag
方法2:使用ELF gadget控制rdi并调用puts
- 控制rdi寄存器后调用
puts泄露libc地址 - 写入0x3e个
call puts的gadget塞满缓冲区 - 本地可行但远程失败,原因可能是缓冲区大小不同
方法3:尝试控制setvbuf
- 需要控制4个参数(rdi, rsi, rdx, rcx)
- 无法控制rdx和rcx寄存器,难以实现
fgetc刷新缓冲区的技术原理
fgetc函数的工作流程
-
初始检查:
if (fp->_IO_read_ptr >= fp->_IO_read_end)当文件指针的读取位置超过或等于读取结束位置时,会进入
__uflow函数 -
__uflow函数:
- 调用
_IO_switch_to_get_mode - 检查
fp->_IO_write_ptr > fp->_IO_write_base - 如果条件成立,进入
_IO_OVERFLOW
- 调用
-
_IO_OVERFLOW宏:
#define _IO_OVERFLOW(FP, CH) JUMP1 (__overflow, FP, CH)实际调用stdout vtable中的
__overflow函数,即_IO_new_file_overflow
_IO_new_file_overflow的关键逻辑
-
标志位检查:
f->_flags = 0xfbad2884_IO_NO_WRITES = 0x8f->_flags & _IO_NO_WRITES = 0→ 进入下一分支
-
当前写入状态检查:
(f->_flags & _IO_CURRENTLY_PUTTING) = 0x800f->_IO_write_base != NULL- 进入
if (ch == EOF)分支(因为rsi=0xffffffff)
-
关键调用:
_IO_do_write(f, f->_IO_write_base, f->_IO_write_ptr - f->_IO_write_base);
_IO_do_write和后续调用链
-
_IO_do_write:
- 调用
new_do_write - 最终调用
_IO_SYSWRITE(即_IO_file_write)
- 调用
-
_IO_file_write:
- 调用
__write(f->_fileno, data, to_do) - 实际执行write系统调用,输出缓冲区内容
- 调用
技术实现要点
-
控制流要求:
- 控制rdi寄存器指向stdout
- 调用
fgetc@plt
-
优势:
- 不需要知道缓冲区具体大小
- 不需要构造大量gadget塞满缓冲区
- 简洁高效,可靠性高
-
适用场景:
- 当无法直接调用
fflush时 - 当缓冲区大小未知或不可预测时
- 当寄存器控制有限时(只需控制rdi)
- 当无法直接调用
实际应用示例
在Ret2libc's Revenge题目中,攻击者可构造如下利用链:
- 找到控制rdi的gadget
- 将rdi设置为stdout地址
- 调用
fgetc@plt - 此时stdout缓冲区会被刷新,泄露其中的libc地址
- 基于泄露的地址构造后续ROP链
总结
通过深入分析fgetc函数的内部实现,我们发现它可以通过以下路径间接刷新stdout缓冲区:
fgetc → __uflow → _IO_switch_to_get_mode → _IO_OVERFLOW → _IO_new_file_overflow → _IO_do_write → _IO_file_write → write系统调用
这种方法相比传统技术具有以下优势:
- 不依赖缓冲区大小
- 不需要构造复杂的ROP链
- 只需控制rdi寄存器即可实现
- 在远程环境中可靠性更高
这种技术展示了深入理解库函数内部实现对于二进制漏洞利用的重要性,为CTF比赛和实际安全研究提供了新的思路。