"在/ usr/bin中/ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ;?

Joe*_*oey 20 c command

我在unix版本6 的if.c中找到了这一行.

ncom = "/usr/bin/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
Run Code Online (Sandbox Code Playgroud)

为什么有那么多x?你为什么要这样设置?

mic*_*has 29

您正在谈论的代码如下所示:

ncom = "/usr/bin/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
while(c=nargv[0][i])  {
    ncom[9+i++] = c;
}
ncom[9+i] = '\0';
Run Code Online (Sandbox Code Playgroud)

所有这些x都充当缓冲区,它们被以下循环覆盖.因此代码有效地将"/ usr/bin /"添加到命令中nargv[0].

有了更多的上下文,代码就是这样做的:

execv(nargv[0], nargv, np);
execv(ncom+4, nargv, np);
execv(ncom, nargv, np);
Run Code Online (Sandbox Code Playgroud)

如果给定的命令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;
}
Run Code Online (Sandbox Code Playgroud)

如果你运行它将(很可能)输出:

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
[...]
Run Code Online (Sandbox Code Playgroud)

它将用零填充字符串(包含ASCII值97到101)并继续写入内存,它将找到变量的位置,i它也将它设置为零.现在i为零,因此循环再次启动,一次又一次地覆盖已经被重写的字符串.

不仅可以覆盖局部变量,还可以覆盖函数的返回地址,从而导致"分段错误"或任意代码的执行,这通常由恶意软件使用.

  • 虽然这里的`ncom`代码不是一个好的防御性编程的例子,但实际上字符串对于正确使用该程序的用户来说足够长,因为在V6中,你永远不需要运行一个无路径名的命令(一个没有命令名称中的某个'/'字符,长度超过14个字符,因为这是目录中条目最长的一个.使用不当,我想它会覆盖`libc`使用的数据. (6认同)
  • 更不用说,`ncom`指向一个*字符串文字*然后被修改 - 在现代C中是一个很大的禁忌,其中字符串文字通常存储在只读存储器中. (5认同)
  • 数字是字符串中的位置:"/ usr"是4个字符."/ usr/bin /"是9个字符. (4认同)
  • 如果我们<strike>需要</ strike>试图运行名称超过35个字符的命令怎么办? (3认同)
  • 为什么+9和+4?谢谢michas :) (2认同)
  • 是的,这是一个很好的例子,如何**不**做这样的事情,因为这会产生缓冲区溢出.(答案更新.) (2认同)