我在阅读 this 时看到这段显示格式字符串利用的代码文章。
#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);
}
使用以下输入执行它
[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]$
到目前为止我的理解是 %x
的序列将继续打印当前 %esp
以上地址的值(我假设堆栈是向低地址向下增长)。
我无法理解的是给定的输入存储在 buffer
数组中,该数组距离当前 %esp
不能少于 512 字节。那么,输出如何在 4 个 %x
之后包含 41414141
(AAAA
的十六进制表示),即在 4 个地址之上当前 %esp
。我也努力盯着汇编代码看,但我想我无法理解堆栈上的字符串操作。
最佳答案
在进入 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
target
在 snprintf
开始使用其单词作为参数之前被 snprintf
的结果覆盖:它首先写入“AAAA”(0x41414141 ) 在 0xbfd25800,然后“%x”读取 0xbfd257ec 的值并将其写入 0xbfd25804,...,然后“%x”读取 0xbfd25800(0x41414141)的值并将其写入 0xbfd25814,...
关于c - 无法理解格式字符串利用代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6930352/