问题
I of course know it used to output pointer with arguments.
I read book Writing Secure Code by Michael Howard and David LeBlanc.
One program in book demonstrates how stack overflow works by strcpy()
Note printf()
without arguments.
#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;
}
The result is
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
What is the meaning of printf("%p")
inside code? Why it can print the content of stack?
回答1:
In general, %p
is a format specifier to print the pointer (address value), the argument expected is a pointer to void
type.
That said, in your code,
printf("My stack looks like:\n%p\n%p\n%p\n%p\n%p\n% p\n\n");
is undefined behaviour.
As per the printf()
description in the standard, if there are insufficient arguments for supplied format, it's UB.
To quote the standard, C11
, chapter §7.21.6.1
[...] If there are insufficient arguments for the format, the behavior is undefined. .[...]
The code snippet has zero guarantee to produce any valid output.
回答2:
The behaviour of printf("Now the stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n\n");
is undefined since your argument list does not match the inputted string.
The authors are conjecting that this particular misuse of printf
will inject variables from the current stack, and output their addresses. Sometimes they might be correct. Other times the compiler might eat your cat.
回答3:
As others have said, this is undefined behaviour.
But what you see seems to be an admittedly naive but "natural" thing. In most C implementation based on the call stack, function input arguments are pushed onto the stack by the caller, and popped[1] off the stack by the callee. In this particular case, the callee (printf
) seems to blindly pop successive pointer-sized elements, based on how many %p
formatting directives there are in the formatting string, without any form of checking. So instead of popping off the (absent) input arguments, it traverses the stack and "sees" what it's not supposed to see. But this is not always the case for other implementations.
[1] By "popping off" I don't mean destructively removing them from the stack; don't take it literally ;) Most likely what happens under-the-hood is that the input arguments are referenced by an offset from a pointer. But here apparently there's no constraint on how far this offset can get.
回答4:
It means it will print output in a specific format. In the case of parameter "%p" it will be printed in the memory address format for your system (8 digits, hexadecimal).
来源:https://stackoverflow.com/questions/31806193/what-is-the-meaning-of-printfp-without-arguments