scanf源码分析

本文深入探讨了glibc2.31中scanf的相关源码,主要关注其在CTF场景下的利用方法,而非算法细节。分析了vfscanf的内部工作原理,包括如何根据格式字符串读取输入,以及当输入不匹配格式时的处理。重点讲解了inchar()、_IO_getc_unlocked(s)、__uflow()等关键函数,它们在流读取过程中的作用,最终指向系统调用read来获取数据。当利用scanf实现任意写时,需要控制_IO_buf_base并清空read缓冲区,而getchar()常用于辅助清空缓冲区。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文分析的是glibc2.31中的scanf相关源码,目的不是研究scanf的算法,而是说明scanf在IO attack中的利用方法,属于CTF的范畴

scanf.c

其实就是对__vscanf_internal的封装

__scanf (const char *format, ...)
{
  va_list arg;
  int done;

  va_start (arg, format);
  done = __vfscanf_internal (stdin, format, arg, 0);  //实际是对__vfscanf_internal的封装,arg指向可变参数
  va_end (arg);

  return done;
}
ldbl_strong_alias (__scanf, scanf)

vscanf-internal.c

  • 函数原型
int __vfscanf_internal(FILE *s, const char *format, va_list argptr, unsigned int mode_flags)
  • 原理:
    • 在vfscanf中有两个流:一个是指导读入格式的字符串流format,一个是被读入的流s
    • vfscanf先逐字符解析format,解析出一个要读入的格式后,就会调用inchar()从流s中逐字符读入
    • 例如format="%d%",输入"13\n"
      • vfcanf解析出%d后指导要从流s中读入一个十进制整数,于是调用inchar()得到字符'1',继续调用inchar()得到'2',再次调用inchar()得到字符'\n',vfscanf就知道一个整数已经结束了,就把'\n'放回流s中,然后把读入的"12"转化为int 12
      • 其余的同理
  • 总结:vfscanf与流的接口如下,搞CTF不需要了解这个解析算法是怎么实现的,因此下面专注于流相关调用过程
//向流s中放回一个字符c
#define ungetc(c, s) ((void)((int)c == EOF || (--read_in, \
											   _IO_sputbackc(s, (unsigned char)c))))
#define ungetc_not_eof(c, s) ((void)(--read_in, \
									 _IO_sputbackc(s, (unsigned char)c)))
//从流s中取出一个字符:c=_IO_getc_unlocked(s); ++read_in;
#define inchar() (c == EOF ? ((errno = inchar_errno), EOF)                  \
						   : ((c = _IO_getc_unlocked(s)),  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值