Wargame/pwnable.kr

[Pwnable.kr] mistake 풀이 (1pt)

bjloed 2020. 7. 20. 23:14

풀이

문제 안읽고 그냥 냅다 풀다가 당했다

다음은 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;
 }

먼저 문제를 읽어보자.. 제발..

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

hint : operator priority

 

힌트가 연산자 우선순위다. 멍하니 코드를 10분 동안 바라보다가 이상한 부분을 찾았다. 검거!

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

먼저 연산자 우선순위 사진을 퍼와봤다.

if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0)

해당 코드에서는 fd 값에 open 함수의 리턴 값을 대입하는 게 먼저가 아니라 0과 비교하는 게 먼저 실행된다.

해당 파일에는 아무런 이상이 없으니 음수가 아닌 파일 디스크립터 값(음이 아닌 정수)을 반환한다.

그러므로 if(fd=[음이 아닌 정수] < 0)이고, 음이 아닌 정수와 0중 큰 값은 당연히 왼쪽 값이므로 false가 남게 된다.

즉, fd에는 false 값(0)이 대입된다.


그러면 fd에는 0이라는 값이 들어있음을 알았다.

if(!(len=read(fd,pw_buf,PW_LEN) > 0)){
        printf("read error\n");
        close(fd);
        return 0;
}

그렇다면 read(0, pw_buf, PW_LEN)이 되고, 0은 stdin이니 우리가 원하는 값을 pw_buf에 10칸만큼 넣을 수 있다.

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

결국, read로 읽은 값인 pw_buf와 우리가 입력할 값인 pw_buf2를 비교하는 것이기 때문에, xor(pw_buf2)와 pw_buf1이 같다면 문제가 해결될 것이다.