I am studying for my Computer Security exam and I am on the Format String Bugs section. In the notes there is this code, and I was testing it on my VM:
#include <stdio.h>
void test(char *arg) {
char buf[256];
snprintf(buf, 250, arg);
printf("buffer: %s\n", buf);
}
int main (int argc, char *argv[]) {
test(argv[1]);
return 0;
}
Now, the goal is to print the stack content upside the snprintf()
call, so I always run it as follows:
$ ./vuln "AAAA %x %x %x"
What I am expecting is printing three hex values on the stack, as what I have understood is that the stack would be in this state when executing snprintf
:
HIGH STACK ADDRESSES
|----------------------|
| stuff | %x
|----------------------|
| stuff | %x
|----------------------|
| stuff | %x
|----------------------|
| &"AAAA %x %x %x" |
|----------------------|
| 250 |
|----------------------|
| &buf[0] |
|----------------------|
LOW STACK ADDRESSES
Now, here is what I am really struggling to understand: at every run, the output is this:
buffer: AAAA 41414141 34313420 34313431
Why does it print the 41414141 (AAAA in hex)?! wasn't the format string supposed to be a pointer? If it is a pointer to argv[]
, it should be at the start of the stack before main()
, not in the frame stack of test()
!
I really can't understand if I'm missing something or if it is a coincidence (but I don't think so, because in the slides there's also this output)
I'm compiling this code in a VM with ASLR disabled and this flags:
gcc -O0 -mpreferred-stack-boundary=2 -ggdb -march=i386 -m32 -fno-stack-protector -no-pie -z execstack vuln.c -o vuln.o
I tried to run it in gdb but I before the snprintf()
the stack is full of 0s and just after the call the buffer is filled with 41414141 34313420 34313431. Where is it catching this values from?
Base on the format string vulnerability code, the reason you're seeing 41414141
(which is "AAAA" in hex) maybe is because the format string itself is being processed by snprintf()
. When you pass "AAAA %x %x %x"
as the format string, the first %x
reads the address where the format string is stored on the stack, which contains your "AAAA" input.
To exploit this and read actual stack content above the snprintf()
call, you may need to use more %x
placeholders to walk up the stack. Try running it with more format specifiers like: ./vuln "AAAA %x %x %x %x %x %x %x %x"
to see different stack values.
The key insight is that snprintf(buf, 250, arg)
treats arg
as the format string, so each %x
reads from the stack starting from where the format string pointer is located.