You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么scanf()仅在匹配指定文本后才读取输入?

为什么scanf()仅在匹配指定文本后才读取输入?

嘿,这个问题我当初刚接触scanf的时候也踩过坑,咱们结合你贴的CTF逆向代码来唠明白~

先把你那段代码整理成可读格式(看起来后面没贴完,但核心是这个scanf的用法):

int main(void) {
   int iVar1;
   char input[32];

   fwrite("Password: ",1,10,stdout);
   __isoc99_scanf("DoYouEven%sCTF",input);
   iVar1 = strcmp(input,"__dso_handle");
   if ((-1 < iVar1) && (iVar1 = strcmp(input,"__dso_handle"), iVar1 < 1)) {
     printf("Try again!");
     return 0;
   }
   // 剩余代码省略
}

本质上,scanf的格式串里,除了%s、%d这类格式说明符,其他普通字符都是「强制匹配项」。它的工作逻辑不是“跳过这些字符直接读变量”,而是:

  • 会从输入流里逐个字符比对这些普通文本,必须完全匹配(字符、顺序都不能错),才会继续处理后面的格式说明符。
  • 只有匹配完前面的DoYouEven之后,%s才会开始把后续的非空白字符读到input里;而且读完之后,scanf还会继续等着输入里出现CTF这三个字符,要是没匹配上,这次scanf操作就相当于失败了,input里的内容可能完全不是你预期的那样。

就拿这个CTF题来说,出题人就是故意挖了个坑:很多人看到要让input不等于__dso_handle(因为if里判断等于的话就输出Try again),可能直接输入__dso_handle,但实际上scanf根本不会把这个值读到input里——因为输入开头没有DoYouEven,scanf一直在等着匹配这个前缀,自然不会处理%s。

正确的输入得是DoYouEven__dso_handleCTF:

  1. 先匹配上DoYouEven,触发%s读取中间的__dso_handle到input;
  2. 最后匹配上末尾的CTF,整个scanf操作才算完成。

说白了,scanf设计成这样,就是为了支持「格式化输入匹配」——比如你要读取一个日期,写"%d/%d/%d",就要求输入必须是2024/10/01这种带/的格式,中间的/就是强制匹配项,少一个都不行,这样才能保证读入的是符合格式的日期数据。

这种用法在逆向CTF里特别常见,就是利用新手对scanf格式串的不熟悉,设下匹配陷阱,一不小心就踩坑~

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 12:48:07