6

假设我有两个程序 - input.c 和 output.c 我想要做的就是使用 execl() 函数将一些“半金字塔”格式的有效负载/字符发送到另一个程序中。

输入.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

#define SIZE 1024

int length;

int main(int argc, char *argv[])
{
    pid_t pid;
    char *target;
    //char payload[length+1];
    char payload[SIZE + 1];
    int status;
    int i = 0;

    if(argc < 2)
    {
        printf("Usage %s <length> <target>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    length = atoi(argv[1]);
    target = argv[2];

    while(i < length)
    {
        pid = fork();

        if(pid != 0)
        {
            waitpid(-1, &status, 0);
            //exit(0);
        }

        if(pid == 0)
        {
            payload[i] = 'A';
            payload[i + 1] = '\0';
            execl(target, target, payload, NULL);
            //printf("%s\n", payload);
        }
        ++i;
    }
    return 0;
}

注释段落仅用于调试目的。因为正如您所见(尝试时),当您只想打印它时,一切正常。

output.c(或者如果你想要' target.c ')

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char buffer[30];
    strncpy(buffer, argv[1], sizeof(buffer));
    printf("Output: %s\n", buffer);

    return 0;
}

当我像这样编译 input.c 时:

gcc input.c -o input

&输出.c:

gcc output.c -o output

好的。现在,一切都准备好了。假设,我想发送一个有效载荷 - 长度为 6

./input 6 ./output

但我得到的只是这个(或者只是用另一个垃圾字符):

Output: A
Output: 0A
Output: 0,A
Output: 0,�A
Output: 0,�8A
Output: 0,�8�A

我尝试了很多东西,但都失败了,输出仍然相同,如您在上面看到的。

如果有人可以帮助我并可能告诉我问题出在哪里,我将不胜感激。一起使用 fork() 和 execl() 函数会有问题吗?

4

2 回答 2

5

明白了,您不应该payload 子块代码中更新...

这是一个修复(现在无法测试):

 while(i < length)
    {
        pid = fork();
        payload[i] = 'A';
        payload[i + 1] = '\0';

        if(pid != 0)
        {
            waitpid(-1, &status, 0);
            //exit(0);
        }

        if(pid == 0)
        {
            execl(target, target, payload, NULL);
            //printf("%s\n", payload);
        }
        ++i;
    }

[删除无关的句子]

编辑(附加说明):payload更新必须在代码和子代码中。如果您不明白为什么,我可以添加更多解释。

EDIT2(根据要求)。您需要更新下一个分叉子进程的有效负载。在您的代码中,所有子代码都替换为execl()intotarget代码。因此,仅由第一个父进程(根进程)fork()执行。

您必须由第一个父级更新有效负载并使其也可以访问所有子级。将其放入此块中也不起作用:

// block only executed by the first parent.
if(pid != 0)
{
    waitpid(-1, &status, 0);
}

因此,您必须在父母和孩子都可以访问的地方更新它:在fork(), beforeif(pid == 0)块之后。

在您的代码中,您在公共块中递增i,但父块payload永远不会更新。因此,在子块中,就在 ' 之前,在未初始化的C 字符串的末尾execl()添加。A\0'

于 2015-04-16T16:29:49.350 回答
2

当您的程序分叉时,它会创建一个新进程。这个新进程,之后if(pid == 0),改变payload,并运行 exec (即执行output,然后死掉。即,您对有效负载的更改保留在子进程中,并且不会影响父进程。只有++i这样做,这就是为什么你看到 unialized数据。

在 fork 之前移动有效负载更改(或至少移出仅限子块),因此它也在父块中。

于 2015-04-16T16:31:17.303 回答