Проблемы, вызывающие Execve в Forked Process - PullRequest
0 голосов
/ 13 апреля 2019

Я пытаюсь создать очень простой сервер telnet, чтобы практиковать эксплойты с повреждением памяти. Когда я пытаюсь выполнить команду, на первой итерации ничего не происходит. Вторая итерация. Я получаю несколько ошибок печати файловых дескрипторов на моей стороне сервера. На стороне клиента все вроде бы нормально. Я получаю все необходимые подсказки. Вот мой соответствующий код:

int piper[2];
pipe(piper);

...

     while (1) {
        n = write(newsockfd,"Enter a command...\n",21);
                if (n < 0) error("ERROR writing to socket");
                bzero(buffer,4096);
                n = read(newsockfd,buffer,4095);
                strcpy(command, buffer);
                pid_t childpid;
                childpid = fork();
                if(childpid == -1) {
                    perror("Failed to fork");
                    return 1;
                }
                if(childpid == 0) { //child
                    printf("I am child %ld\n", (long)getpid());
                    if(dup2(piper[1], 1) < 0) {
                        perror("Failed to pipe in child process");
                    }
                    else {
                        close(piper[0]);
                        close(piper[1]);
                        char *args[] = {command, NULL};
                        execve(command, args, NULL);
                    }
                }
                else { // parent
                    if(dup2(piper[0], 0) < 0) {
                        perror("Failed to pipe in parent process");
                    }
                    else {
                        // read command output from child
                        while(fgets(command_out, sizeof(command_out), stdin)) {
                            printf("%s", command_out);
                        }
                    }
                }
            }

Если я ввожу /bin/ls в мой клиент, на моем сервере выводится следующее:

I am child 26748

Во второй раз, когда я это делаю, на сервер выводится следующее:

Failed to pipe in parent process: Bad file descriptor

0I am child 26749

Failed to pipe in child process: Bad file descriptor

1 Ответ

2 голосов
/ 13 апреля 2019

Существует вероятность, что закрытие канала в дочернем процессе также закрывает его в родительском процессе. Подумайте о перемещении вашего пайпера (трубы) в начале цикла while. И для безопасности закройте канал в конце файлового цикла, не забывая проверить возвращаемое значение close.

На самом деле read ставит символ новой строки в конце ввода, чтобы ваша команда могла быть, например, testprog, но на самом деле, при использовании read(), это testprog\n, поэтому вы должны избавиться от новой строки добавлено или execve() будет ожидать имя программы с новой строкой.

#define STDIN 0
int n = read(STDIN, command, 4096);
command[n - 1] = '\0';   // get rid of newline

char *args = { command, NULL };
execve(buf, &args[0], NULL);
...