6

たとえば、input.c と output.c という 2 つのプログラムがあるとします。実行したいのは、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

& output.c:

gcc output.c -o output

Ok。これですべての準備が整いました。たとえば、長さ 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;
    }

【無関係な文章を削除】

EDIT (追加説明) :更新は、親コードと子コードの両方payloadで行う必要があります。理由がわからない場合は、さらに説明を追加できます。

EDIT2 (要求に応じて)。次のフォークされた子プロセスのペイロードを更新する必要があります。コードでは、すべての子コードがコードに置き換えられexecl()ますtarget。そのため、最初の親プロセス(ルートプロセス) によってのみfork()実行されます。

最初の親でペイロードを更新し、すべての子からもアクセスできるようにする必要があります。このブロックに入れても機能しません:

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

したがって、親と子の両方がアクセスできる場所で更新する必要があります: after fork()、 beforeif(pid == 0)ブロック。

コードでは、共通ブロックをインクリメントiしますが、親のブロックpayloadは更新されません。したがって、子ブロックの の直前に、初期化されていないC 文字列の末尾にexecl()' を追加します。A\0'

于 2015-04-16T16:29:49.350 に答える