본문 바로가기

CTF_Write_UP/pwnable.kr

pwnable.kr : mistake 풀이

 

시작

안녕하세요 :D

passcode에 이어 오늘은 mistake를 들고 왔습니다.

10점짜리 풀다가 1점짜리 푸니깐 편-안하네요..ㅎㅎ..

시작해보겠습니다!

root@goorm:/workspace/LCH_Server# ssh mistake@pwnable.kr -p2222

Write UP

mistake@ubuntu:~$ ls -l
total 24
-r-------- 1 mistake_pwn root      51 Jul 29  2014 flag
-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

4개의 파일이 보입니다.

mistake 부터 실행해볼까요?

mistake@ubuntu:~$ ./mistake
do not bruteforce...
1234
input password : 1234
Wrong Password

입력을 하나 받고, 조금 기다리면 input password :라며 또 하나의 입력을 받습니다.

패스워드가 틀릴 경우 Wrong Password를 출력하네요.

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

정상적으로 프로그램이 작동하려면 다음과 같이 진행되어야 합니다.

  • fd 변수에 open 함수의 return 값이 들어간다. 그 후 fd0< 연산이 진행된다.

  • read 함수에 의해 pw_buf[] 배열에 /home/mistake/password의 내용이 저장된다.

하지만 MSDN의 연산자 우선순위를 보면 <, >=보다 높다고 하는군요.

때문에 이 프로그램은 다음과 같이 진행됩니다.

  • open 함수의 return값과 0< 연산이 먼저 이루어진다. 그 후의 값을 fd 변수에 대입한다.

  • open 함수는 정상적인 파일을 열었으므로 양수가 반환된다.

  • 양수 < 0의 결과는 0 이므로 fd 변수에 0, 즉 표준 입력 파일 디스크럽터가 들어간다.

결국 우리는 read 함수에서 fd0으로 넘겨주기 때문에 pw_buf[] 배열에

임의의 값을 PW_LEN 만큼 넣어줄 수 있게 됩니다!!

그 다음으로 pw_buf2[] 배열에 10 bytes 만큼 입력을 받고

xor 함수에 의해 pw_buf2[] 배열은 1XOR 연산됩니다.

이렇게 해서 나온 값이 pw_buf와 같다면 flag를 출력해주네요.

저는 pw_buf[]AAAAAAAAAA를 넣겠습니다.

AAAAAAAAAA1XOR한 값은 다음과 같네요.

mistake@ubuntu:/tmp$ cat xor.c
#include <stdio.h>

int main() {
        int i;
        char buf[11] = "AAAAAAAAAA";

        for (i = 0; i < 10; i++) {
                buf[i] ^= 1;
        }

        printf("%s\n", buf);

        return 0;
}

mistake@ubuntu:/tmp$ ./xor
@@@@@@@@@@

그대로 넣어주겠습니다.

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

마무리

파일 디스크립터를 많이 다루다 보니깐 조금씩 익숙해 지는군요..

MSDN의 연산자 우선순위도 배울 수 있었던 좋은 문제인 것 같습니다!!

다음 Write Up에서 뵙겠습니다! :D

 

'CTF_Write_UP > pwnable.kr' 카테고리의 다른 글

pwnable.kr : lotto 풀이  (0) 2019.04.17
pwnable.kr : shellshock 풀이  (0) 2019.04.16
pwnable.kr : passcode 풀이  (0) 2019.04.14
pwnable.kr : random 풀이  (0) 2019.04.13
pwnable.kr : bof 풀이  (0) 2019.04.13