答案 0 :(得分:29)
您所谈论的代码如下所示:
ncom = "/usr/bin/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
while(c=nargv[0][i]) {
ncom[9+i++] = c;
}
ncom[9+i] = '\0';
所有这些x都充当缓冲区,它们被以下循环覆盖。
因此,代码有效地将“/ usr / bin /”添加到nargv[0]
中的命令。
有了更多的上下文,代码就是这样做的:
execv(nargv[0], nargv, np);
execv(ncom+4, nargv, np);
execv(ncom, nargv, np);
如果nargv[0]
中的给定命令为"foo"
,它将首先尝试运行"foo"
,然后"/bin/foo"
,最后"/usr/bin/foo"
。
请注意,以上是如何不执行此类操作的一个很好的示例:
如果nargv[0]
中的字符串恰好比x的字符串长,代码将很乐意继续复制数据。这将覆盖堆栈的其他部分。结果是缓冲区溢出的一个很好的例子。 (您分配一些大小的缓冲区并写入比分配的数据更多的数据。)
此示例将演示此问题:
#include <stdio.h>
int main(){
char s[]="abcde";
int i;
for(i=0;i<100;i++){
printf("position %2d contains value %3d\n",i,s[i]);
s[i]=0;
}
puts(s);
return 0;
}
如果你运行它,它(很可能)会输出:
position 0 contains value 97
position 1 contains value 98
position 2 contains value 99
position 3 contains value 100
position 4 contains value 101
position 5 contains value 0
position 6 contains value 0
position 7 contains value 0
position 8 contains value 0
position 9 contains value 0
position 10 contains value 0
position 11 contains value 0
position 12 contains value 12
position 1 contains value 0
position 2 contains value 0
position 3 contains value 0
position 4 contains value 0
position 5 contains value 0
position 6 contains value 0
position 7 contains value 0
[...]
它将用零填充字符串(包含ASCII值97到101)并继续写入内存,它将找到变量i
的位置,它也将其设置为零。现在i
为零,因此循环再次启动,一次又一次地覆盖已经重写的字符串。
不仅可以覆盖局部变量,还可以覆盖函数的返回地址,从而导致“分段错误”或执行任意代码,这通常被恶意软件使用。