C Tim Newsham格式字符串攻击
我正在阅读关于格式字符串漏洞的文章,发现一开始有些部分很难理解 正在讨论下列方案C Tim Newsham格式字符串攻击,c,security,exploit,format-string,C,Security,Exploit,Format String,我正在阅读关于格式字符串漏洞的文章,发现一开始有些部分很难理解 正在讨论下列方案 /* * fmtme.c * Format a value into a fixed-size buffer */ #include <stdio.h> int main(int argc, char **argv) { char buf[100]; int x; if(argc != 2) exit(1); x = 1; s
/*
* fmtme.c
* Format a value into a fixed-size buffer
*/
#include <stdio.h>
int
main(int argc, char **argv)
{
char buf[100];
int x;
if(argc != 2)
exit(1);
x = 1;
snprintf(buf, sizeof buf, argv[1]);
buf[sizeof buf - 1] = 0;
printf("buffer (%d): %s\n", strlen(buf), buf);
printf("x is %d/%#x (@ %p)\n", x, x, &x);
return 0;
}
该报说:
"A quick analysis of the program will reveal that the stack layout of the
program when the snprintf function is called is:
Address Contents Description
fp+8 Buffer pointer 4-byte address
fp+12 Buffer length 4-byte integer
fp+16 Format string 4-byte address
fp+20 Variable x 4-byte integer
fp+24 Variable buf 100 characters
The four values output in the previous test were the next four arguments on
the stack after the format string: the variable x, then three 4-byte
integers
taken from the uninitialized buf variable."
这里的fp
是什么?文件指针
为什么它是从fp+8开始的,而不是从fp+4开始的,当增量为4时,其他地方(4字节地址)
在这里,地址越大,表示该值在堆栈上越高还是越低
“目录”下的名称是什么意思
当我运行上述程序时,
x
,即1
,的值没有被打印出来。也许是因为不同的建筑
我是这样的
./fmtme "%x %x %x %x"
buffer (34): cd512860 b3356d80 b3356d80 8247ee8
x is 1/0x1 (@ 0x7ffc08247d8c)
有人能帮忙吗?
代表“帧指针”fp
- 参数从
开始,因为fp+8
是返回地址,fp+4
是保存的帧指针fp+0
- 在x86使用的传统向下扩展堆栈中,较高的地址在堆栈中越深(先前推送的项)
内容有点不清楚-它试图描述堆栈槽中的内容,但其中一些没有名称。这可能更清楚:
Address Contents Description
fp+8 First snprintf argument pointer 4-byte address
fp+12 Second snprintf argument length 4-byte integer
fp+16 Third snprintf argument string 4-byte address
fp+20 Variable x in main 4-byte integer
fp+24 Variable buf in main 100 characters
您看不到相同的结果,因为这些类型的东西——形式上未定义的行为——对您使用的体系结构、编译器和编译器版本高度敏感。从用%p
打印的指针值可以看出,您使用的是64位体系结构-如果您使用的是x86-64,那么函数的前6个整型参数将在寄存器中传递,而不是在堆栈中传递,因此,这就是伪%x
格式开始查找的地方。您可以尝试使用-m32
编译器选项为x86编译,但没有任何保证。
fp
代表“帧指针”
- 参数从
fp+8
开始,因为fp+4
是返回地址,fp+0
是保存的帧指针
- 在x86使用的传统向下扩展堆栈中,较高的地址在堆栈中越深(先前推送的项)
内容有点不清楚-它试图描述堆栈槽中的内容,但其中一些没有名称。这可能更清楚:
Address Contents Description
fp+8 First snprintf argument pointer 4-byte address
fp+12 Second snprintf argument length 4-byte integer
fp+16 Third snprintf argument string 4-byte address
fp+20 Variable x in main 4-byte integer
fp+24 Variable buf in main 100 characters
您看不到相同的结果,因为这些类型的东西——形式上未定义的行为——对您使用的体系结构、编译器和编译器版本高度敏感。从用%p
打印的指针值可以看出,您使用的是64位体系结构-如果您使用的是x86-64,那么函数的前6个整型参数将在寄存器中传递,而不是在堆栈中传递,因此,这就是伪%x
格式开始查找的地方。您可以尝试使用-m32
编译器选项为x86进行编译,但没有任何保证。@user3386109我们能以某种方式将旧的体系结构与新的体系结构联系起来吗?如果这就是不同之处?@user3386109我们能以某种方式将旧架构与新架构联系起来吗?如果这是不同之处的话?我是架构概念的新手。您是如何从用%p
打印的地址看出我使用的是64位体系结构机器的?我发现snprintf()
的参数是从右向左推的,这有点奇怪。如果给出更多的参数,它们将出现在“格式”和“变量x”之间。但是为什么snprintf()
读取“缓冲区”并进行跟踪?这不匹配。我怀疑这是作者的一个错误。@J…S:因为打印的指针值超过32位(而且我也认为它在Linux x86-64上的典型堆栈地址范围内)。@thebusybee:从右向左推参数是很常见的。这意味着您可以访问varargs函数中的所有参数,而不必知道它们有多少(因为第一个参数始终位于函数项上堆栈指针的已知偏移量处,就在返回地址之后)@thebusybee:非常清楚地展示了从右到左的论点推进。我是架构概念的新手。您是如何从用%p
打印的地址看出我使用的是64位体系结构机器的?我发现snprintf()
的参数是从右向左推的,这有点奇怪。如果给出更多的参数,它们将出现在“格式”和“变量x”之间。但是为什么snprintf()
读取“缓冲区”并进行跟踪?这不匹配。我怀疑这是作者的一个错误。@J…S:因为打印的指针值超过32位(而且我也认为它在Linux x86-64上的典型堆栈地址范围内)。@thebusybee:从右向左推参数是很常见的。这意味着您可以访问varargs函数中的所有参数,而不必知道它们有多少个(因为第一个参数始终位于函数项上堆栈指针的已知偏移量处,就在返回地址之后)。@thebusybee:非常清楚地演示了从右到左推送参数。