input

문제

Mom? how can I pass my input to a computer program?

ssh [email protected] -p2222 (pw:guest)

소스

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(int argc, char* argv[], char* envp[]){
    printf("Welcome to pwnable.kr\n");
    printf("Let's see if you know how to give input to program\n");
    printf("Just give me correct inputs then you will get the flag :)\n");

    // argv
    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");    

    // stdio
    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");

    // env
    if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return 0;
    printf("Stage 3 clear!\n");

    // file
    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");    

    // network
    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");

    // here's your flag
    system("/bin/cat flag");    
    return 0;
}

취약점

힌트

  • stage 1:
  • stage 2:
  • stage 3:
  • stage 4:
  • stage 5:
  • script 작성시 홈폴더에는 저장이 안되므로 $mkdir /tmp/임의디렉토리명으로 디렉토리를 만들어서 스크립트를 짭니다.
  • 마지막에 임의디렉토리에는 flag 파일이 없는 것을 고려하여야 합니다.
  • 힌트 사이트 : https://werewblog.wordpress.com/2016/01/11/pwnable-kr-input/

공략

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

void main(void) {
    // for stage1
    char *argv[101]={"/home/input2/input", [1 ... 99] = "A", NULL};
    argv['A'] = "\x00";
    argv['B'] = "\x20\x0a\x0d";

    // for stage2
    int pipe2stdin[2] = {-1,-1};
    int pipe2stderr[2] = {-1,-1};
    pid_t childpid;

    // for stage3
    char *env[2] = {"\xde\xad\xbe\xef=\xca\xfe\xba\xbe", NULL};

    // for stage4
    FILE* fp = fopen("\x0a", "w");

    // for stage5
    int cd;
    struct sockaddr_in saddr;
    argv['C'] = "7777";


    // source
    // for stage4
    fwrite("\x00\x00\x00\x00", 1, 4, fp);
    fclose(fp);
    // for stage2
    if ( pipe(pipe2stdin) < 0 || pipe(pipe2stderr) < 0){
        perror("Cannot create the pipe");
        exit(1);
    }

    if ( ( childpid = fork() ) < 0 ){
        perror("Cannot fork");
        exit(1);
    }

    if ( childpid == 0 ){
        /* Child process */
        close(pipe2stdin[0]); close(pipe2stderr[0]); // Close pipes for reading
        write(pipe2stdin[1],"\x00\x0a\x00\xff",4);
        write(pipe2stderr[1],"\x00\x0a\x02\xff",4);

        // for stage 5
        saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
        saddr.sin_family = AF_INET;
        saddr.sin_port = htons(7777);
        printf("socket()\n");
        cd = socket(AF_INET, SOCK_STREAM, 0);
        if(-1 == cd)
        {
        printf("socket error!\n");
        exit(0);
        }
        printf("sleep()\n");
        sleep(1);
        printf("connect()\n");
        if(-1==connect(cd, (struct sockaddr *)&saddr, sizeof(saddr)))
        {
        printf("connect error!\n");
        exit(0);
        }
        printf("send()\n");
        send(cd, "\xde\xad\xbe\xef", 4, 0);
        printf("close(sd)\n");
        close(cd);
    }
    else {
        /* Parent process */
        close(pipe2stdin[1]); close(pipe2stderr[1]);   // Close pipes for writing
        dup2(pipe2stdin[0],0); dup2(pipe2stderr[0],2); // Map to stdin and stderr
        close(pipe2stdin[0]); close(pipe2stderr[1]);   // Close write end (the fd has been copied before)
        // for stage 1, 3
        execve("/home/input2/input", argv, env);  // Execute the program
    }
}

results matching ""

    No results matching ""