Я нашел эту строку в if.c версии unix версии 6.
ncom = "/usr/bin/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
Почему так много х? И почему вы это установили?
Я нашел эту строку в if.c версии unix версии 6.
ncom = "/usr/bin/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
Почему так много х? И почему вы это установили?
Код, о котором вы говорите, выглядит следующим образом:
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
равен нулю, и поэтому цикл запускается снова, переопределяя уже переопределенную строку снова и снова.
Нельзя переопределять не только локальные переменные, но и обратный адрес функции может стать чрезмерным, что приведет к "ошибке сегментации" или выполнению произвольного кода, который часто используется вредоносными программами.