在分叉进程中调用 Execve 的问题
Issues Calling Execve In Forked Process
我正在尝试创建一个非常基本的 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
有可能在子进程中关闭管道也会在父进程中关闭它。考虑在 while 循环的开头移动你的 piper(pipe)。为了安全起见,在文件循环结束时关闭管道,不要忘记测试关闭的 return 值。
实际上 read
在输入的末尾放置一个换行符,因此您的命令可能是例如 testprog
但实际上,当使用 read()
时,它是 testprog\n
所以你必须摆脱添加的换行符,否则 execve()
将期望程序名称中包含换行符。
#define STDIN 0
int n = read(STDIN, command, 4096);
command[n - 1] = '[=10=]'; // get rid of newline
char *args = { command, NULL };
execve(buf, &args[0], NULL);
我正在尝试创建一个非常基本的 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
有可能在子进程中关闭管道也会在父进程中关闭它。考虑在 while 循环的开头移动你的 piper(pipe)。为了安全起见,在文件循环结束时关闭管道,不要忘记测试关闭的 return 值。
实际上 read
在输入的末尾放置一个换行符,因此您的命令可能是例如 testprog
但实际上,当使用 read()
时,它是 testprog\n
所以你必须摆脱添加的换行符,否则 execve()
将期望程序名称中包含换行符。
#define STDIN 0
int n = read(STDIN, command, 4096);
command[n - 1] = '[=10=]'; // get rid of newline
char *args = { command, NULL };
execve(buf, &args[0], NULL);