这个简单的代码令我感到困惑 - 我故意打印出比传递给printf更多的整数.我预计会出错.我得到了奇怪的数字 - 它们来自哪里?
#include <stdio.h>
/* learn arrays */
void main(){
    int pout;
    pout = 6;
    printf("%i %i %i\n%i %i %i\n%i %i %i\n", pout);
}
输出的一个例子:
6 608728840 0
-885621664 -885543392 608728816
0 0 -889304251
单个数字不会随着重复运行而改变,但是大整数会改变.
这是printf字符串格式漏洞之一.你试图调用比实际更多的参数,所以printf在堆栈上采取他能做的任何事情.
它(并且仍然)非常习惯于利用程序来探索堆栈以访问隐藏信息或绕过身份验证.
查看堆栈
Run Code Online (Sandbox Code Playgroud)printf ("%08x %08x %08x %08x %08x\n");这指示printf函数从堆栈中检索五个参数并将它们显示为8位填充的十六进制数字.所以可能的输出可能如下所示:
40012980 080628c4 bffff7a4 00000005 08059c04
见这更完整的解释.
因为它是未定义的行为.如果说明符的数量大于匹配参数的数量或它们的类型不兼容,则行为未定义.
这个qoute来自c11标准草案
7.21.6.1
fprintf功能
- 该
fprintf函数在format指向的字符串的控制下将输出写入stream指向的流,该格式指定后续参数如何转换为输出.如果格式的参数不足,则行为未定义.如果参数保留时格式已用尽,则会评估多余的参数(一如既往),否则将被忽略.遇到格式字符串的末尾时,fprintf函数返回.
- 如果转换规范无效,则行为未定义.282) 如果任何参数不是相应转换规范的正确类型,则行为未定义.
我强调了相关部分,使它们变得大胆.