Github avatar

GyeongSu Han's Github Pages

Pwnable.kr mistake

Jul 23, 2016 · Wargame

문제는 다음과 같다.

#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;
}

password파일을 읽어 이 파일에 있는 값과 xor된 입력받은 값을 비교해 일치할 경우 해결되는 문제이다. hint : operator priority 인데, 17번째 줄을 보면 이유를 알 수 있다.

img1

사진 : Microsoft MSDN

이 표를 보게되면 대입 연산자는 우선순위에서 많이 늦게 실행되고, 비교연산자의 경우 대입보다 우선적으로 실행된다.

결과적으로 open의 결과와 0을 비교한 값을 fd에 넣어주게 된다. open의 결과는 정상적으로 열릴 경우 0이상의 값이 나오게 되므로, 저 조건문은 거짓이 된다.

그러므로 fd에는 0이 들어가게 된다.

0이 들어간 fd를 기준으로 모든 연산을 실행하게 되면, 0은 stdin이기 때문에 표준입력에서 password의 값을 가져오게 된다.

그러므로 사용자가 입력한 10개의 값과, scanf에 의해 입력받은 값을 비교하게 된다.

XOR키의 값은 1이기 때문에 모든 비트에서 가장 하위 비트만 1과 xor해주게 된다. 1이라는 문자를 16진수로 표현하면 110001인데, 이 값을 1과 xor하게 되면 110000이다. 이 값은 0이라는 문자의 값을 가지게 된다.

이를 기준으로 문제를 풀면 다음과 같다.

mistake@ubuntu:~$ ./mistake
do not bruteforce...
1111111111
0000000000
input password : Password OK
Mommy, the operator priority always confuses me :(