【发布时间】:2019-08-25 11:29:41
【问题描述】:
我们每周对计算机系统漏洞进行一次测试,其中有以下问题:
以下函数是在 32 位 x86 系统上运行的程序的一部分;编译器不会改变栈上变量的顺序。
void function(char *input) {
int i = 1;
char buffer[8];
int j = 2;
strcpy(buffer,input);
printf("%x %x %s\n",i,j,buffer);
}
通过输入参数传递给函数的字符串的最小长度可以使应用程序崩溃?
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。上述问题的正确答案应该是什么?我如何知道可以使上述应用程序崩溃的字符串的最小长度?
【问题讨论】:
-
公平地说,我已经预料到 8 个字符会出现一些奇怪的行为。
-
它的开发人员有责任确保
buffer有足够的内存空间来存储input,否则会导致缓冲区溢出,进而导致未定义的行为。使用一种模式,例如它只允许将7字符复制到input。 -
我的意思是,在 8 个字符处,您已经在调用未定义的行为,因此问题和那些可能的答案一开始就没有多大意义。无论如何,您是否尝试过反编译您的可执行文件并检查它如何处理这些参数?另外,我会在编译器调用中添加
-O0以消除任何类型的优化。 -
"...可以使上述应用程序崩溃的最小字符串长度?" >7.它是否会崩溃取决于月球。
-
缓冲区为 8 个字节。在 C 中,字符串需要 1 个额外的字节来存储
0-终止符。所以存储在 8 个字节中的最大字符串长度是 8 个字节减去 1 个字节 = 7 个字节。额外的字节将被写入buffer的边界之外。在 C 中写出数组的边界会调用臭名昭著的未定义行为,从那时起任何事情都可能发生。