gpt4 book ai didi

c - 可能使某些应用程序崩溃的字符串的最小长度

转载 作者:太空狗 更新时间:2023-10-29 15:56:31 24 4
gpt4 key购买 nike

我们每周都会进行一次计算机系统漏洞测试,测试题如下:

The below function is part of a program that is running on a 32-bit x86 system; the compiler does not change the order of variables on the stack.

void function(char *input) {
int i = 1;
char buffer[8];
int j = 2;
strcpy(buffer,input);
printf("%x %x %s\n",i,j,buffer);

}

What is the minimum length of a string passed to the function through the input parameter that can crash the application?

a)10 b)11 c)12 d)13

我写了一个 main 函数来调用 void function(... 并使用 gcc -m32 test.c -o test 编译程序,因为我在 64 位计算机上。下面是主要功能:

int main(int argc, char *argv[]) {
function(argv[1]);
return 1;
}

并使用输入进行测试:

~/Dir:./test 1234567
1 2 1234567
~/Dir:./test 12345678
1 2 12345678
~/Dir:./test 123456789
1 2 123456789
*** stack smashing detected ***: <unknown> terminated
Aborted (core dumped)

一旦我输入 123456789 作为参数,就会检测到堆栈粉碎,所以这个问题的答案应该是 9 但没有选择 9 的选项。上面问题的正确答案应该是什么?我如何知道可以使上述应用程序崩溃的最小字符串长度?

最佳答案

你会得到 9 个字符的“Stack smashing detected”,因为你的编译器确实对堆栈上的变量重新排序。 GCC 可以,即使在 -O0。为防止这种情况,请将变量放在一个结构中。

#include <stdio.h>
#include <string.h>
struct variables {
int i;
char buffer[8];
int j;
};
void function(char *input) {
struct variables s;
s.i = 1;
s.j = 2;
strcpy(s.buffer, input);
printf("%x %x %s\n", s.i, s.j, s.buffer);
}
int main(int argc, char *argv[]) {
function(argv[1]);
return 0;
}

在关闭优化的情况下编译它,否则编译器很可能会优化 s 本身。

$ ./a.out 1234567                    
1 2 1234567
$ ./a.out 12345678
1 0 12345678
$ ./a.out 123456789
1 39 123456789
$ ./a.out 1234567890
1 3039 1234567890
$ ./a.out 1234567890a
1 613039 1234567890a
$ ./a.out 1234567890ab
1 62613039 1234567890ab
$ ./a.out 1234567890abc
1 62613039 1234567890abc
*** stack smashing detected ***: <unknown> terminated
[2] 6086 abort (core dumped) ./a.out 1234567890abc

现在您可以看到发生了什么。最多 7 个字符,加上空终止符,该字符串适合 8 字节缓冲区。对于 8 个字符,字符串开始溢出到内存中的下一个内容,即 j。在 32 位小端机器上,组成 j 的字节的值为 {0x02, 0x00, 0x00, 0x00}。对于 8 到 11 个字符,字符串逐渐接管 j

在 12 个字符处,空终止符会覆盖内存中 s 之后的任何内容。在我的测试中,内存中的这个字节的值恰好为 0,因此没有发生比覆盖 j 更糟糕的事情。在 13 个字符处,字符串 c 的最后一个字符覆盖该字节,堆栈保护检测到该字节,因为该字节实际上是堆栈金丝雀的一部分。

在我的构建中,导致崩溃的字符数是 13。但是,这是因为 j 之后恰好有一个空字节。鉴于练习的假设,可能使应用程序崩溃所需的字符数为12。此时,strcpy 调用会写入函数的本地存储,这可能是一个未映射的地址。

为了视觉引用,这是 strcpy 调用之前内存的内容:

+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| 01 | 00 | 00 | 00 | ?? | ?? | ?? | ?? | ?? | ?? | ?? | ?? | 02 | 00 | 00 | 00 | 00 | ?? |
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
^-i ^-buffer ^-j ^-stack canary

如果我用 gcc -O0 -fno-stack-protector 编译,它需要 21 个字节才能在我的平台上实际导致崩溃,大概是因为这是覆盖返回地址所需要的。练习(我没看过,我不知道它有多难):借助调试器并借助汇编代码和一些 x86 ABI 文档,找出其中的内容(帧指针?对齐间隙?)。

关于c - 可能使某些应用程序崩溃的字符串的最小长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57645610/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com