我当然知道它曾经用于输出带参数的指针。
我读过迈克尔·霍华德和戴维·勒布朗的书写安全代码
书中的一个程序演示了strcpy()
的堆栈溢出如何工作
注意printf()
,不带参数。
#include <stdio.h>
#include <string.h>
void foo(const char* input)
{
char buf[10];
//What? No extra arguments supplied to printf?
//It's a cheap trick to view the stack 8-)
//We'll see this trick again when we look at format strings.
printf("My stack looks like:\n%p\n%p\n%p\n%p\n%p\n% p\n\n");
//Pass the user input straight to secure code public enemy #1.
strcpy(buf, input);
printf("%s\n", buf);
printf("Now the stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n\n");
}
void bar(void)
{
printf("Augh! I've been hacked!\n");
}
int main(int argc, char* argv[])
{
//Blatant cheating to make life easier on myself
printf("Address of foo = %p\n", foo);
printf("Address of bar = %p\n", bar);
if (argc != 2)
{
printf("Please supply a string as an argument!\n");
return -1;
}
foo(argv[1]);
return 0;
}
结果是
C:\Secureco2\Chapter05>StackOverrun.exe Hello
Address of foo = 00401000
Address of bar = 00401045
My stack looks like:
00000000
00000000
7FFDF000
0012FF80
0040108A <-- return address
00410EDE
Hello
Now the stack looks like:
6C6C6548 <-- 'l','l','e','h'
0000006F <-- 0, 0, 0, 'o'
7FFDF000
0012FF80
0040108A
00410EDE
printf("%p")
内部代码是什么意思?为什么它可以打印堆栈的内容?
[通常,%p
是format specifier to print the pointer(地址值),期望的参数是指向void
类型的指针。
也就是说,在您的代码中,
printf("My stack looks like:\n%p\n%p\n%p\n%p\n%p\n% p\n\n");
是undefined behaviour。根据标准中的printf()
描述,如果提供的格式的参数不足,则为UB。
引用标准C11
,第7.21.6.1章
[...]如果格式的参数不足,则行为为未定义。 。[...]
代码段对产生任何有效输出的保证为零。
printf("Now the stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n\n");
的行为是未定义,因为您的参数列表与输入字符串不匹配。
作者推测,这种对printf
的特定滥用将注入当前堆栈中的变量,并输出其地址。有时它们可能是正确的。其他时候,编译器可能会吃掉你的猫。
正如其他人所说,这是不确定的行为。
这意味着它将以特定格式打印输出。对于参数“%p”,它将以系统的内存地址格式(8位,十六进制)打印。