无法理解格式字符串开发代码

Ter*_*nal 16 c

我碰到这个代码显示在阅读格式字符串利用文章.

#include <stdio.h>

int main(void)
{
char secret[]="hack.se is lame";
char buffer[512];
char target[512];

printf("secret = %pn",&secret);

fgets(buffer,512,stdin);
snprintf(target,512,buffer);
printf("%s",target);
}
Run Code Online (Sandbox Code Playgroud)

使用以下输入执行它

[root@knark]$ ./a.out
secret = 0xbffffc68
AAAA%x %x %x %x %x %x %x //Input given
AAAA4013fe20 0 0 0 41414141 33313034 30326566
- [root@knark]$ 
Run Code Online (Sandbox Code Playgroud)

到目前为止我所理解的是,序列%x将继续打印当前地址以上的值%esp(我假设堆栈向下朝向较低地址增长).

我无法理解的是给定的输入存储在buffer数组中,该数组不能小于当前的512字节%esp.所以,输出如何可以包含41414141(的十六进制表示AAAA)只是4之后%x,即,刚好高于当前的4个地址%esp.我也很努力地盯着汇编代码,但我想我无法跟踪堆栈上字符串的操作.

nin*_*alj 4

在进入 时snprintf,堆栈具有以下内容:

0xbfd257d0:     0xxxxxxxxx      0xxxxxxxxx      0xxxxxxxxx      0x080484d5
0xbfd257e0:     0xbfd25800      0x00000200      0xbfd25a00      0x00000000
0xbfd257f0:     0x00000000      0x00000000      0x00000000      0x00000000
0xbfd25800:     0x00000000      0x00000040      0xb7f22f2c      0x00000000
0xbfd25810:     0x00000000      0x00000000      0x00000000      0x00000000

0xbfd25800 -> target (initially 0x00000000 0x00000040 ...)
...        -> garbage
0xbfd257e8 -> pointer to buffer
0xbfd257e4 -> 512
0xbfd257e0 -> pointer to target
0xbfd257df -> return address
Run Code Online (Sandbox Code Playgroud)

targetsnprintf被before gets的结果覆盖,snprintf使用它的单词作为参数:它首先在 0xbfd25800 处写入“AAAA”(0x41414141),然后“%x”读取 0xbfd257ec 处的值并将其写入 0xbfd25804,...,然后“%” x”读取 0xbfd25800 (0x41414141) 处的值并将其写入 0xbfd25814,...