今回もリモート問題なので接続し、ソースコードを見てみると

長い。。。。

Stage5まであってそれぞれの値と比較してあってれば次のStageに行く感じ

そして、実際に値をいちいち入れるのは無理だから、ソースコードを書いて解いて行く

まず、ステージ1から

if(argc != 100) return 0;

    if(strcmp(argv['A'],"\x00")) return 0;

    if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0;

    printf("Stage 1 clear!\n"); 

だから

argcが100で、argv['A']には\x00

argv['B']には\x20\x0a\x0dが入っていればクリアらしい

まず、argv_hを100個作って、

argv['A']には\x00

argv['B']には\x20\x0a\x0d

そしてargv[100]にはNULLを入れる(C言語の配列の一番最後にはNULL)

セッティングが終わったらexecveシステムコールで実行ファイルのパスとセッティングしたargv_hを渡す。

そして、実行して見ると

ステージ1はクリア!!

ステージ2は

char buf[4];

    read(0, buf, 4);

    if(memcmp(buf, "\x00\x0a\x00\xff", 4)) return 0;

    read(2, buf, 4);

        if(memcmp(buf, "\x00\x0a\x02\xff", 4)) return 0;

    printf("Stage 2 clear!\n");

ステージ2がどうすればいいか分からなくて色々検索したらpipeを使えばいいと書いてあったので

pipeについて勉強もできた!!

簡単に言うとpipe関数を使うとプロセス間通信ができるということだ

順番に説明すると

1.両方向通信のために二つのpipeを作る

2.childプロセスを生成する

3.子プロセスはwriteは要らないからwriteを閉じて、read側を0(stdin)と2(stderr)に割り当てる

4.execveシステムコールでchildプロセスをinputプロセスに変える

4.親プロセスはreadは要らないからreadを閉じて、write側にクリア条件の値を書いてあげる

で、実行したら

ステージ2までクリア!!

次は、ステージ3

if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return 0;

    printf("Stage 3 clear!\n");

これは、execveシステムコールに環境変数を設定して渡せばOK!

childプロセスのexecveに追記して、実行すると

ステージ3もクリア!!

次はステージ4

FILE* fp = fopen("\x0a", "r");

    if(!fp) return 0;

    if( fread(buf, 4, 1, fp)!=1 ) return 0;

    if( memcmp(buf, "\x00\x00\x00\x00", 4) ) return 0;

    fclose(fp);

    printf("Stage 4 clear!\n");   

これは"\x0a"というファイルに"\x00\x00\x00\x00"を書いて置けばOKっぽい!

下から4番目からが追記したもの!

ファイルをオープンしてwriteで"\x00\x00\x00\x00"を書いてあげて、実行すると

ステージ4もクリア!!

次はステージ5

int sd, cd;

    struct sockaddr_in saddr, caddr;

    sd = socket(AF_INET, SOCK_STREAM, 0);

    if(sd == -1){

        printf("socket error, tell admin\n");

        return 0;

    }

    saddr.sin_family = AF_INET;

    saddr.sin_addr.s_addr = INADDR_ANY;

    saddr.sin_port = htons( atoi(argv['C']) );

    if(bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0){

        printf("bind error, use another port\n");

            return 1;

    }

    listen(sd, 1);

    int c = sizeof(struct sockaddr_in);

    cd = accept(sd, (struct sockaddr *)&caddr, (socklen_t*)&c);

    if(cd < 0){

        printf("accept error, tell admin\n");

        return 0;

    }

    if( recv(cd, buf, 4, 0) != 4 ) return 0;

    if(memcmp(buf, "\xde\xad\xbe\xef", 4)) return 0;

    printf("Stage 5 clear!\n");

ソースコードをみると

saddr.sin_port = htons( atoi(argv['C']) ); ここでargv['C']の値を設定するから

任意の番号をargv['C']に設定して、ソケットに"\xde\xad\xbe\xef"を書いてあげれば良い

int sock; からが追記したソースコードだ

これで、実行するとステージ5までクリアはできるけど、flagが出力されない。。。

調べたら、現在の経路(実行ファイルがあるところ/home/input2には権限がないため、/tmp/私が作ったフォルダーの中)

にはflagファイルがないためだという。。

解決方法はシンボルリンクを作ればOKだという記事をみたので

やってみたらflagが出力された!!

でも、スクリーンショット取るの忘れた。。